表单将无法识别自定义输入指令

时间:2017-10-28 00:46:33

标签: angularjs

我正在尝试创建一个动态生成表单的系统。我创建了一个指令,它从输入id中查找有关输入字段的元数据并为该字段生成模板。输入工作正常,但表单不识别它存在。它没有考虑到表单的计算。$ valid等。编译和链接之间发生了什么神秘的事情,这使表单识别输入?

这是简化的代码: 请参阅以下内容:Plunker

<form name="myForm">
  works: <input type="text" ng-model="model.works" required></input>
  <div ng-repeat="inp in inputList">
      broken: <my-component info="inp"></my-component>
  </div>
  form valid: {{myForm.$valid}}
</form>

app.controller('MainCtrl', function($scope) {
  $scope.model = {
    works:'works',
    broken:'broken',
  };
  $scope.inputList = [
    {id:'broken'},
  ];
});

app.directive('myComponent', function($compile) {
  return {
    restrict: 'E',
    scope: {
        'info': '='
    },
    link: function($scope, $element, $attrs) {
        var html = '<input type="text" ng-model="model.'+ $scope.info.id +'" required></input>';
        $scope = $scope.$parent.$parent;
          // ^ this hack makes the model work, but form still not attached
        var el = $compile(html)($scope);
        $element.replaceWith(el);
    }
  };
});

2 个答案:

答案 0 :(得分:0)

你想到的神秘事物是&#34;范围&#34;。 AngularJS&#34;范围&#34;将模型,视图和控制器粘合在一起。在您发布的代码中,有3个不同的范围需要考虑。 &#34; MainCtrl&#34;范围。我们称之为“scope01&#39;”。 &#34; ng-repeat&#34;为每次迭代创建一个新范围。我们称之为&#39; scope02&#39;因为你的数组中只有一个项目。最后,您的指令有一个isolate scope。我们称之为&#39; scope03&#39;。

指令中的变量需要遍历两个范围才能返回到&#34; MainCtrl&#34;控制器scope01。这就是为什么你的hack需要两个&#34; $ parent&#34;调用。 &#34; myForm的&#34;对象位于&#39; scope01&#39;中。它将由&#39; scope02&#39;继承。但需要传递到范围03&#39;。您需要将更改冒泡到&#39; scope01&#39;通过双重绑定参数或使用事件来&#34;广播&#34;对输入的更改。

以下是使用参数和双重绑定的示例:

<my-component info="inp" form-ref="myForm">

在你的指令中:

var directive = {
restrict: 'E',
scope: {
  'info': '=',
  'formRef': '='
},
link: function(scope, element, attributes) {
  //You may want to wrap the following  in a watch:
  formRef.$valid = myService.isValid(scope.info);// myService checks if input is valid and returns true or false
}
};

答案 1 :(得分:0)

我找到了解决方案,以防其他人遇到此问题:

    var el = $compile(html)($scope.$parent, function(_el) {
      $element.replaceWith(_el);
    });

更新了Plunker