Angular2 – Sharing data between two components

angular-2-tutorialAngular2 is a fully component driven framework. Each component has its own html template where you can bind the data to this template through the respective component.

What if you need to share some data within two component? May be you need to modify the same data/variable inside multiple components.

For example,inside both navBarComponent and AppComponent, we need to change the header text of the nav bar.

First you need to write a service for storing data as angular Observebles.

import { Injectable } from '@angular/core';
import { Observable,Subject } from 'rxjs/Rx';

// lessonService to be shared within the application
@Injectable()
export class TestService {

  constructor() { }

    // Observable string sources
  private selectedTestSource = new Subject<string>();

  // Observable string streams
  selectedTestSource$ = this.selectedTestSource.asObservable();

  // Service message commands
  setSelectedTestItem(param: string) {
    this.selectedTestSource.next(param);
  }

}

Now inject this service into Component 1.


@Component({
  selector: 'app-sidenav',
  templateUrl: './sidenav.component.html',
  styleUrls: ['./sidenav.component.css']
})
export class SidenavComponent implements OnInit {

  constructor(private testService:TestService) { }

  ngOnInit() {
  }

changeTest(testId:string){
  this.testService.setSelectedTestItem(testId);
}
}

Now access this value inside the other component using a  subscriber.

import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

export class AppComponent implements OnDestroy {

constructor(private testService:TestService) {
this.subscription = testService.selectedTestSource$.subscribe(
testId=&gt;{
// add your code here
});
}

ngOnDestroy() {
// prevent memory leak when component destroyed
this.subscription.unsubscribe();
}

}

 

Advertisements
Categories: Angular2

Angularjs Routing – Angular1 vs Angular2

Before we start and to make sure we are in line on the terminology, I will use the name AngularJS to define AngularJS 1.x and Angular2 to define AngularJS 2.x.

AngularJS

