Angular 4视图也未从服务更新

时间:2017-05-23 05:56:59

标签: angular

我正在努力解决我的观点未从服务中更新的问题。

我想要实现的是消息处理。我发送消息给服务,订阅的组件得到更新。在模型上,一切都很完美,但视图根本没有变化。

我的服务:

import {Injectable} from '@angular/core';
import {Observer} from 'rxjs/Observer';
import {Subscription} from 'rxjs/Subscription';
import {Subject} from 'rxjs/Rx';

import {MyMessage} from './myMessage';

@Injectable()
export class MessageHandlingService {
    private _message: Subject<MyMessage> = new Subject();

    handle(message: string, stack: string) {
        // console.log('handle', message, stack);
        let newMyMessage: MyMessage;

        if (stack) {
            newMyMessage = new MyMessage(2, message, stack);
        } else {
            newMyMessage = new MyMessage(1, message, stack);
        }

        this._message.next(newMyMessage);
    }

    subscribeMessages(observer: Observer<MyMessage>): Subscription {
        // console.log('MessageHandling - subscriber accepted');
        return this._message.subscribe(observer);
    }
}

我的组件:

import {Component, OnInit, OnDestroy} from '@angular/core';
import {Observer} from 'rxjs/Observer';
import {Subscription} from 'rxjs/Subscription';

import {MessageHandlingService} from './messageHandling.service';
import {MyMessage} from './myMessage';

@Component({
    templateUrl: './my-messager.component.html',
    selector: 'mymy-messager'
})
export class MyMessagerComponent implements OnInit, OnDestroy, Observer<MyMessage> {

    private _subscription: Subscription;

    display: boolean = false;

    msg: MyMessage = null;

    constructor(private messageHandling: MessageHandlingService) {}

    ngOnInit() {
        console.log('MyMessager is subscribing');
        this._subscription = this.messageHandling.subscribeMessages(this);
    }

    ngOnDestroy() {
        console.log('MyMessager is UN-subscribing');
        if (this._subscription) {
            this._subscription.unsubscribe();
        }
    }

    /* istanbul ignore next */
    complete() {}

    /* istanbul ignore next */
    error(e: any) {
        if (console) {
            console.error(e);
        }
    }

    next(message: MyMessage) {
        console.log('observed next', message);
        this._showMessage(message);
    }

    private _showMessage(message: MyMessage) {
        this.msg = message;
        console.log('Settind display to true')
        this.display = true;
    }

    hideDialog() {
        this.msg = null;
        this.display = false;
    }
}

和组件HTML

{{msg}}
{{display}}
<span *ngIf="msg">
    <span *ngIf="msg.severity === 1">
        <p-dialog 
            header="Information message"
            [(visible)]="display" 
            modal="modal"
            showEffect="fade">
            <p>{{msg.message}}</p>
            <footer>
                <div
                    class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
                    <button type="button" pButton icon="fa-close" (click)="hideDialog()" label="OK"></button>
                </div>
            </footer> 
        </p-dialog>
    </span>
    <span *ngIf="msg.severity === 2">
        <p-dialog 
            header="Technical message"
            [(visible)]="display" 
            modal="modal"
            showEffect="fade">
            <p>{{msg.message}}</p>
            <br />
            <hr />
            <p style="white-space: pre;">{{msg.stackTrace}}</p>
            <footer>
                <div
                    class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
                    <button type="button" pButton icon="fa-close" (click)="hideDialog()" label="OK"></button>
                </div>
            </footer> 
        </p-dialog>
    </span>
</span>

我试过了

ChangeDetectorRef.detectChanges()

ChangeDetectorRef.markForCheck()

ApplicationRef.tick()

甚至

NgZone run

但没有运气。相同的代码适用于Angular 2.

2 个答案:

答案 0 :(得分:2)

this._message.subscribe(observer);执行期间正在创建SafeSubscriber

function SafeSubscriber(_parentSubscriber, observerOrNext, error, complete) {
    _super.call(this);
    this._parentSubscriber = _parentSubscriber;
    var next;
    var context = this;
    if (isFunction_1.isFunction(observerOrNext)) {
        next = observerOrNext;
    }
    else if (observerOrNext) {
        next = observerOrNext.next;
        error = observerOrNext.error;
        complete = observerOrNext.complete;
        if (observerOrNext !== Observer_1.empty) {
            context = Object.create(observerOrNext); // this line

因此您丢失了指向当前AppComponent实例的链接

enter image description here

enter image description here

例如,这应该对你有用

subscribeMessages(observer: Observer<MyMessage>): Subscription {
  const subscriber = new Subscriber(
      observer.next.bind(observer),
      observer.error.bind(observer),
      observer.complete.bind(observer))

  return this._message.subscribe(subscriber);
}

或者你可以使用像

这样的对象
const subscriber = {
   next: observer.next.bind(observer),
   error: observer.error.bind(observer),
   complete: observer.complete.bind(observer))
}

<强> Plunker Example

答案 1 :(得分:1)

这是一个this绑定问题。如果替换

,您的代码可以正常工作
    this.messageHandling.subscribeMessages(this);

通过

    this.messageHandling.subscribeMessages({
      next: (message) => this.next(message),
      error: (error) => this.complete(error),
      complete: () => this.complete()
    });

请参阅a demo

那就是说,我宁愿暴露observable,而不是让你的服务公开一个以Observer为参数的方法。这样,调用者可以在实际订阅observable之前轻松添加它想要的运算符。 Demo