我想基于动态字段配置呈现表单:
$scope.fields = [
{ title: 'Label 1', type: 'text', value: 'value1'},
{ title: 'Label 2', type: 'textarea', value: 'value2'}
];
这应输出行为类似的东西:
<div>
<label>{{field.title}}<br />
<input type="text" ng-model="field.value"/>
</label>
</div>
<div>
<label>{{field.title}}<br />
<textarea ng-model="field.value" rows="5" cols="50"></textarea>
</label>
</div>
简单的实现是使用if
语句为每种字段类型呈现模板。但是,由于Angular不支持if
语句,因此我会指导指令。我的问题是了解数据绑定的工作原理。 documentation for directives有点密集且理论化。
我已经嘲笑了我在这里尝试做的一个简单的例子:http://jsfiddle.net/gunnarlium/aj8G3/4/
问题是表单字段没有绑定到模型,因此submit()中的$ scope.fields不会更新。我怀疑我的指令功能的内容是非常错误的......:)
展望未来,我还需要支持其他字段类型,例如单选按钮,复选框,选择等。
答案 0 :(得分:22)
无论您尝试创建哪个指令,您遇到的第一个问题是在带有表单元素的表单中使用ng-repeat。 ng-repeat如何创建新范围可能很棘手。
This directive creates new scope.
我建议您在部分模板中使用ngSwitch而不是使用element.html。
<div class="form-row" data-ng-switch on="field.type">
<div data-ng-switch-when="text">
{{ field.title }}: <input type="text" data-ng-model="field.value" />
</div>
<div data-ng-switch-when="textarea">
{{ field.title }}: <textarea data-ng-model="field.value"></textarea>
</div>
</div>
由于ng-repeat,这仍然会导致修改子范围中的表单元素的问题,因此我建议在每个元素上使用ngChange方法来设置项目更改时的值。这是我认为AngularJS目前处理得很少的少数项目之一。
答案 1 :(得分:4)
您可以考虑Metawidget。它使用JSON模式,但在其他方面非常接近您的用例。完整样本:
<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js" type="text/javascript"></script>
<script src="http://metawidget.org/js/3.5/metawidget-core.min.js" type="text/javascript"></script>
<script src="http://metawidget.org/js/3.5/metawidget-angular.min.js" type="text/javascript"></script>
<script type="text/javascript">
angular.module( 'myApp', [ 'metawidget' ] )
.controller( 'myController', function( $scope ) {
$scope.metawidgetConfig = {
inspector: function() {
return {
properties: {
label1: {
type: 'string'
},
label2: {
type: 'string',
large: true
}
}
}
}
}
$scope.saveTo = {
label1: 'value1',
label2: 'value2'
}
$scope.save = function() {
console.log( $scope.saveTo );
}
} );
</script>
</head>
<body ng-controller="myController">
<metawidget ng-model="saveTo" config="metawidgetConfig">
</metawidget>
<button ng-click="save()">Save</button>
</body>
</html>
答案 2 :(得分:0)
当元素超出DOM时,可以更改Test
属性,那么为什么不从DOM中删除它的小指令,更改它的类型然后再添加到同一个地方?
type
是可选的,因为目标可以动态更改一次而不是不断更改。
$watch
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.rangeType = 'range';
$scope.newType = 'date'
});
app.directive('dynamicInput', function(){
return {
restrict: "A",
link: linkFunction
};
function linkFunction($scope, $element, $attrs){
if($attrs.watch){
$scope.$watch(function(){ return $attrs.dynamicInput; }, function(newValue){
changeType(newValue);
})
}
else
changeType($attrs.dynamicInput);
function changeType(type){
var prev = $element[0].previousSibling;
var parent = $element.parent();
$element.remove().attr('type', type);
if(prev)
angular.element(prev).after($element);
else
parent.append($element);
}
}
});
span {
font-size: .7em;
}
在最新的Chrome和IE11中测试过。