我正在尝试创建一个动态生成表单的系统。我创建了一个指令,它从输入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);
}
};
});
答案 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