[英]Angular 2: how to change @Input property value during ngOnInit/ngOnChanges
I am creating a component with 2 @Input()
properties, and they happen to depend on one another. 我正在创建一个具有2个
@Input()
属性的组件,它们恰好相互依赖。 Here's an example (also you can see this plunk ): 这是一个示例(您也可以看到这个问题 ):
@Component({
selector: 'my-select',
template: `
<ul>
<li *ngFor="let item of items">
{{ item }}
<span *ngIf="item === default">(default)</span>
<button *ngIf="item !== default" (click)="makeDefault(item)">Make default</button>
</li>
</ul>
`,
}) export class MyInput implements OnInit {
@Input() public items: string[] = [];
@Input() public defaultValue: string;
@Output() public defaultValueChange = new EventEmitter<string>();
public makeDefault(item: string): void {
this.defaultValue = item;
this.defaultValueChange.emit(this.defaultValue);
}
public ngOnInit(): void {
if (!this.defaultValue) {
// choose the first item, since there always must be a default
this.makeDefault(this.items[0]);
}
}
}
The actual problem is that I'm changing an @Input()
property value during an ongoing change-detection cycle, which is not very awesome (and result in an error thrown by Angular). 实际的问题是我在进行中的更改检测周期内更改了
@Input()
属性值,这不是很出色(并导致Angular引发错误)。 This is happening assuming that 假设发生这种情况
<my-select [(default)]="defaultItem" ...></my-select>
syntax is used, which is exactly the expected usage pattern. 使用语法,这正是预期的用法模式。
I can fix this by surrounding makeDefault
call with setTimeout
, like this: 我可以通过用
setTimeout
包围makeDefault
调用来解决此问题,如下所示:
public ngOnInit(): void {
if (!this.defaultValue) {
setTimeout(() => {
this.makeDefault(this.items[0]);
}, 0);
}
}
but this is pretty ugly, IMHO. 但这很丑,恕我直言。
What is the proper way to handle such interaction patterns? 处理这种交互模式的正确方法是什么?
To set the default value, you must use: 要设置默认值,必须使用:
[defaultValue]="default"
Not: 不:
[(defaultValue)]="default"
Check out the updated plnkr . 签出更新的plnkr 。 I wired up the defaultValueChange event too.
我也连接了defaultValueChange事件。
Update from comment: 评论更新:
Also, instead of initializing 'default' in the my-app template, using a default value declared in the App class overcomes this issue too: 此外,使用在App类中声明的默认值代替在my-app模板中初始化“默认”也可以解决此问题:
<my-select [(default)]="defaultItem" ...></my-select>
export class App {
defaultItem = 'default';
items = ['item 1', 'item 2', 'item 3'];
constructor() {
this.name = 'Angular2'
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.