Правильный способ, по-видимому, заключается в том, что A
реализует интерфейс ControlValueAccessor
.
export class A implements OnInit, AfterViewInit, ControlValueAccessor {
...
...
}
"" * * * SelectControlValueAccessor
, который заботится о тексте inputs
и textareas
, *1009* который обрабатывает select
входные данные или CheckboxControlValueAccessor
, который, как ни удивительно, имеет дело с checkboxes
и т. д. Поэтому для этих элементов пользовательского интерфейса нам не нужно создавать средства доступа к значениям, а для пользовательских компонентов нам нужны создать собственный метод доступа "- https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html
Пояснение - я прошу formB
принять значение A
и сопоставить его с field5
из formB
. Но Angular
не знает, каково значение A
. Для input
полей Angular
уже знает, что значение текстового поля - это значение, которое отображается в элемент управления формы. Но для пользовательских компонентов мы должны явно указать Angular
, какое значение генерирует пользовательские компоненты, которое сопоставляется с полем form
. Это делается путем реализации интерфейса ControlValueAccess
.
Интерфейс имеет 3 важных метода. 1) writeValue
, который показывает способ изменения пользовательского интерфейса при изменении модели. Скажем, пользовательский интерфейс пользовательского компонента представлял собой ползунок с левым концом, означающим 0%, и правым концом, означающим 100%. Если модель изменит свое значение на 10/100, то пользовательский интерфейс должен опуститься до 10%. Обновите этот метод, чтобы изменить пользовательский интерфейс. В моем случае мне ничего не нужно было делать, потому что направление ввода данных в моем случае - UI для моделирования, а не модель для UI (моя модель не создает текст, который должен быть заполнен в текстовой области.
writeValue(value:any){
console.log('write value called with value ',value);
}
2) registerOnChange
- это обратное значение writeValue
. Всякий раз, когда изменяется пользовательский интерфейс, модель также должна быть изменена. В моем случае, когда пользователь пишет в текстовом поле, я хочу обновить свою модель. «Angular предоставляет вам функцию и просит ее вызывать всякий раз, когда в вашем компоненте изменяется новое значение, чтобы он мог обновить элемент управления». - https://netbasal.com/angular-custom-form-controls-made-easy-4f963341c8e2
В моем случае я хочу распространить изменения, после чего нажимается кнопка сохранения A
(тогда вызывается onSaveAnswer
). Я хочу распространить значение всех сохраненных ответов в это время
answers:Array<AnswerInformation>;
propagateChange = (_: any) => {};
registerOnChange(fn) {
console.log('registerOnchange called');
this.propagateChange = fn;
}
inSaveAnswer(){
...
this.propagateChange(this.answers);
}
Полученное значение отображается в поле формы, в которое отображается A
.
<A #a [readonlyFormStatus]="readonlyFormStatus" (answerSectionsEmitter)="handleAEvent($event)" class="form-control" formControlName="field5" [ngClass]="validateField('field5')" ></A>
field5
будет содержать предложенные значения (this.answers). его структура будет Array<AnswerInformation>;
, т.е. field5:Array<AnswerInformation>;
Я мог бы добавить дополнительную проверку, что field5
не является пустым массивом, как, например, так:
field5: [null, this.validateField5IsProvided]
validateField5IsProvided(control:AbstractControl) {
const f5:Array<AnswerInformation> = control.value;
if(f5){
if(f5.length !== 0){
// console.log('answer field is valid');
return null;
} else {
return {
validateAnswerIsSaved: { // check the class ShowErrorsComponent to see how validatePassword is used.
valid: false,
message: 'The field can\'t be empty. Please make sure to save the field'
}
};
}
} else {
return {
validateAnswerIsSaved: {
valid: false,
message: 'The fieldcan\'t be empty. Please make sure to save the field'
}
};
}
}
Есть еще пара функций, которые требуют также будет реализовано
registerOnTouched() {
console.log('registerOnTouched called');
}
setDisabledState(isDisabled: boolean): void {
console.log('set disabled called with value ',isDisabled);
this.editor.setReadOnly(isDisabled);
}