我正在为这个问题苦苦挣扎,无法弄清楚。 我只需要显示位于页面中的弹出 div,单击 navbar.component 中的菜单条目即可。
我在弹出窗口中添加了一个属性“show”,它使用 ngClass(带有 if)指令在我的 div 上打印“show”类。如果操作按钮位于我的弹出组件内,我可以使其工作,但我无法单击另一个组件来打印显示类。对象中的属性得到更新,但类没有打印。我正在使用 Angular 4 和 ng-bootstrap。我尝试了服务和父/子发出事件。
这是我的情况:
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;
}
}
最佳答案
这里的问题是您的导航栏和登录组件是兄弟组件,无法直接相互通信。您已将显示作为导航栏的输出和登录的输入,但尚未将这些点连接起来。
您需要更新您的 app.component 才能连接它们。
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>
这里有很多两种方式的绑定(bind),它们适用于简单的事情,但通常这是一个坏主意,因为它会导致无法维护的代码。您应该选择一个显示变量的所有者,并通过他强制对其进行所有更改。在这种情况下,应用程序组件是最合乎逻辑的所有者,因此我将更改登录组件以发出一个事件,该事件会更改应用程序组件中的显示变量并删除所有 2 路绑定(bind),但在更大的应用程序中,您甚至可能需要一个管理隐藏/显示弹出窗口的单独服务。这消除了在组件树上上下发送消息的需要,您可以在需要的地方注入(inject)服务。
正如另一位评论者提到的,您还应该使用 ngClass 进行类操作,例如
[ngClass]="{'show':show}"
基于服务的解决方案看起来像
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); }
}
然后您在应用程序模块或应用程序组件级别提供:
providers:[PopUpService]
确保您稍后不会重新提供此信息,因为您只希望存在一份副本,以便每个人都共享它。
然后注入(inject)两个组件,并让它们调用服务关闭或显示弹出方法。
然后在登录组件中绑定(bind)到 popUp$ 可观察的
constructor(private popUpSvc:PopUpService){}
show$;
ngOnInit() { this.show$ = this.popUpSvc.showPopUp$; }
showPopUp() { this.popUpSvc.showPopUp(); }
closePopUp() { this.popUpSvc.closePopUp(); }
并在模板中订阅 w 异步管道
<div id="wrapper-login-popup" class="fade-from-top" [ngClass]="{'show': (show$ | async) }">
使用异步管道的原因是垃圾收集管理更简单。如果您不使用异步,则需要通过调用 unsubscribe() 在 ngOnDestroy 中手动进行垃圾收集,否则您的订阅将不断堆积。还有一个更细微的好处,即异步管道会触发更改检测,但只有当您开始使用 onPush 更改检测来优化性能时,这一点才变得重要。
关于javascript - Angular 4显示其他组件单击时的弹出窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45677139/