我有一个自定义选择组件,当你点击li
项目时会设置模型,但由于我每次更改模型时都会手动调用this.modelChange.next(this.model)
,因此我非常混乱和可重复我想避免。
所以我的问题是,是否有类似$scope.$watch
的内容,我可以观察值是否发生变化,然后每次发生时调用this.modelChange.next(this.model)
。
我一直在阅读有关Observables
但我无法弄清楚如何将其用于一个简单的值,因为我看到的所有示例都是对外部api:s的异步请求。
当然必须有一种更简单的方法来实现这一目标?
(不是我不能使用ngModelChanges
,因为我实际上并没有使用输入。)
import {Component, Input, Output, EventEmitter, OnInit, OnChanges} from 'angular2/core';
@Component({
selector: 'form-select',
templateUrl: './app/assets/scripts/modules/form-controls/form-select/form-select.component.html',
styleUrls: ['./app/assets/scripts/modules/form-controls/form-select/form-select.component.css'],
inputs: [
'options',
'callback',
'model',
'label'
]
})
export class FormSelectComponent implements OnInit, OnChanges {
@Input() model: any;
@Output() modelChange: EventEmitter = new EventEmitter();
public isOpen: boolean = false;
ngOnInit() {
if (!this.model) {
this.model = {};
}
for (var option of this.options) {
if (option.model == (this.model.model || this.model)) {
this.model = option;
}
}
}
ngOnChanges(changes: {[model: any]: SimpleChange}) {
console.log(changes);
this.modelChange.next(changes['model'].currentValue);
}
toggle() {
this.isOpen = !this.isOpen;
}
close() {
this.isOpen = false;
}
select(option, callback) {
this.model = option;
this.close();
callback ? callback() : false;
}
isSelected(option) {
return option.model === this.model.model;
}
}
编辑:我尝试使用ngOnChanges
(请参阅上面的更新代码),但它只在初始化时运行一次,然后才检测到更改。有什么不对吗?
答案 0 :(得分:20)
所以我的问题是,是否有类似于$ scope的内容。$ watch我可以观察输入属性
model
的值是否发生变化
如果model
是JavaScript基元类型(Number,String,Boolean),那么您可以实现ngOnChanges()
以通知更改。请参阅cookbook example和lifecycle doc, OnChanges section
另一种选择是使用setter和getter。请参阅cookbook example。
如果model
是JavaScript引用类型(数组,对象,日期等),那么检测更改的方式取决于模型的更改方式:
ngOnChanges()
以获得更改通知,就像原始类型一样。ngDoCheck()
来实现自己的更改检测逻辑。 答案 1 :(得分:3)
如果您选择内部使用表单输入的自定义组件,我会利用它上面的ngModelChange事件:
<select [ngModel]="..." (ngModelUpdate)="triggerUpdate($event)">…</select>
或valueChanges可观察相应的控件(如果有)。在模板中:
<select [ngFormControl]="myForm.controls.selectCtrl">…</select>
在组件中:
myForm.controls.selectCtrl.valueChanges.subscribe(newValue => {
(...)
});
答案 2 :(得分:1)
ngAfterViewChecked是一个更好的生命周期方法,因为它在渲染DOM之后被调用,并且可以在此处完成任何操作。
答案 3 :(得分:0)
您可以通过添加model
方法使ngOnChanges(changes) {}
成为getter / setter或实现OnChanges,每次@Input()
值更改后调用该方法。
文档中的ngOnChanges()
示例(上面链接):
@Component({
selector: 'my-cmp',
template: `<p>myProp = {{myProp}}</p>`
})
class MyComponent implements OnChanges {
@Input() myProp: any;
ngOnChanges(changes: {[propName: string]: SimpleChange}) {
console.log('ngOnChanges - myProp = ' + changes['myProp'].currentValue);
}
}
@Component({
selector: 'app',
template: `
<button (click)="value = value + 1">Change MyComponent</button>
<my-cmp [my-prop]="value"></my-cmp>`,
directives: [MyComponent]
})
export class App {
value = 0;
}
bootstrap(App).catch(err => console.error(err));
<强>更新强>
如果model
的内部状态发生变化但model
本身(不同的model
实例)发生变化,则更改检测无法识别它。您需要实现自己的机制来通知感兴趣的代码,例如在Observable
中使用model
发出组件可以订阅的更改事件。
ngOnChanges()
仅在数据绑定更改model
时调用(someFieldInParent
在<my-comp [model]="someFieldInParent">
中更改且Angular将新值传递给model
时} MyComponent
。
return option.model === this.model.model;
不会导致ngOnChanges()
被调用。为此,getter / setter方法更适合。