javascript - Angular 4 show popup onclick by other component -
i'm struggling problem , can't figure out. need show popup div situated in page clicking menu entry in navbar.component.
i added property "show" in popup prints "show" class on div using ngclass (with if) directive. can working if action button inside popup component cannot print show class clicking on component. property in object updated class not printed. i'm using angular 4 ng-bootstrap. tried both services , parent/child emit event.
this is situation:
app.component.html
<app-nav-bar></app-nav-bar> <app-login></app-login> <router-outlet></router-outlet> <app-footer></app-footer>
navbar.component.html
... <button class="dropdown-item" (click)="showpopup()">login</button> ...
navbar.component.ts
import {component, eventemitter, input, oninit, output} '@angular/core'; @component({ moduleid: module.id, selector: 'app-nav-bar', templateurl: 'navbar.component.html', styleurls: ['./navbar.component.css'], }) export class navbarcomponent implements oninit { @output() show = new eventemitter<boolean>(); ngoninit() { } showpopup() { this.show.emit(true); } }
login.component.html
<div id="wrapper-login-popup" class="fade-from-top" [(class.show)]="show"> <div id="container-login-popup"> <div class="row"> <div class="col-sm-12 text-center"> <img id="popup-bomb" src="assets/images/bomb.png" alt="bomb"/> <img id="popup-close" class="close-icon" src="assets/images/close.png" alt="close" (click)="closepopup()"/> </div> </div> </div> </div>
login.component.ts
import {component, input, oninit} '@angular/core'; import {authservice} '../services/auth.service'; import {iuser} './user'; @component({ selector: 'app-login', templateurl: 'login.component.html', styleurls: ['login.css'] }) export class logincomponent implements oninit { private username: string; private password: string; @input() show: boolean = false; constructor(private authservice: authservice) { } ngoninit() { } login() { ... } showpopup() { console.log(this); //show false this.show = true; console.log(this); //show true not trigger show class } closepopup() { this.show = false; } }
the issue here nav-bar , login components siblings , can't directly communicate each other. have show output of navbar , input of login, haven't connected dots.
you need update app.component connect them.
export class appcomponent implements oninit { show = false; onshow() { this.show = true; } }
and in template:
<app-nav-bar (show)="onshow()"></app-nav-bar> <app-login [(show)]="show"></app-login>
there's lot of 2 way binding going on here works simple liek this, it's bad idea leads unmaintainable code. should choose 1 owner of show variable , force changes through him. in case app component logical owner, i'd change login component emit event changes show variable in app component adn remove 2 way bindings, in bigger app, may want separate service manages hiding/showing pop ups. eliminates need sending message , down component tree, can inject service it's needed.
as commenter mentioned, should using ngclass class manipulation
[ngclass]="{'show':show}"
a service based solution like
import {subject} 'rxjs/subject'; @injectable() export class popupservice { private showpopupsource = new subject(); showpopup$ = this.showpopupsource.asobservable(); showpopup() { this.popupsource.next(true); } closepopup() { this.popupsource.next(false); } }
then provide in app module or @ app component level:
providers:[popupservice]
make sure don't re provide later, want 1 copy exist shares it.
then inject both components, , have them call services close or show pop methods.
then in login component bind popup$ observable like
constructor(private popupsvc:popupservice){} show$; ngoninit() { this.show$ = this.popupsvc.showpopup$; } showpopup() { this.popupsvc.showpopup(); } closepopup() { this.popupsvc.closepopup(); }
and in template subscribe w async pipe like
<div id="wrapper-login-popup" class="fade-from-top" [ngclass]="{'show': (show$ | async) }">
the reason using async pipe garbage collection managemetn simpler. if don't use async, need garbage collect manually in ngondestroy calling unsubscribe(), otherwise subscriptions keep stacking up. there more nuanced benefit in async pipe triggers change detection, becomes important if start using onpush change detection performance optimization.
Comments
Post a Comment