Передача формы компоненту AngularJS для проверки

Я перемещаю свою базу устаревшего кода на новую архитектуру компонента, продвигаемую с помощью AngularJS 1.5. Я столкнулся с проблемой, когда делаю это для больших форм. Традиционно, я бы добавил подтверждение формы следующим образом:

<form name="myForm">
  <input type="text" name="input1" ng-model="vm.input1" required />
  <div ng-messages="myForm.input1.$error">
    <div ng-message="required">Please fill out this field.</div>
  </div>
  <!-- many more inputs -->
</form>

При переходе к компонентной архитектуре я должен явно передать форму компоненту:

<form name="vm.myForm">
  <my-awesome-input-component model="vm.input1" form="vm.myForm"><my-awesome-input-component>
  <!-- many more inputs -->
</form>

Я хотел бы избежать загрязнения vm моей формой. Есть ли лучший способ достичь желаемой архитектуры компонентов для форм?

Ответы

Ответ 1

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

Как следует из комментария Иина Рида, вам не нужно использовать vm для этого. Вы просто назовите форму, которую хотите, а затем передадите это имя своему компоненту, чтобы он выглядел следующим образом:

<form name="myForm" ng-submit="ctrl.someFunction()" novalidate>
   <my-input form-reference="myForm"></my-input>
   <button type="submit">Some button</button>
</form>

Убедитесь, что вы пишете "novalidate" в своей форме, чтобы отключить проверки браузера по умолчанию, если вы хотите самостоятельно обрабатывать проверки (которые, по вашему мнению, вы используете ng-сообщения, которые, как я думаю, вы делаете).

Затем оттуда на моем компоненте я бы написал что-то вроде:

angular.module("myApp")
  .component("myInput",{
     templateUrl:'path/to/template.html'
     bindings:{
       formReference:'<',
       myInputModel:'<',
       onUpdate:'&'
     },
     controller: MyInputController
  }

И затем в шаблоне ввода:

<input type="text" name="myInput" ng-model="$ctrl.myInputModel" ng-change="$ctrl.update($ctrl.myInputModel)" required />
<div ng-messages="$ctrl.formReference.myInput.$error">
  <div ng-message="required">Please fill out this field.</div>
</div>

Несколько дополнительных заметок о привязках и способах передачи и обновления моделей:

  • '<': означает одностороннее связывание, которое Angular говорит использовать для всех компоненты с этого момента. Чтобы обновить значение и иметь два пути мы должны включить функцию onUpdate.
  • onUpdate: '&' я говорю здесь, что я пройду функция для обновления модели (обратный вызов для событий компонента).

Итак, в контроллере ввода я бы написал что-то вроде:

function MyInputController(){
    var ctrl = this;
    ctrl.update = function(value){
        ctrl.onUpdate({value: value});
    };
}

И, наконец, когда я использую свой компонент внутри формы:

<form name="myForm" ng-submit="ctrl.someFunction()" novalidate>
   <my-input form-reference="myForm" my-input-model="ctrl.anyModelIWant" on-update="ctrl.updateMyInput(value)"></my-input>
   <button type="submit">Some button</button>
</form>

И контроллер формы будет иметь функцию:

...
ctrl.updateMyInput = function(value){
   ctrl.anyModelIWant = value;
}
...

Официальные документы: https://docs.angularjs.org/guide/component

Я надеюсь, что все это поможет кому-то: -)