我试图将数据从子组件传递到父组件,从子组件传递到父组件的变量值,不幸的是,父组件中没有进行任何更改。知道是怎么回事吗?或者@Output装饰器严格地只适用于子组件中的点击事件?我也会期望,它并不重要,如果我使用方法eventemitter或不,所以,例如设置emit为事件发射器内部构造函数或ngOnInit方法,我尝试了它,仍然不工作。
子组件:
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'app-server',
templateUrl: './server.component.html',
styles: [
`.online {
color: white;
}
`
]
})
export class ServerComponent {
serverId: number = 10;
serverStatus: string = 'offline';
serverName: 'Random server';
@Output() serverNameEmitter = new EventEmitter<string>();
constructor() {
this.serverStatus = Math.random() > 0.5 ? 'online' : 'offline';
}
ngOnInit(): void {
this.passServerName(this.serverName);
}
passServerName(serverName: string) {
this.serverNameEmitter.emit(serverName);
}
getColor() {
return this.serverStatus == 'online' ? 'green' : 'red';
}
getServerStatus() {
return this.serverStatus;
}
}
父组件
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-servers',
templateUrl: './servers.component.html',
styleUrls: ['./servers.component.css'],
})
export class ServersComponent implements OnInit {
allowNewServer = false;
serverCreationStatus = 'No server was created!';
serverNames = "";
serverStatus = false;
servers = [];
serverName = {
name: "Test server"
};
constructor() {
setTimeout(() => {
this.allowNewServer = true;
}, 2000);
}
ngOnInit(): void {}
onCreateServer() {
this.serverStatus = true;
this.servers.push(this.serverName.name);
this.serverCreationStatus = 'Server has been created! Name is ' + this.serverName.name;
}
onUpdateServerName(event: Event) {
this.serverNames = (event.target as HTMLInputElement).value;
}
changeServerName() {
this.serverName.name = this.serverNames;
}
gettingServerName(serverName: string) {
this.serverNames = serverName;
}
}
父组件HTML
<label>Server Name</label>
<input type="text" class="form-control" (input)="onUpdateServerName($event)">
<!--<input type="text" class="form-control" [(ngModel)]="serverName.name">-->
<!--<p>{{serverName}}</p>-->
<button class="btn btn-primary" [disabled]="!allowNewServer"
(click)="onCreateServer()">Add Server</button>
<!--<p [innerText]="allowNewServer"></p>-->
<!--<p>{{serverCreationStatus}}</p>-->
<p>Here's {{ serverNames }}</p>
<p *ngIf="serverStatus; else noServer">Server was created, server name is {{
serverName.name }}</p>
<ng-template #noServer>
<p>No server was created!</p>
</ng-template>
<button class="btn btn-primary" (click)="changeServerName()">Change server name</button>
<app-server *ngFor="let server of servers"
(serverNameEmitter)="gettingServerName($event)"></app-server>
您可以在每次调用gettingServerName()
时手动触发变更检测。这样你就可以避免Flo提到的ExpressionChangedAfterItHasBeenCheckedError。不需要使用timeout.
导入ChangeDetectorRef
:
import { ChangeDetectorRef } from '@angular/core';
通过构造函数注入它,然后在gettingServerName()
方法的末尾调用detectChanges()
:
constructor(private cdRef: ChangeDetectorRef) {}
gettingServerName(serverName: string) {
this.serverNames = serverName;
this.cdRef.detectChanges();
}
虽然我想补充:你并没有真正使用@Output
的方式。
好的,我已经用你的代码创建了一个Stackblitz项目。但是我不明白....在父组件中设置新的服务器名称。然后可以添加一个新服务器。但是,如果创建了子节点,则不会为它设置名称。所以子进程发出事件(它可以工作)然后将serverNames设置为随机服务器;总是这样。
我唯一看到的是:你得到了一个ExpressionChangedAfterItHasBeenCheckedError如果你在onInit()的子线程中发出了serverName。简单技巧:setTimeout
.
但是看看Stackblitz和玩它。如果你有其他问题,请告诉我。
问候,弗洛