【问题标题】:Angular2 Access Component Members in Observable Delegate?Angular2访问可观察委托中的组件成员?
【发布时间】:2016-08-18 16:24:39
【问题描述】:

我正在订阅一个 rxjs ObservableSubject,并在事件触发时尝试重新加载 iframe。我的可观察委托正在触发,但我似乎无法弄清楚如何访问我的组件的属性,它们都是未定义的。这是一些sn-ps:

@Component({
    selector: 'tile-comp',
    templateUrl: './app/tiles/feature.html'
})

export class FeatureComponent implements OnInit, OnDestroy {
    dtUrl: SafeResourceUrl;

 ngOnInit() {
    console.log('in ngOnInt');

    this._patientService.patientSubject.subscribe(
        currentPatientObs => { console.log('dt url ' + this.dtUrl); });

    }
}

我不断将这个写入控制台:'dt url undefined'。 dtUrl 绑定到 iframe 的 src,所以我希望更新这个可观察委托中的值。

谢谢!

编辑 1


这是组件的完整源代码:

import { Component, HostListener, HostBinding, OnInit, OnDestroy, NgZone } from '@angular/core';
import {SafeResourceUrl, DomSanitizationService } from '@angular/platform-browser';
import {Router, ActivatedRoute, RoutesRecognized, ActivatedRouteSnapshot } from '@angular/router';
import { NavService } from '../layout/nav/nav.service';
import { NavigationItem} from '../model/NavigationItem';
import { SubNavigationItem, CTAButtonTarget} from '../model/SubNavigationItem';
import {OrderBy} from '../shared/orderBy';
import {PatientService} from '../patient/patient.service';


@Component({
    selector: 'tile-comp',
    templateUrl: './app/tiles/feature.html',
    pipes: [OrderBy], 
    providers: [NavService]
})

export class FeatureComponent implements OnInit, OnDestroy {

    selectedFeature: NavigationItem;
    selectedSubFeature: SubNavigationItem;

    featureQryParam: string;
    subfeatureQryParam: string;

    dtUrl: SafeResourceUrl;

    private routeParamObs: any;
    ctaButtons: SubNavigationItem[];

    constructor(private _navService: NavService, private _route: ActivatedRoute, private _router: Router, private _sanitizer: DomSanitizationService, private _patientService: PatientService) { }

    ngOnInit() {
        this.routeParamObs = this._route.params.subscribe(qp => {
            this.handleParamChange(qp);
        });

        this._patientService.patientSubject.subscribe(
            currentPatientObs => { console.log('dt url ' + this.dtUrl); });
    }

    getSelectedFeature() {

        this._navService.getSubNavItem(this.featureQryParam).subscribe(item => {
            this.selectedFeature = item;

            if (this.selectedFeature && this.selectedFeature.SubNavigation) {
                this.selectedFeature.SubNavigation.forEach(s => s.Href ? s.SanitizedUrl = this._sanitizer.bypassSecurityTrustResourceUrl(s.Href) : s.Href);

                if (this.subfeatureQryParam && this.subfeatureQryParam !== '') {
                    this.selectedSubFeature = this.selectedFeature.SubNavigation.find(sn => sn.SubFeature.toLocaleLowerCase() === this.subfeatureQryParam);
                } else {
                    this.selectedSubFeature = this.selectedFeature.SubNavigation.find(sn => sn.Order === 1);
                }

                this.getCTAButtons();

                this.dtUrl = this.selectedSubFeature.SanitizedUrl;
            }
        }); 
    }

    handleParamChange(params: any) {
        this.featureQryParam = params['feature'];
        this.subfeatureQryParam = (params['subFeature'] && params['subFeature'] !== '') ? params['subFeature'].toLocaleLowerCase() : '';
        this.getSelectedFeature();
    }

    ngOnDestroy() {
        this.routeParamObs.unsubscribe();
    }