To enable Hash (#) urls,  set the following configuration. This will shift within two nodes.(HTML5 enable mode or not)

$locationProvider.html5Mode(true);

Angular2

In Angular2 , same modes are called as PathLocationStrategy and HashLocationStrategy

PathLocationStrategy is the default strategy which is used by Angular2. This is equivalent to HTML5 mode in AngularJS.

import {ROUTER_PROVIDERS, APP_BASE_HREF} from 'angular2/router';
 
bootstrap(yourApp, [
  ROUTER_PROVIDERS, // includes binding to PathLocationStrategy
  provide(APP_BASE_HREF, {useValue: '/my/prefix/here'})
]);

HashLocationStrategy will add hash fragment to URL.

import {ROUTER_PROVIDERS, LocationStrategy, HashLocationStrategy} from 'angular2/router';  // works only for rc6 ,
// for others  import { ROUTER_PROVIDERS } from '@angular/router-deprecated';
 //  import {LocationStrategy,HashLocationStrategy }from '@angular/common';
bootstrap(yourApp, [
  ROUTER_PROVIDERS,
  provide(LocationStrategy, {useClass: HashLocationStrategy})
]);

Define Routes

AngularJS

$stateProvider.state('home', {
    url: '/',
    templateUrl: 'home.html',
    controller: 'HomeCtrl'
}).state('about', {
    url: '/about',
    templateUrl: 'about.html',
    controller: 'AboutCtrl'
})

Angular2

import {RouteConfig, Route} from 'angular2/router';
import {MyComponentHome, MyComponentAbout} from './myComponents';
@Component({
    selector: "app"
})
@RouteConfig([
    new Route({ path: '/', component: MyComponentHome, name: 'Home' }),
    new Route({ path: '/about', component: MyComponentAbout, name: 'About' })
])
export class App {...}

Template Update

AngularJS

<body>
    <ui-view>
        <i>Some content will load here!</i>
    </ui-view>
</body>

Angular2

import {RouterOutlet} from 'angular2/router';
@Component({
    selector: "app"
})
@View({
    directives: [RouterOutlet]
    template: `
      <router-outlet></router-outlet>
    `
})

Navigate through views

AngularJS

<a ui-sref="home">Home page</a>
<a ui-sref="about">About page</a>

Angular2

import {RouterLink} from 'angular2/router';
@Component({
  selector: "menu",
  directives: [RouterLink],
  template: `
     <a [routerLink]="['./Home']">Home page</a>
     <a [routerLink]="['./About']">About page</a>
  `
})
export class Menu {...}

Thymeleaf + print session variable on page

Use these code snippet to add session data to html/jsp page without touching ANY java code.


<h4 style="color: white;" th:text="${#ctx.httpSession.id}">SessionID </h4>

 

Categories: Thymeleaf

jQuery Autocomplete example with Spring MVC

First create Spring REST controller to process the request.


@RestController
@RequestMapping(value = "/json")
public class RESTController
{

@ResponseBody
@RequestMapping(value = "/city", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Response<List<SearchBean>> getStateList( @RequestParam("term") String term, Locale locale )
{

Response<List<SearchBean>> returnResponse = null;
List<City> cityList = null;
List<SearchBean> suggestCityList = null;
String cityName = "";
SearchBean searchBean = null;
try
{
cityList = new ArrayList<City>();
suggestCityList = new ArrayList<SearchBean>();
cityList = Data.getCityList( locale );  // load city Objects list

for ( City city : cityList )
{
cityName = city.getName();
if ( ( cityName.toLowerCase( locale ).startsWith( term.toLowerCase( locale ) )   )
{
searchBean = new SearchBean();
searchBean.setLabel( cityName );
suggestCityList.add( searchBean );
}
}
returnResponse = new Response<>( suggestCityList, "", Response.SUCCESS );
}
catch ( CustomGenericException e )
{
// TODO: handle exception

returnResponse = new Response<>( null, "", Response.ERROR );
}
return returnResponse;

}

}

SearchBean class is just a pojo class with two parameters.

now , initialize the autocomplete function.


function loadSmartkeySuggestion(element,_url,minLength,dataType){$(element).autocomplete({

source: function( request, response ) {
$.ajax({
url:_url ,
dataType: dataType,
data: {
term: request.term
},
success: function( data ) {
if(data.status == 1) // if data is available
response( data.data );
}
});
},
minLength: minLength

});}

Categories: jQuery, Spring Tags:

Eclipse cannot connect to marketplace

 

download

If you are using windows 8, you might have come up with this issue. After hours of Googling, finally found a solution for this.

  1. Open your eclipse.ini file.
  2. Add following parameter in the bottom and save.

-Djava.net.preferIPv4Stack=true

3.Restart Eclipse.

Categories: Uncategorized

Spring Security : Basic Http Authentication

Suppose we need to create an API which requires user authentication to access that. Spring security is there to implement this on the fly.

First create your REST service

Service.java


@RestController
@RequestMapping("/api")
public class Service
{
private static final Logger LOGGER = LoggerFactory.getLogger( Service.class );

/**
* Clear the template cache
*
* @return response object with status and message
*/
@ResponseBody
@RequestMapping(value = "/foo", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Response<String> accessApi()
{
Response<String> returnResponse = null;
try
{

returnResponse = new Response<String>( "", "Successfull", Response.SUCCESS );
}
catch ( Exception )
{
// TODO: handle exception
returnResponse = new Response<String>( "", "Error", Response.ERROR );
LOGGER.error( ex.getMessage() );
}

return returnResponse;
}

}

Now create security config class.


@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{

@Autowired
MyBasicAuthenticationEntryPoint myBasicAuthenticationEntryPoint;

@Autowired
public void configureGlobal( AuthenticationManagerBuilder auth ) throws Exception
{
auth.inMemoryAuthentication().withUser( "user" ) // #1
.password( "password" ).roles( "USER" );
}

@Override
protected void configure( HttpSecurity http ) throws Exception
{
// @formatter:off
http
.authorizeRequests()
.antMatchers("/api/foo").hasRole("USER")
.anyRequest().permitAll()
.and()
.httpBasic()
.authenticationEntryPoint( myBasicAuthenticationEntryPoint );
// @formatter:on
}

}

Now add bean to MvcConfig class.


@Bean
public MyBasicAuthenticationEntryPoint myBasicAuthenticationEntryPoint()
{
return new MyBasicAuthenticationEntryPoint();
}

Then add SecurityConfig class to WebAppInitializer.


public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
@Override
protected Class<?>[] getRootConfigClasses()
{
return new Class<?>[] {SecurityConfig.class };
}

}

Then add


public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer
{

}

Now create entry point.


import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;

public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint
{

@Override
public void commence( final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException ) throws IOException, ServletException
{
response.setHeader( "Access-Control-Allow-Origin", "*" );
response.setHeader( "Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE" );
response.setHeader( "Access-Control-Max-Age", "3600" );
response.setHeader( "Access-Control-Allow-Headers", "x-requested-with" );

response.addHeader( "WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\"" );
response.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
final PrintWriter writer = response.getWriter();
writer.println( "HTTP Status " + HttpServletResponse.SC_UNAUTHORIZED + " - " + authException.getMessage() );
}

@Override
public void afterPropertiesSet() throws Exception
{
setRealmName( "FooService" );
super.afterPropertiesSet();
}
}

Now redirect to http:localhost/example/api/foo URL will request your credentials.

Angularjs + Spring MVC: Remove # from url

AngularJs is mainly used for developing  Single Page Applications (SPA). So different views are loaded to single html on different user actions. The typical URL of AngularJs application is as following.

Default URL : http://localhost:8080/SampleApp/

User Info : http://localhost:8080/SampleApp/#/User

What if you need to remove hash from url and make it SEO friendly.

You need to change both client side and server side configurations for this.

Client side.

Add following to app.js where you have defined the routing.


$locationProvider.html5Mode(true);

Now set base folder in your index.html

 <base href="/SampleApp/index.html"></base> 

Now add the Server side configuration. Its just adding URL mapping and changing the routing.

 @RequestMapping(value = { "/User" }, method = RequestMethod.GET)
public ModelAndView redirectPage(ModelAndView modelAndView ) throws ServletException, IOException
{
RedirectView view = new RedirectView( "redirect:" + "/" );
view.setExposeModelAttributes( false );
return new ModelAndView( view );
}

 

Categories: angularjs, Spring MVC