您好,我尝试了解角度的变化检测。
我有一个用于内联文本编辑的父组件my-editable
和一个带有样式输入元素的子组件my-input
。我正在使用从父组件到子组件的响应式表单。
现在,如果子组件的输出属性status
发出新事件,我的父组件将调用其方法dummy()
,而无需任何表达式。
我感到困惑的是,父级的更改检测显然触发了!
如果我从(status)="dummy()"
中删除了行my-editable.component.html
,则模板中的错误消息(<small class="error">{{ formControl.errors.msg }}</small>
)将不会显示。
我认为,更改检测应该由(status)="cdr.detectChanges()"
或类似的东西触发。
有人可以向我解释吗?
my-input.component.ts
@Component({
selector: 'my-input',
...
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyInput implements OnInit, OnDestroy {
...
@Input('control')
set control(control: AbstractControl) {
this.formControl = control as FormControl;
this.formGroup = control.parent;
}
@Output('status') statusOutput = new EventEmitter<string>();
set status(status: string) {
if (status) {
this.statusOutput.emit(status);
this.statusClass = status.toLowerCase();
this.cdr.detectChanges();
} else {
this.statusClass = false;
}
}
public statusClass: false | string;
public formGroup: FormGroup | FormArray;
public formControl: FormControl;
...
constructor(
...
private cdr: ChangeDetectorRef
) {...}
public ngOnInit(): void {
this.status = this.formControl.status;
this.updateOnStatusChange();
...
}
...
private updateOnStatusChange(): void {
this.formControl.statusChanges
.pipe(pairwise(), untilDestroyed(this))
.subscribe(([lastStatus, status]) => {
if (status !== lastStatus) {
this.status = status;
}
});
}
}
my-input.component.html
<i [ngClass]="statusClass" *ngIf="statusClass"></i>
<input [formControl]="formControl" [placeholder]="placeholder">
my-editable.component.ts
@Component({
selector: 'my-editable',
...
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyEditableComponent {
...
@Input('control')
set control(control: AbstractControl) {
this.formControl = control as FormControl;
}
...
public formControl: FormControl;
...
public dummy() {} // <<< MAGIC
...
}
my-editable.component.html
...
<ng-container [ngSwitch]="currentMode">
<ng-template [ngSwitchCase]="EditModes.READONLY">
<p>{{ formControl.value }}</p>
</ng-template>
<ng-template [ngSwitchCase]="EditModes.EDITABLE">
<div class="wrapper">
<p>{{ formControl.value }}</p>
<button (click)="mode = EditModes.EDIT">
<i class="edit"></i>
</button>
</div>
</ng-template>
<ng-template [ngSwitchCase]="EditModes.EDIT">
<my-input
(status)="dummy()" <!-- MAGIC -->
[control]="formControl"
...
></my-input>
</ng-template>
</ng-container>
<ng-container [ngSwitch]="formControl.invalid && formControl.touched">
<ng-template [ngSwitchCase]="true">
<small class="error">{{ formControl.errors.msg }}</small>
</ng-template>
<ng-template [ngSwitchCase]="false">
<small class="description">{{ description }}</small>
</ng-template>
</ng-container>
答案 0 :(得分:0)