    CTAButtonClick(ctaBtn: SubNavigationItem) {
        let ngRoute = [];
        ngRoute.push(ctaBtn.CTAButtonTarget.AngularRouteName);
        ctaBtn.CTAButtonTarget.AngularRouteParams.forEach(rParam => ngRoute.push(rParam));
        this._router.navigate(ngRoute);
    }

    //iterate over the subfeatures and grab all the cta buttons and load them into the ctaButtonTargets collection
    getCTAButtons() {
        this.ctaButtons = [];
        this.ctaButtons = this.selectedFeature.SubNavigation.filter(sn => sn.IsCTAButton === true);
        console.log('number of cta buttons: ' + this.ctaButtons.length);
        this.ctaButtons.forEach(btn => btn.CTAButtonTarget.Href ? btn.CTAButtonTarget.SanitizedHref = this._sanitizer.bypassSecurityTrustUrl(btn.CTAButtonTarget.Href) : btn.CTAButtonTarget.Href);
    }
}

【问题讨论】:

  • 你在哪里给this.dtUrl赋值?
  • 为什么你认为_navService.getSubNavItem().subscribe(...)_patientService.patientSubject.subscribe(...)之前被执行?由于代码太复杂,我没有完全调查所有可能的代码路径。

标签: angular rxjs angular2-observables


【解决方案1】:

我过去曾遇到过通过匿名函数访问时变量拒绝存在于组件上的问题。到目前为止,我处理它的方法是创建一个专门设置数据的方法并从订阅中调用它。如:

ngOnInit() {
    this.routeParamObs = this._route.params.subscribe(qp => {
        this.handleParamChange(qp);
    });

    this._patientService.patientSubject.subscribe(
        currentPatientObs => { this.performOperation(); });
}

performOperation(): void {
    console.log('dt url ' + this.dtUrl);
}

不完全确定为什么有时会发生这种情况,但希望这会有所帮助。

【讨论】:

  • 也许你的意思是catch(this.handleError)map(...) 或所有传递方法引用的位置相同。这种方式在handleError() this. 内部是“损坏的”并且不指向当前组件或服务实例。如果您将其传递为catch(this.handleError.bind(this)catch((err) => this.handleError(err)),则保留this.。我在问题的代码中没有看到类似的内容。
  • 我们的代码中有一个地方,我们非常具体地做了类似this._patientService.patientSubject.subscribe(currentPatientObs => { this.dtUrl = currentPatienObs; }); 的事情,而this. 被“破坏”了,因为我们无法在组件上设置任何东西。我们认为解决它的唯一方法是调用一个为我们设置值的方法,如我的回答中所示。这是不久前的事了(可能是 RC 之前的?)所以它可能已经改变了。
【解决方案2】:

这似乎是我们如何定义订阅的问题。当我添加对组件的可观察引用时,我开始能够从可观察委托中访问组件成员变量。这是我所做的:

    export class FeatureComponent implements OnInit, OnDestroy {

    selectedFeature: NavigationItem;
    selectedSubFeature: SubNavigationItem;

    featureQryParam: string;
    subfeatureQryParam: string;

    dtUrl: SafeResourceUrl;

    private routeParamObs: any;
    private patientObs: any;
    ctaButtons: SubNavigationItem[];

    constructor(private _navService: NavService, private _route: ActivatedRoute, private _router: Router, private _sanitizer: DomSanitizationService, private _patientService: PatientService) { }

    ngOnInit() {
        this.routeParamObs = this._route.params.subscribe(qp => {
            this.handleParamChange(qp);
        });

        this.patientObs = this._patientService.patientSubject.subscribe(
            currentPatient => {

                console.log('dt url ' + this.dtUrl);
                this.refreshIframe(currentPatient);
            });
    }

    refreshIframe(pat:any) {
      console.log('dt url in method ' + this.dtUrl);
      console.log('pat: '+pat);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-07
    • 1970-01-01
    • 2010-11-17
    相关资源
    最近更新 更多