#angular #angular-reactive-forms
#angular #угловые реактивные формы
Вопрос:
У меня есть реактивная форма с пользовательским FormControl
интерфейсом. При первой загрузке экрана, хотя пользовательский элемент управления является обязательным полем, моя форма действительна.
Если я инициирую какое-либо изменение, например, установив флажок в своей форме, то форма помечается как недействительная, пока я не введу значение в свой пользовательский элемент управления.
Если я сброшу значение моего пользовательского элемента управления, то форма снова будет помечена как недействительная, и с этого момента она будет работать так, как ожидалось.
Таким образом, проблема возникает ТОЛЬКО при первой загрузке формы на экран.
Я заметил следующее исключение в консоли:
Эта ошибка вызывается средством проверки моего пользовательского элемента управления, потому что, если я прокомментирую ее, ошибка исчезнет.
Ниже приведен код моего пользовательского элемента управления. Я делаю что-то не так?
import { Component, forwardRef, Input, OnInit, Output } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-multiple-checkbox',
templateUrl: './multiple-checkbox.component.html',
styleUrls: ['./multiple-checkbox.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MultipleCheckboxComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MultipleCheckboxComponent),
multi: true
}]
})
export class MultipleCheckboxComponent implements OnInit, ControlValueAccessor {
value = [];
disabled = false;
@Input() public options: { key, value }[];
onTouched: any;
onChange: any;
constructor() { }
validate({ value }: FormControl) {
const isNotValid = this.value.length === 0;
return isNotValid amp;amp; {
invalid: true
};
}
ngOnInit(): void { }
evaluate(event, key): void {
if (event.target.checked) {
this.value.push(key);
} else {
this.value.splice(this.value.findIndex(i => key === i), 1);
}
this.onChange(this.value);
this.onTouched();
}
isChecked(key): boolean {
return this.value.findIndex(e => e === key) > -1;
}
writeValue(value: any): void {
this.value = value;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
}
[ПРАВИТЬ]
Добавление способа добавления пользовательского элемента управления на экран в его родительской форме:
<div [formGroup]="form">
<div *ngIf="control.visible">
<div [ngSwitch]="control.controlType">
<div *ngSwitchCase="'checkbox'">
<label [attr.for]="control.key">{{control.label}}</label>
<input [formControlName]="control.key" [id]="control.key" type="checkbox"
(change)="evaluate(control.key)">
</div>
<!-- THIS IS MY CUSTOM CONTROL -->
<app-multiple-checkbox *ngSwitchCase="'multipleCheckbox'" [formControlName]="control.key"
[options]="control.options" (change)="evaluate(control.key)">
</app-multiple-checkbox>
</div>
</div>
[ПРАВИТЬ]
Следующий комментарий ниже, ошибка вызвана этой строкой в моей форме :
<button type="submit" color="accent" (click)="save()"
[disabled]="catalogForm.invalid">Submit</button>
Комментарии:
1. Можете ли вы создать stackblitz?
2. Не могли бы вы показать, как вы используете этот пользовательский компонент, например, как вы встраиваете его в свой шаблон? И как
validate
вызывается метод? Используете ли вы его с того места,ValidatorFn
FormControl
где используется этот компонент?3. @Eddi Я отредактировал свой вопрос с отсутствующей информацией. Я только что реализовал
Validator
интерфейс, поэтому нет необходимости выполнять какие-либо другие вызовы. Опять же, работает нормально, за исключением первого раза (до того, как форма станет грязной)4. @Sam Для меня это выглядит нормально. В сообщении об ошибке, которое вы предоставили, что-то говорится об
[disabled]
атрибуте вcatalog.component.html
строке 11. Так что в основном любое выражение, которое вы там использовали, изменилось «слишком рано». В большинстве случаев, насколько я знаю, это происходит при изменении значения выражения внутриngAfterViewInit
.5. на самом деле с реактивными формами более распространенным способом является подписка на
valueChanges
форму в файле ts вместо(change)
обработчиков шаблонов. Я считаю, что это может решить вашу проблему
Ответ №1:
Выражение изменилось после проверки
Вышеуказанная ошибка появляется только в режиме разработки. В рабочей среде этой ошибки нет.
Чтобы удалить эту ошибку в режиме разработки
import ChangeDetectorRef from @angular/core
constructor(private changeDecRef:ChangeDetectorRef) {}
затем
if (event.target.checked) {
this.value.push(key);
} else {
this.value.splice(this.value.findIndex(i => key === i), 1);
}
this.onChange(this.value);
this.onTouched();
/// ADD THIS FUNCTION ///
this.changeDecRef.detectChanges();
}```
Комментарии:
1. Но я не могу не думать, что это связано с проблемой проверки, с которой я сталкиваюсь. Это не объясняет, почему форма действительна, когда она не должна быть.
2. это показывает, что в рабочем режиме что-то может пойти не так. так что вы не можете просто игнорировать это
3. Если я добавлю ваш код, ошибка все еще будет там, и моя проблема останется.
4. @sam вы должны добавить это в файл catalouge.component.ts..
5. Я тоже пробовал это, но тогда больше ничего не работает. FormControls больше не добавляются в форму.