typescript Angular中的@Output装饰器是否只与click事件一起严格工作?

ykejflvf  于 2022-11-26  发布在  TypeScript
关注(0)|答案(2)|浏览(122)

我尝试将数据从子组件传递到父组件,同时将变量值从子组件传递到父组件,不幸的是,父组件中没有任何更改。您知道这是怎么回事吗?或者@Output装饰器严格地只处理来自子组件中的点击事件吗?我还希望是否使用eventemitter方法并不重要。因此,例如从构造函数或ngOnInit方法内部设置eventemitter的emit,我尝试了它,仍然不起作用。
子组件:

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>
o75abkj4

o75abkj41#

您可以在每次调用gettingServerName()时手动触发更改检测。这样可以避免Flo提到的ExpressionChangedAfterItHasBeenCheckedError。无需使用超时
只需导入ChangeDetectorRef

import { ChangeDetectorRef } from '@angular/core';

通过构造函数注入它,然后在gettingServerName()方法的末尾调用detectChanges()

constructor(private cdRef: ChangeDetectorRef) {}

  gettingServerName(serverName: string) {
    this.serverNames = serverName;
    this.cdRef.detectChanges();
  }

不过我想补充一句:您实际上并没有按照预期的方式使用@Output

5anewei6

5anewei62#

好的,我已经用你的代码创建了一个Stackblitz项目。但是我不明白一些事情....你在父组件中设置了一个新的服务器名称。然后你可以添加一个新的服务器。但是如果创建了子组件,你从来没有给它设置名称。所以子组件发出事件(它工作),你总是把serverNames设置为“Random server”。
我只看到:如果在onInit()中发出子进程中的serverName,则会出现ExpressionChangedAfterItHasBeenCheckedError。简单技巧:setTimeout .
但是看到Stackblitz并玩它。如果你有其他问题让我知道。
你好,弗洛

相关问题