我希望字段的标签与字段验证属性进行一些交互。 我创建了一个工作示例的插件。
http://plnkr.co/edit/oNq5lmjtjRDaEkzKsrR2?p=preview
但在此示例中,fieldname是硬编码的。
我尝试通过范围变量将fieldname设置为模板。这不起作用:
http://plnkr.co/edit/yEl04xyFR5RWYCmI2bMH?p=preview
HTML:
<form name="myForm" ng-controller="ctrl">
<fieldset field-name="{{model.fieldName}}" label-text="{{model.label}}" ng-model="model.value">
<fieldset>
</form>
JavaScript的:
var app = angular.module('myApp',[]);
app.directive('fieldset', function(){
return {
template: '<label ng-class="{invalid:$parent.myForm[{{fieldName}}].$invalid}">{{lbl}}</label>: ' +
'<input name="{{fieldName}}" ng-model="value" required>',
restrict : 'E',
scope : {
value : '=ngModel',
lbl : '@labelText',
fieldName : '@'
},
link : function(scope, elem, attrs) {
console.log(scope.$parent.myForm);
}
}
})
app.controller('ctrl', function($scope) {
$scope.model = {
fieldName : 'myField',
label : 'Label for Field',
value : 6
}
});
范围内的字段名称。$ parent.myForm是“{{fieldName}}”而不是“myField”。但是在DOM中,fieldname按预期分配。 我该如何解决这个问题?
答案 0 :(得分:4)
Stewie绝对正确。如果创建了ng-model指令,它将立即在表单中注册。如果你看一下角度源,你会发现ngModel是通过它们在数组form
中的当前名称注册的:
if (control.$name) {
form[control.$name] = control;
}
在您的情况下,这是“{{fieldName}}”。无法更改此name
,因为它是数组中的键。那么我们可以做些什么来改变这个呢?如果我们查看 FormController API ,我们可以看到有删除($removeControl
)或添加($addControl
)控件的函数。这两个函数都需要NgModelController作为输入参数。例如。角度为我们的输入元素创建的NgModelController。我们可以通过以下方式访问此控制器:
var modelController = inputElement.controller('ngModel');
我认为我们现在已经掌握了所有信息来编写指令:
app.directive('fieldset', function(){
return {
template: '<label ng-class="{invalid:form[fieldName].$invalid}">{{lbl}}</label>: ' +
'<input name="{{fieldName}}" ng-model="value" required>',
restrict : 'E',
require: '^form', // we need the parent NgFormController
scope : {
value : '=ngModel',
lbl : '@labelText',
fieldName : '@'
},
link : function(scope, elem, attrs, formCtrl) {
// get the NgModelController for the input element
var modelCtrl = elem.find('input').controller('ngModel');
// remove the ModelController from the FormController
formCtrl.$removeControl(modelCtrl);
// set the right name
modelCtrl.$name = scope.fieldName;
// add the namend ModelController to the FormController
formCtrl.$addControl(modelCtrl);
// publish the FormController to the scope - so we don't need to mess around with the parent scope.
scope.form = formCtrl;
}
}
})
我还建议将NgFormController发布到指令范围。所以你可以写下你的css条件:
form[fieldName].$invalid
instad of:
$parent.myForm[fieldName].$invalid
它更通用,因为您不需要知道表单的名称。
答案 1 :(得分:2)
ng-form
指令。这就是为什么如果要使用角度形式验证,就不能拥有动态字段名称。
但是,在动态创建表单字段(通过ng-repeat
)时,字段实际上不需要具有唯一的name
属性。那是因为你被允许将每个表单元素包装到它自己的私有 ng-form范围中:
app.controller('MainCtrl', function($scope) {
$scope.fields = [
{label: 'First Name', required: false},
{label: 'Last Name', required: false},
{label: 'Email', required: true}
];
});
<body ng-controller="MainCtrl">
<form name="form" class="form-horizontal" ng-submit="save()" novalidate>
<div class="form-group" ng-repeat="field in fields" ng-form="form">
<label class="control-label" ng-class="{required: field.required}">{{field.label}}</label>
<input
type="text"
name="field"
ng-model="field.value"
class="form-control"
ng-required="field.required"
/>
<span
class="help-block error"
ng-show="form.field.$dirty && form.field.$error.required"
>{{field.label}} is required</span>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Save changes</button>
<button type="button" class="btn">Cancel</button>
</div>
</form>
</body>