Angular 4通过其他组件显示弹出onclick [英] Angular 4 show popup onclick by other component

查看:39
本文介绍了Angular 4通过其他组件显示弹出onclick的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为这个问题而苦苦挣扎,无法弄清楚. 我只需要在navbar.component中的菜单项中单击,在页面中显示一个弹出div.

i'm struggling about this problem and can't figure out. I simply need to show a popup div situated in the page clicking from a menu entry in my navbar.component.

我在弹出窗口中添加了一个属性"show",该属性使用ngClass(with if)指令在div上打印"show"类.如果操作按钮位于弹出式组件的内部,我可以使此按钮正常工作,但是我无法打印单击另一个组件的显示类.对象中的属性会更新,但不会打印该类.我在ng-bootstrap中使用angular 4.我同时尝试了服务和父/子发射事件.

I added a property "show" in my popup which prints the "show" class on my div using the ngClass (with if) directive. I can get this working if the action button is inside my popup component but i cannot print the show class clicking on another component. The property in the Object get updated but the class is not printed. I'm using angular 4 with ng-bootstrap. I tried both with services and with parent/child emit event.

这是我的情况:

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} from '@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} from '@angular/core';
import {AuthService} from '../services/auth.service';
import {IUser} from './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 is false
        this.show = true;
        console.log(this); //Show is true but does not trigger the show class
    }

    closePopup() {
        this.show = false;
    }
}

推荐答案

此处的问题是您的导航栏和登录组件是同级组件,无法直接相互通信.您已将其显示为navbar的输出和登录的输入,但尚未连接所有点.

The issue here is that your nav-bar and login components are siblings and can't directly communicate with each other. You have show as an output of navbar and as an input of login, but you haven't connected the dots.

您需要更新app.component才能连接它们.

You need to update your app.component to connect them.

export class AppComponent implements OnInit {
    show = false;
    onShow() { this.show = true; }
}

并在模板中:

<app-nav-bar (show)="onShow()"></app-nav-bar>
<app-login [(show)]="show"></app-login>

这里有很多两种方式进行绑定,这对于一些简单的事情很有效,但是通常这是一个坏主意,因为它会导致代码无法维护.您应该选择一个show变量的所有者,并通过他强制对其进行所有更改.在这种情况下,应用程序组件是最符合逻辑的所有者,因此我将更改登录组件以发出一个事件,该事件会更改应用程序组件中的show变量并删除所有2种方式的绑定,但是在更大的应用程序中,您甚至可能需要单独的服务,用于管理隐藏/显示弹出窗口.这样就无需在组件树上下发送消息,您可以将服务注入到需要的地方.

There's a lot of two way binding going on here which works for something simple liek this, but generally it's a bad idea as it leads to unmaintainable code. You should choose one owner of the show variable and force all changes to it through him. In this case the app component is the most logical owner, so I'd change the login component to emit an event that changes the show variable in app component adn remove all 2 way bindings, but in a bigger app, you may even want a separate service that manages hiding/showing pop ups. This eliminates the need for the sending a message up and down your component tree, you can inject the service where it's needed.

正如另一位评论者所述,您还应该使用ngClass进行类操作,例如

As another commenter mentioned, you also should be using ngClass for class manipulation like

[ngClass]="{'show':show}"

基于服务的解决方案看起来像

a service based solution would look like

import {Subject} from '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 you provide in app module or at app component level:

providers:[PopUpService]

请确保您以后不再提供此副本,因为您只希望存在一个副本,以便所有人共享.

make sure you don't re provide this later, as you only want one copy to exist so everyone shares it.

然后注入这两个组件,并让它们调用服务关闭或显示弹出方法.

then inject into both components, and have them call the services close or show pop up methods.

然后在登录组件中将您绑定到可观察到的popUp $

then in the login component you bind to the popUp$ observable like

constructor(private popUpSvc:PopUpService){}
show$;
ngOnInit() { this.show$ = this.popUpSvc.showPopUp$; }
showPopUp() { this.popUpSvc.showPopUp(); }
closePopUp() { this.popUpSvc.closePopUp(); }

,并在模板中订阅w之类的异步管道

and in the template subscribe w async pipe like

<div id="wrapper-login-popup" class="fade-from-top" [ngClass]="{'show': (show$ | async) }">

使用异步管道的原因是垃圾收集管理更简单.如果您不使用异步,则需要通过调用unsubscribe()在ngOnDestroy中手动进行垃圾收集,否则您的订阅将不断堆积.还有一个更细微的好处,那就是异步管道触发了更改检测,但这仅在您开始使用onPush更改检测进行性能优化时才变得重要.

The reason for using the async pipe is garbage collection managemetn is simpler. If you don't use async, you need to garbage collect manually in ngOnDestroy by calling unsubscribe(), otherwise your subscriptions will keep stacking up. There is also a more nuanced benefit in that the async pipe triggers change detection, but this only becomes important if you start using onPush change detection for performance optimization.

这篇关于Angular 4通过其他组件显示弹出onclick的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