Я не уверен, есть ли лучший способ сделать это, я полагаю, что он должен быть. В основном у меня есть компонент, который я хочу рассматривать как автономный элемент управления формой. К этому элементу управления всегда будет прикреплена какая-то специальная проверка, и я хотел бы, чтобы она всплывала в форме при каждом использовании компонента.
Я прикрепил плунжер. Есть ли способ пометить форму как недопустимую, если компонент / formControl недействителен? Я знаю, что могу добавить валидатор к самой форме, но я хотел бы упростить работу и сделать ее более предсказуемой для будущего использования этого компонента. Я также открыт для лучших идей сделать это.
@Component({
selector: 'my-app',
template: `
<form [formGroup] = "form">
<my-component-control formControlName = "myComponent"></my-component-control>
</form>
<div>Form Value: {{form.value | json}}</div>
<div>Form Valid: {{form.valid}}</div>
`,
})
export class App {
constructor(fb: FormBuilder) {
this.form = fb.group({
myComponent: ''
});
}
}
@Component({
selector: 'my-component-control',
template: `
<div>Control Errors: {{control.errors | json}}</div>
<input [formControl] = "control">
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => MyComponentComponent),
}
]
})
export class MyComponentComponent implements ControlValueAccessor {
control: FormControl;
onChange: any = () => { };
onTouched: any = () => { };
constructor() {
this.control = new FormControl('', (control) => {
return control.value ? null : {shouldHaveSomething: true};
});
this.control.valueChanges.subscribe((value) => {
this.onChange(value);
this.onTouched();
});
}
writeValue (obj: any): void {
this.control.setValue(obj);
}
registerOnChange (fn: any): void {
this.onChange = fn;
}
registerOnTouched (fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
throw new Error('Method not implemented.');
}
}
@masterfloda Спасибо за информацию. У меня есть что-то подобное, чтобы показать, что у элемента управления есть ошибка, но мне действительно нужно, чтобы элемент управления влиял на свойство valid в самой форме, поскольку я не хочу, чтобы ngSubmit запускался до тех пор, пока форма не станет действительной. Имеет ли это смысл?
Да, но я бы не стал делать валидацию частью компонента поля. Просто используйте проверку формы Angular angular.io/guide/form-validation#reactive-form-validation. Или я как-то упускаю из виду главное?
Я может делаю это. Я просто пытался избежать этого, потому что этот компонент будет использоваться в нескольких местах, и я знаю, что на днях я забуду добавить валидатор в форму. Я просто надеялся, что есть способ ВСЕГДА проверять этот компонент.
В этом есть смысл ... Я сам не пробовал, так что это всего лишь предположение, но вы можете использовать метод setError из FormControlangular.io/api/forms/AbstractControl#setValue
К сожалению, я пробовал это раньше, и просто попробовал снова в плункере, чтобы проверить. Вызов setErrors на MyComponentComponent не всплывает в форму. Я полагаю, это потому, что formControl в компоненте не связан напрямую с formControl, указанным в родительской форме.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Одним из решений может быть использование метода setValidators на хосте AbstractControl.
Для этого я собираюсь получить ссылку на AbstractControl через NgControl. Мы не можем просто внедрить NgControl в конструктор, потому что у нас возникнут проблемы с созданием экземпляра циклической зависимости.
constructor(private injector: Injector) {
...
}
ngOnInit() {
Promise.resolve().then(() => {
const hostControl = this.injector.get(NgControl, null);
if (hostControl) {
hostControl.control.setValidators(this.control.validator);
hostControl.control.updateValueAndValidity();
}
});
}
Это в основном именно то, что я искал. Спасибо.
взгляните на подход angular / material. Они отделяют поля формы от директивы
mat-error: github.com/angular/material2/blob/…