订阅Angular 2中组件属性的更改以进行去抖动自动保存?

Rea*_*ues 7 observable typescript angular

假设我有以下Angular 2组件,其中foo是一个未绑定到表单的对象,而不是来自Input():

@Component({
    selector: 'foo',
    templateUrl: '/angular/views/foo.template.html',
    directives: [ContentEditableDirective, ROUTER_DIRECTIVES],
    providers: [FooService]
})
export class FooComponent implements OnInit {
    public foo: Foo = new Foo();

    constructor(
        private fooService: FooService,
        private route : ActivatedRoute,
        private router : Router) {}

    ngOnInit() {
        let id = +this.route.snapshot.params['id'];
        this.fooService.getFoo(id).subscribe(
            foo => {
                this.foo = foo;

                // I have this.foo, we should watch for changes here.

                Observable. // ???
                    .debounceTime(1000)
                    .subscribe(input => fooService.autoSave(this.foo));
            },
            error => console.log(error)
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

如何订阅Foo对象的更改,并将其发送到我的服务器?

到目前为止,我所看到的每个例子都涉及从一个表格中foo脱离出来Input()或者被绑定到一个表格.我只是想看一个普通的旧Javascript对象进行更改并对此作出反应.

更新

我曾经试图再次,并且已经能够抖内部原始组件上的财产这里.

但是,我一直无法使用具有自己属性的复杂对象(此处) ; 因为ngModel当更新foo对象的属性时,不会调用提供的plnkr中的setter .

正确的答案将证明这适用于复杂的对象.

更新2

我相信我有一个复杂的对象 ; 但是必须确保对象是不可变的,并且每个属性都有setter,这有点令人失望.它似乎也需要拆分[(ngModel)][ngModel],(ngModelChange)因此您可以指定自定义设置器逻辑.

理论上你可以将功能抽象为状态服务,但我想看看是否可以进一步去除样板量.每次想要进行状态更改时创建新对象都会让人感到沮丧.

Rea*_*ues 8

对于简单和复杂的对象,我似乎已经部分解决了这个问题.如果不需要整个变换检测器,您可以通过以下方式轻松实现:

  • 组件上的主题和可观察对象.
  • 组件上跟踪属性的getter和setter.

下面是一个如何实现这一目标的非常小的例子.

零件

import {Component} from '@angular/core'
import {Subject} from 'rxjs/Rx';

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <input type="text" [(ngModel)]="foo"  />
      <div>current Foo: {{ foo }}</div>
      <div>debounced Foo: {{ debouncedFoo }}</div>
    </div>
  `,
  directives: []
})
export class App {
  private _foo: any;
  debouncedFoo: any;
  fooSubject : Subject<any> = new Subject<any>(this._foo);
  fooStream : Observable<any> = this.fooSubject.asObservable();

  get foo() {
      return this._foo;
  });

  set foo(value:any) {
    this._foo = value;
    this.fooSubject.next(value);
  });

  constructor() {
    // Manipulate your subscription stream here
    this.subscription = this.fooStream
      .debounceTime(2000)
      .subscribe(
        value => {
          this.debouncedFoo = value;
      });
  }
}
Run Code Online (Sandbox Code Playgroud)

http://plnkr.co/edit/HMJz6UWeZIBovMkXlR01?p=preview

当然,实际上组件应该不了解主题或可观察,因此请将它们提取到服务中.

缺点

此示例仅适用于基元.如果您希望它与对象一起使用,则需要为每个属性设置自定义setter逻辑,并记住每次更改该对象的属性时都要创建新对象.