2
votes

This is another quick regarding how to handle this little pattern. I want to update a variable in my parent component which has been assigned a value from a centralized service which will hold my data so I can share it across my whole application. I am using Angular2.alpha46 build using typescript.

Take the following :)

Main.ts:

import {Component, CORE_DIRECTIVES, Observable, Input, bootstrap} from 'angular2/angular2';
import {RouteConfig, RouterLink, ROUTER_DIRECTIVES} from 'angular2/router';
import {Routes,  APP_ROUTES} from './core/route.config';
import {UserService} from "./shared/service/user.service";
import {InMenu} from './shared/pipe/inmenu.pipe';

@Component({
    selector: 'Main',
    providers: [],
    templateUrl: './app/main.html',
    directives: [ROUTER_DIRECTIVES, CORE_DIRECTIVES, RouterLink],
    pipes: [InMenu]
})

@RouteConfig(APP_ROUTES)

export class Main {
    routes = APP_ROUTES;
    loggedIn: Boolean;

    constructor(private UserService: UserService) {
        this.loggedIn = UserService.isLoggedIn();
    }
}

main.html (part of it where my loggedIn variable is bound)

<header>
    <span>LOGGED IN STATUS: {{loggedIn}}</span>
</header>

user.service.ts (simplified)

import {Inject} from 'angular2/angular2';
import {Http, HTTP_BINDINGS, Headers} from 'angular2/http';
import {ROUTER_BINDINGS} from 'angular2/router';
import {User} from '../../model/user.model';

export class UserService {

    private user: User;
    private loggedIn: Boolean;

    constructor(@Inject(Http) private http:Http) {
    }

    getLoggedInUser() {
        return this.user;
    }

    isLoggedIn() {
        return this.loggedIn;
    }

    login(user: User) {
        var postData = "email=" + user.email + "&password=" + user.password;

        this.headers = new Headers();
        this.headers.append('Content-Type', 'application/x-www-form-urlencoded');

        return this.http.post('/auth/local', postData, {
                headers: this.headers
            })
            .map((res:any) => {
               // Update variable!!!!
               this.loggedIn = true;

               return this.handleResponse(res);
            });
     }

}

So from a child component I would call the userService method login which changes the loggedIn boolean to be true.

child component (where I call the service method)

import {Component, CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2';
import {UserService} from '../../shared/service/user.service';
import {Router} from 'angular2/router';
import {User} from '../../model/user.model';
import {APP_ROUTES, Routes} from '../../core/route.config';

@Component({
    selector: 'login-form',
    templateUrl: 'app/login/components/login-form.component.html',
    directives: [CORE_DIRECTIVES, FORM_DIRECTIVES]
})

export class LoginFormComponent{
    user: User;
    submitted: Boolean = false;
    errorMessage = null;

    constructor(private userService:UserService, private router: Router) {
        this.user = new User();
    }

    onLogin() {
        this.submitted = true;

        this.userService.login(this.user)
            .subscribe(
                data => {},
                err => {}
            );
    }
}

I'd expect the parent view to update accordingly but this isnt the case (obviously)

What is the best solution to essentially force a "digest" (like angular 1) to re-render and update the parent view or to detect a variable that is shared centrally that is changed from a child component? EventEmitters?

thanks again!

1
still cant find a solution for this with build 46 :) - Nige

1 Answers

3
votes

I would add an Observer for loggedIn in the UserService and make the components subscribe to changes to that one.

export class UserService {
    this.loggedIn$ = new Observable(observer => {
        this._loggedInObserver = observer;
    }).share();

    login(user: User) {
    var postData = "email=" + user.email + "&password=" + user.password;

    this.headers = new Headers();
    this.headers.append('Content-Type', 'application/x-www-form-urlencoded');

    return this.http.post('/auth/local', postData, {
            headers: this.headers
        })
        .map((res:any) => {
           this._loggedInObserver.next(true);

           return this.handleResponse(res);
        });
    }
}

Then in your components just subscribe to the new observer:

userService.loggedIn$.subscribe(loggedIn => {
   // Update local value
});