1

前言:我是 Meteor、Angular 和 Typescript 的新手,所以这里很可能会出现 XY 问题。

我正在使用 Meteor 和 Angular 2(使用angular2-meteor包)开发一个简单的项目管理应用程序,其中结构(目前)由具有事件的项目组成。一种视图是项目列表。单击项目会显示项目详细信息的模式,包括项目事件列表。因此,三个组件:ProjectListProjectDetailsProjectEventsListProjectDetails使用Session变量来知道要显示哪个项目,并且有效。但是,模式中的事件列表在为单击的第一个项目创建后不会更新。

项目事件列表.ts

import {Component, View} from 'angular2/core';
import {MeteorComponent} from 'angular2-meteor';

import {ProjectEvents} from 'collections/ProjectEvents';


@Component({
    selector: 'projectEventsList',
    inputs: ['projectId']
})

@View({
    templateUrl: '/client/projectEventsList/projectEventsList.html'
})

export class ProjectEventsList extends MeteorComponent {
    projectEvents: Mongo.Cursor<ProjectEvent>;

    projectId: string;

    constructor() {
        super();

        this.subscribe('projectEvents', this.projectId, () => {
            this.autorun(() => {
                this.projectEvents = ProjectEvents.find({projectId: this.projectId});
            }, true);
        });
    }
}

据我了解(尽管我可能会离开这里),我很难autorun自动运行。我试过放一个getter和setter,projectId当我点击一个项目时它会更新,但里面的代码在autorun第一次点击后不会运行。我尝试过的事情:

  • subscribe()切换和的嵌套autorun()
  • 添加/删除 autobind 参数到subscribe()autorun()。我真的不明白那应该做什么。
  • 将订阅代码移动到 setter 上projectId

    private _projectId: string = '';
    get projectId() {
        return this._projectId;
    }
    set projectId(id: string) {
        this._projectId = id;
    
        this.subscribe('projectEvents', this._projectId, () => {
            this.projectEvents = ProjectEvents.find({projectId: this._projectId});
        }, true);
    }
    

    当我这样做时,列表停止显示任何项目。

如果这一切看起来应该可行,我将创建一个小测试用例来发布,但我希望这里的某些内容对于那些知道的人来说显然是错误的。谢谢!

4

2 回答 2

1

this.subscribe()并且this.autorun()似乎不是 Angular 组件类的一部分。如果这是一个外部库,您可能需要在 Angular 区域中显式运行它才能进行更改检测:

constructor(private zone: NgZone) {
  this.subscribe('projectEvents', this.projectId, () => {
        this.autorun(() => {
            zone.run(() => {
              this.projectEvents = ProjectEvents.find({projectId: this.projectId});
            });
        }, true);
    });
 }

如果您想订阅从组件本身触发的事件,请使用主机绑定

@Component(
  {selector: 'some-selector',
  host: {'projectEvents': 'projectsEventHandler($event)'}
export class SomeComponent {
  projectsEventHandler(event) {
    // do something
  }
}
于 2016-01-25T18:18:24.413 回答
0

I eventually got the setter method working, as shown below. It feels clunky, so I'm hoping there's a cleaner way to do this, but the below is working for me now (i.e., the list of events is updated when the parent component (ProjectList) sends a new projectId to the input.

ProjectEventsList.ts

import {Component, View} from 'angular2/core';
import {MeteorComponent} from 'angular2-meteor';

import {ProjectEvents} from 'collections/ProjectEvents';


@Component({
    selector: 'projectEventsList',
    inputs: ['projectId']
})

@View({
    templateUrl: '/client/projectEventsList/projectEventsList.html'
})

export class ProjectEventsList extends MeteorComponent {
    projectEvents: Mongo.Cursor<ProjectEvent>;

    set projectId(id: string) {
    this._projectId = id;

    this.projectEventsSub = this.subscribe('projectEvents', this._projectId, () => {
        this.projectEvents = ProjectEvents.find({projectId: this._projectId}, {sort: { startDate: 1 }});
    }, true);
}

get projectId() {
    return this._projectId;
}

    constructor() {
        super();

        this.subscribe('projectEvents', this.projectId, () => {
            this.projectEvents = ProjectEvents.find({projectId: this.projectId});
        }, true);
    }
}
于 2016-02-05T19:58:38.147 回答