Как включить поля ввода из пользовательских директив в угловые формы?

Мне нужно создать простую форму с такими проверками: https://jsfiddle.net/rohansh20/k7omkz7p /2/

<div ng-app="module1" ng-controller="ctrl1 as vm">
  <form novalidate name="vm.form1" class="css-form">
    <label>Name:
      <input type="text" name="Name" ng-model="vm.user.name" required />
    </label>
    <br />
    <label>E-mail:
      <input type="email" name="Email" ng-model="vm.user.email" required />
    </label>
    <br />
    <input type="submit" ng-click="vm.save(vm.form1, vm.user)" value="Save" />
  </form>
  <div>
    {{vm.result}}
  </div>  
  <pre>form = {{vm.form1 | json}}</pre>
</div>


angular.module('module1', []);

angular.module('module1').controller('ctrl1', function() {
  this.save = function(form, user) {
    if(form.$invalid) {
        this.result = 'Please correct the data entered';
      return;
    }
    this.result = 'User ' + user.name + ' with email ' + user.email + ' saved successfully';
  };
});

Но мне нужно динамически генерировать поля ввода. Поэтому я сделал директиву, которая преобразуется в поле ввода любого типа — https://jsfiddle.net/rohansh20/hdxj0np6/3/

<div ng-app="module1" ng-controller="ctrl1 as vm">
  <form novalidate name="vm.form1" class="css-form">
    <custom-input name="Name" type="text" model="vm.user.name" required="true">
    </custom-input>
    <br />
    <custom-input name="Email" type="email" model="vm.user.email" required="true">
    </custom-input>
    <br />
    <input type="submit" ng-click="vm.save(vm.form1, vm.user)" value="Save" />
  </form>
  <div>
    {{vm.result}}
  </div>
  <pre>form = {{vm.form1 | json}}</pre>
</div>

var app = angular.module('module1', []);

app.controller('ctrl1', function() {
  this.save = function(form, user) {
    if(form.$invalid) {
        this.result = 'Please correct the data entered';
      return;
    }  
    this.result = 'User ' + user.name + ' with email ' + user.email + ' saved successfully';
  };
});

app.directive('customInput', function($compile) {
  return {
    restrict: 'E',
    link: function(scope, element, attributes) {
      var labelElement = angular.element('<label/>'),
        name = attributes.name,
        type = attributes.type,
        ngModelString = attributes.model,
        required = attributes.required,
        inputElement = angular.element('<input/>');
      inputElement.attr('ng-model', ngModelString);
      inputElement.attr('name', name);
      inputElement.attr('type', type);
      if (required) {
        inputElement.attr('required', 'required');
      }
      labelElement.append(name + ': ');
      labelElement.append(inputElement);
      $compile(labelElement)(scope);
      element.replaceWith(labelElement);
    }
  }
});

Скрипки — это упрощенные версии того, что я пытаюсь сделать. Проблема в том, что эти поля, даже несмотря на то, что они скомпилированы и отрисованы идеально (что можно увидеть при просмотре HTML), не включаются в состав родительского элемента управления формы. Это можно увидеть в отображаемом объекте управления формой в обеих скриптах. Из-за этого невозможно определить действительность формы, и обе формы ведут себя по-разному при отправке неверных данных.

Мне нужно, чтобы элемент управления формы во второй скрипке имел правильные значения для своих свойств и имел дочерние элементы управления и их свойства, как в первой скрипке. Возможно ли это даже с помощью пользовательской директивы? Что мне нужно изменить, чтобы это заработало?

Примечание. Директива будет включать сложные операции для динамического создания HTML, поэтому это необходимо сделать в функции ссылки директивы. Шаблон директивы с несколькими ngIf просто не будет работать.


person Rohan Sharma    schedule 20.01.2017    source источник


Ответы (1)


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

В вашей директиве

    (function () {
    'use strict';

    angular
        .module('myApp')
        .directive('customInput', customInput)





    customInput.$inject = ['$compile'];
    /* @ngInject */
    function customInput ($compile) {


        var directive = {
            templateUrl: 'app/custom-input.html',
            restrict: 'E',
            transclude: true,
            require: "?^form",
            compile: compile,
            controller:CustomInputController,
            controllerAs:'vm',
            scope:{
                inputType:'=',
                inputValue:'='
            }
        };

        return directive;
        function CustomInputController($scope){
            var vm = this;


        }
        function compile(element, attributes){

            return {
                pre: preLink,
                post: postLink
            }
        }
        function preLink (scope,element,attrs, form, transclude){

        }
        function postLink (scope,element,attrs, form, transclude){
            scope.currentForm = form;

            $compile(element.contents())(scope);
        }
    }

})();

В вашем директивном html-шаблоне

<input type="inputType" ng-model="inputValue">

Когда вы называете свою директиву

   <br-input type="text"
          input-value="vm.user.email"
          inputname="name"
          input-required ="true">
   </br-input>
person Salih Şenol Çakarcı    schedule 20.01.2017