服务在 Angular2 中不能很好地与 *ngIf 一起使用
Service does not work well with *ngIf in Angular2
编辑:嗯,我应该更清楚。这是一个 angular2-meteor 项目。因为 meteor 是反应性的,所以也许有其他方式。但是@lodewijk-bogaards 是纯 Angular2 项目的一个很好的解决方案。
我正在使用 Angular 2 (TypeScript)。
我尝试使用 ChatService
服务将值“12345”从 App
传递到 ChatDetailsComponent
。
如果布尔值 showChatDetails
为真,我第一次单击“显示”按钮时会显示“12345”,效果很好。
问题是,如果布尔值 showChatDetails
为假,在我第二次单击“显示”按钮后它将显示“12345”。不知道为什么第二次点就可以了,应该是第一次吧
(请不要切换到[hidden],因为我这里需要*ngIf。)
// app.ts
import {Component, View} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {ChatService} from './chat.service';
import {ChatDetailsComponent} from './chat-details.component';
@Component({
selector: 'app'
})
@View({
directives: [ChatDetailsComponent],
template: `
<button (click)="showButton()">Show</button>
<chat-details-component *ngIf="showChatDetails"></chat-details-component>
`
})
class App {
// Here if it is true, it works well. If it is false, the problem comes.
showChatDetails:boolean = false;
constructor(private _chatService: ChatService) {}
showButton() {
this._chatService.setChatId("12345");
this.showChatDetails = true;
}
}
bootstrap(App, [ChatService]);
// 聊天-details.component.ts
import {Component, View} from 'angular2/core';
import {ChatService} from './chat.service';
@Component({
selector: 'chat-details-component'
})
@View({
template: `
<div>ID: {{chatId}}</div>
`
})
export class ChatDetailsComponent {
chatId:string;
constructor(private _chatService: ChatService){}
ngOnInit() {
this._chatService.getChatId().subscribe(id => this.chatId = id);
}
}
// chat.service.ts
import {EventEmitter} from 'angular2/core';
export class ChatService {
chatId: EventEmitter<string> = new EventEmitter();
setChatId(id) {
this.chatId.emit(id);
}
getChatId() {
return this.chatId;
}
}
在我看来像是一种竞争条件。如果 ChatDetailsComponent
订阅了 ChatService
在 发出 chatId
之后它将不会收到它。这很容易实现,因为 Angular 将在 Rx 安排事件发出的同时安排组件的创建。
我可以想出多种解决方案,但我建议您考虑使用 ReplaySubject 而不是 EventEmitter。
我不确定你的目标是按照你所说的方式完成任务,还是你在完成任务时是否灵活。
我认为将 chatId 设置为 ChatDetailsComponent
的 @Input()
并让 App
在 chatId
更改时创建组件的新实例更不容易出错。
包含组件必须知道何时需要创建 ChatDetailsComponent
的实例。让它通过所需的 chatId
irhgt 对我来说似乎是一个更好的方法。
编辑:嗯,我应该更清楚。这是一个 angular2-meteor 项目。因为 meteor 是反应性的,所以也许有其他方式。但是@lodewijk-bogaards 是纯 Angular2 项目的一个很好的解决方案。
我正在使用 Angular 2 (TypeScript)。
我尝试使用 ChatService
服务将值“12345”从 App
传递到 ChatDetailsComponent
。
如果布尔值 showChatDetails
为真,我第一次单击“显示”按钮时会显示“12345”,效果很好。
问题是,如果布尔值 showChatDetails
为假,在我第二次单击“显示”按钮后它将显示“12345”。不知道为什么第二次点就可以了,应该是第一次吧
(请不要切换到[hidden],因为我这里需要*ngIf。)
// app.ts
import {Component, View} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {ChatService} from './chat.service';
import {ChatDetailsComponent} from './chat-details.component';
@Component({
selector: 'app'
})
@View({
directives: [ChatDetailsComponent],
template: `
<button (click)="showButton()">Show</button>
<chat-details-component *ngIf="showChatDetails"></chat-details-component>
`
})
class App {
// Here if it is true, it works well. If it is false, the problem comes.
showChatDetails:boolean = false;
constructor(private _chatService: ChatService) {}
showButton() {
this._chatService.setChatId("12345");
this.showChatDetails = true;
}
}
bootstrap(App, [ChatService]);
// 聊天-details.component.ts
import {Component, View} from 'angular2/core';
import {ChatService} from './chat.service';
@Component({
selector: 'chat-details-component'
})
@View({
template: `
<div>ID: {{chatId}}</div>
`
})
export class ChatDetailsComponent {
chatId:string;
constructor(private _chatService: ChatService){}
ngOnInit() {
this._chatService.getChatId().subscribe(id => this.chatId = id);
}
}
// chat.service.ts
import {EventEmitter} from 'angular2/core';
export class ChatService {
chatId: EventEmitter<string> = new EventEmitter();
setChatId(id) {
this.chatId.emit(id);
}
getChatId() {
return this.chatId;
}
}
在我看来像是一种竞争条件。如果 ChatDetailsComponent
订阅了 ChatService
在 发出 chatId
之后它将不会收到它。这很容易实现,因为 Angular 将在 Rx 安排事件发出的同时安排组件的创建。
我可以想出多种解决方案,但我建议您考虑使用 ReplaySubject 而不是 EventEmitter。
我不确定你的目标是按照你所说的方式完成任务,还是你在完成任务时是否灵活。
我认为将 chatId 设置为 ChatDetailsComponent
的 @Input()
并让 App
在 chatId
更改时创建组件的新实例更不容易出错。
包含组件必须知道何时需要创建 ChatDetailsComponent
的实例。让它通过所需的 chatId
irhgt 对我来说似乎是一个更好的方法。