Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular 2 service subscription only updates after second click on component with routerLink(s)

Angular 2.0 rc 5, router version 3.0.0 rc1

I have an angular 2 app that uses a service to communicate between components, a parent component that has a <router-outlet> and a child component that has routerLinks. I am using NgClass to update css classes for animations. I added the service so that NgClass updates when I click one of the router links, in addition to changing <router-outlet> output. However I was only able to get the NgClass to update after clicking on the routerLinks twice. Clicking the same routerLink or different ones doesn't matter, as long as it's clicked twice the subscription updates.

page behavior gif

My parent component's .ts :

import {Component} from '@angular/core';
import {NgClass} from '@angular/common';
import {NavService} from 'components/nav.service';
import {Subscription} from 'rxjs/Subscription';
import {ButtonComponent} from 'components/button.component';
import {MenuComponent} from 'components/menu.component';
import {CardContainerComponent} from 'components/cardcontainer.component';

@Component({
    selector: 'juan',
    templateUrl: 'app/components/app.component.html',
    directives: [ NgClass ,ButtonComponent, MenuComponent, CardContainerComponent],
    providers: [NavService]
})
export class AppComponent {
    isPushed = false;
    subscription: Subscription;
    public initiatePush(){
        this.isPushed = !this.isPushed;
    }
    constructor(private navService: NavService){
        this.subscription = this. navService.navToggle$.subscribe(
            isPushed => {
                this.isPushed = isPushed;
            }
        )   
    }
}

the parent component's .html:

<div class="frame" [ngClass]="{'pushed' : isPushed}">

    <div id="o-wrapper" class="o-wrapper">
        <div class="menu">

        </div>
        <div class="menu-cover">
        </div>
        <animated-button (triggerer)="initiatePush($event)"></animated-button>

    </div>
    <router-outlet></router-outlet>
    <div class="footer"><p class="credit">by <a href="mailto:[email protected]?Subject=Site%20query" class= "email-link">Juan Asher</a></p></div>
    <div id="c-mask" class="c-mask" [ngClass]="{'is-active' : isPushed}"></div>
    <main-menu></main-menu>
</div>

the service .ts:

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

@Injectable()
export class NavService{
    private navToggleSource = new Subject<boolean>();
    navToggle$ = this.navToggleSource.asObservable();
    toggleNav(isPushed: boolean) {
        this.navToggleSource.next(isPushed);
    }
}

the child component .ts :

import {Component} from '@angular/core';
import {SlidingButtonComponent} from './sliding-button.component';
import {NgClass} from '@angular/common';
import {NavService} from './nav.service';

@Component({
    selector: 'main-menu',
    templateUrl: 'app/components/menu.component.html',
    directives: [SlidingButtonComponent, NgClass],
    providers: []
})
export class MenuComponent {
    isSlided = false;
    isClicked = false;
    public initiateSlide(){
        this.isSlided = !this.isSlided;
    }
    constructor(private navService: NavService) {}
    public toggleFocus(){
        this.isClicked = !this.isClicked;
        this.navService.toggleNav(this.isClicked);  
    }
}

Child component's .html:

<nav class="c-menu">
    <ul class="c-menu__items">
        <li class="c-menu__item"><a (click)="toggleFocus()" class="c-menu__link" routerLink="/card-container" routerLinkActive="active">Home</a></li>
        <li class="c-menu__item"><sliding-button (slider)="initiateSlide($event)"></sliding-button></li>
    </ul>
</nav>
<div class="login-slider" [ngClass]= "{'is-slided' : isSlided}">
    <div class="slider-content">
        <input type="email" class="input-field" placeholder="Email Address">

        <input type="password" class="input-field" placeholder="Password">  
        <button type="submit" class="button button-block">Login</button>
    </div>
    <div class="slider-tab">
        <ul class="c-menu__items">
            <li class="c-menu__item"><a (click)="toggleFocus()" class="c-menu__link last-item" routerLink="/join" routerLinkActive="active">Join</a></li>
        </ul>
    </div>
</div>

Do I need to implement some lifecycle hook to make this work?

Update 20/08/2016

@KrishnrajRana did you mean this?

constructor(private navService: NavService){}

ngOnInit() { 
    this.subscription = this. navService.navToggle$.subscribe(
        isPushed => {
            this.isPushed = isPushed;
        }
    )   
}

I tried that, it is still having the same behavior.

like image 254
bleaknight Avatar asked Aug 19 '16 04:08

bleaknight


1 Answers

Ah this is a simple logic mistake on my end, I needed a false boolean to make my class go away, however I switched my boolean to true before triggering the service method, hence the next action sets the sent boolean to false, making the class disappear.

export class MenuComponent {
    isSlided = false;
    isClicked = false;
    public initiateSlide(){
        this.isSlided = !this.isSlided;
    }
    constructor(private navService: NavService) {}
    public toggleFocus(){
        this.isClicked = !this.isClicked;
        this.navService.toggleNav(this.isClicked);  
    }
}

changed to

export class MenuComponent {
    isSlided = false;
    isClicked = false;
    public initiateSlide(){
        this.isSlided = !this.isSlided;
    }
    constructor(private navService: NavService) {}
    public toggleFocus(){
        this.navService.toggleNav(this.isClicked);  
    }
}
like image 135
bleaknight Avatar answered Oct 15 '22 01:10

bleaknight