Как стать автором
Обновить

Комментарии 10

НЛО прилетело и опубликовало эту надпись здесь
Спасибо за статью!

У меня возник вопрос. Допустим, наш компонент реализован с использованием реактивной формы внутри и поддерживает валидаторы. Существует ли стандартный подход для поддержки метода markAsTouched в таком компоненте?

Объясню проблему… На кастомный контрол, в родительской форме, установлен валидатор, проверяющий пустое значение. Далее вызывается метод markAsTouched. Контрол в родительской форме становится invalid, так как значение пустое. Однако статус внутренней формы кастомного контрола не меняется, соотвественно не выполняется поведение при статусе invalid. Есть ли способ задавать коллбек для метод markAsTouched по аналогии с onChange?
Существует ли стандартный подход для поддержки метода markAsTouched в таком компоненте?

Touched событий у формы в принципе нету… Но как всегда есть костыль — можно проверять touched внутри DoCheck и обновлять внутреннюю форму. Правда в этом случае есть проблемы с тем как получить ссылку на внешний FormControl, легче и лучше всего это сделать через @Input() formControl (правда оно не будет работать с formControlName, но зато максимально прозрачно и без костылей...)

Так и делал, но что-то мне подсказывает, что я решаю задачу неправильно. Либо не стоит использовать реактивную форму внутри, либо есть возможность иначе связать родительскую форму с внутренней.

Всё нормально, расслабьтесь, это ангуляр, тут подобных костылей на каждом шагу по десятку...

Ну а если серьезно, то


либо есть возможность иначе связать родительскую форму с внутренней.

Никак.


Либо не стоит использовать реактивную форму внутри

Это зависит от того что вам надо, возможно, в вашем случае можно заменить родительный контрол на FormGroup (которая сейчас внутри), это решит проблемы с touched, но в сложных формах, когда это невозможно — только костылить пытаясь заставить это всё работать....

Спасибо за ваш интерес к статье!

Если я правильно вас понял, то есть необходимость в обработке ошибок внутри кастомного контрола
Для этого вам нужна ссылка на FormControl из внешней формы
Сделать это достаточно просто с DI (и долей грязной черной магии)

в классе кастом контрола инжектим:
constructor(
    @Optional() @Self() public control: NgControl
  ) {
    if (control) {
      control.valueAccessor = this; // иначе ошибка Uncaught Error: Template parse errors: Cannot instantiate cyclic dependency! NgControl
    }
} 


и в метаданных убираем провайдер NG_VALUE_ACCESSOR. Взято отсюда.
registerOnTouched(fn: any)  — аналогично registerOnChange, определяет обработчик на touch-события
Что вы имеете в виду по touch-событиями?
registerOnTouched на самом деле определяет обработчик onBlur: angular.io/api/forms/ControlValueAccessor#registerOnTouched
Спасибо за ваш комментарий!
Действительно была неточность, вы правы
Статью поправил.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации