简体   繁体   English

Angular2中的* ngIf服务不能很好地工作

[英]Service does not work well with *ngIf in Angular2

EDIT: Hmm, I should be more clear. 编辑:嗯,我应该更清楚。 This is an angular2-meteor project. 这是一个有角度的流星项目。 Because meteor is reactive, so maybe has other ways. 因为流星是反应性的,所以可能还有其他方法。 But @lodewijk-bogaards is an good solution for pure Angular2 project. 但@ lodewijk-bogaards是纯Angular2项目的一个很好的解决方案。

I am using Angular 2 (TypeScript). 我正在使用Angular 2(TypeScript)。

I try to use ChatService service to pass value "12345" from App to ChatDetailsComponent . 我尝试使用ChatService服务将值“12345”从App传递给ChatDetailsComponent

If the boolean showChatDetails is true, it will show "12345" the first time I click the Show button, which works well. 如果布尔showChatDetails为true,则在我第一次单击Show按钮时它将显示“12345”,这样效果很好。

The problem is, if the boolean showChatDetails is false, it will show "12345" after the second time I click the Show button. 问题是,如果布尔值showChatDetails为false,则在第二次单击“显示”按钮后,它将显示“12345”。 I don't know why it works the second time I click it, which should be first time too. 我不知道为什么它第二次点击它时才有效,这也应该是第一次。

(Please don't switch to [hidden], because I need *ngIf here.) (请不要切换到[隐藏],因为我需要* ngIf。)

// app.ts // 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]);

// chat-details.component.ts // chat-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 // 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;
    }
}

Looks like a race condition to me. 对我来说看起来像是一场竞争。 If the ChatDetailsComponent subscribes to the ChatService after the chatId has been emitted it will not receive it. 如果ChatDetailsComponent订阅了ChatService chatId已经发出它不会接受它。 This is very easily possible, since Angular will schedule the creation of the component at the same time as Rx schedules the emit of the event. 这很容易实现,因为Angular将在Rx计划事件发射的同时安排组件的创建。

I can come up with multiple solutions, but I would suggest that you look into using a ReplaySubject instead of an EventEmitter. 我可以提出多种解决方案,但我建议您考虑使用ReplaySubject而不是EventEmitter。

I'm not sure if your aim is to accomplish the task the very way you stated or if you're flexible in how it's done. 我不确定你的目标是按照你所陈述的方式完成任务,或者你是否灵活完成任务。

I think it's much less error prone to make chatId an @Input() of ChatDetailsComponent and have App create a new instance of the component whenever chatId changes. 我认为这是更容易出错,使chatId的@Input()ChatDetailsComponent和具有App创建组件时的新实例chatId变化。

The containing component has to know when an instance of ChatDetailsComponent needs to be created anyway. 包含组件必须知道何时需要创建ChatDetailsComponent的实例。 Having it pass the needed chatId irhgt away seems to be a better approach to me. 让它通过所需的chatId irhgt似乎是一个更好的方法对我来说。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM