Компоненты Angular как самопроверяющаяся форма

Я не уверен, есть ли лучший способ сделать это, я полагаю, что он должен быть. В основном у меня есть компонент, который я хочу рассматривать как автономный элемент управления формой. К этому элементу управления всегда будет прикреплена какая-то специальная проверка, и я хотел бы, чтобы она всплывала в форме при каждом использовании компонента.

Я прикрепил плунжер. Есть ли способ пометить форму как недопустимую, если компонент / 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.');
  }
}

взгляните на подход angular / material. Они отделяют поля формы от директивы mat-error: github.com/angular/material2/blob/…

masterfloda 09.03.2018 19:36

@masterfloda Спасибо за информацию. У меня есть что-то подобное, чтобы показать, что у элемента управления есть ошибка, но мне действительно нужно, чтобы элемент управления влиял на свойство valid в самой форме, поскольку я не хочу, чтобы ngSubmit запускался до тех пор, пока форма не станет действительной. Имеет ли это смысл?

jensengar 09.03.2018 19:42

Да, но я бы не стал делать валидацию частью компонента поля. Просто используйте проверку формы Angular angular.io/guide/form-validation#reactive-form-validation. Или я как-то упускаю из виду главное?

masterfloda 09.03.2018 19:49

Я может делаю это. Я просто пытался избежать этого, потому что этот компонент будет использоваться в нескольких местах, и я знаю, что на днях я забуду добавить валидатор в форму. Я просто надеялся, что есть способ ВСЕГДА проверять этот компонент.

jensengar 09.03.2018 20:05

В этом есть смысл ... Я сам не пробовал, так что это всего лишь предположение, но вы можете использовать метод setError из FormControlangular.io/api/forms/AbstractControl#setValue

masterfloda 09.03.2018 20:29

К сожалению, я пробовал это раньше, и просто попробовал снова в плункере, чтобы проверить. Вызов setErrors на MyComponentComponent не всплывает в форму. Я полагаю, это потому, что formControl в компоненте не связан напрямую с formControl, указанным в родительской форме.

jensengar 09.03.2018 21:48
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
6
785
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Одним из решений может быть использование метода 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();
    }
  }); 
}

Пример ng-run

Это в основном именно то, что я искал. Спасибо.

jensengar 09.03.2018 22:05

Другие вопросы по теме