如何使用指令和可重复使用的参数创建可重复使用的窗体小部件?喜欢这个:
<form> <special-input label-text="A Special Input" bind-to="data.special"></special-input> <special-input label-text="Specialer" bind-to="data.moreSpecial"></special-input> </form>
指令模板似乎不允许在ng模型上插值.
此外,您可以模块化和参数化表单行为,以便您可以使用标准的POST操作?
根据我的实验,我已经回答了下面的问题,但是我暂停接受一段时间,因为我对Angular很新,并希望听到别人的话.
<body ng-app="TestApp"> <form ng-controller="FormCtrl" name="testForm"> <input name="firstInput" ng-model="data.first"> <input name="secondInput" ng-model="data.second"> <button ng-click="submit()">Submit</button> </form> </body>
JS:
var app = angular.app('TestApp',[]); app.controller('FormCtrl',function($scope) { $scope.submit = function() { // Form submit logic here console.log("Submitting the form"); console.log($scope); } })
这将为表单创建一个范围,因为表单标签包含ng-controller标签.在范围内,testForm是表单的javascript对象,testForm.firstInput是第一个输入的javascript对象.看起来这些对象也有一些可用的验证功能,see docs here.
窗体上的数据将作为FormCtrl范围中的对象数据提供,键为“first”和“second”,您可以在控制器中定义方法.
您也可以使用相同的FormCtrl放置多个表单,并且似乎Angular将为每个表单创建新的实例,因此您不必担心表单会污染对方的数据.
使用指令
现在假设我们有一种在指令中实现的复杂的输入或小部件.此示例使用两个选择框来显示状态中的所有城市.您必须首先选择一个状态,然后它将查询该州的城市并填充第二个选择框.
app.directive('citySelect',function() { return { replace: true,template: '<div><select ng-change="getCities()" ng-options="s.name for s in states"></select>' + '<select ng-model="data.selectedCity" ng-options="c.name for c in cities"></select>',controller: function($scope) { // Omitting the logic for getCities(),but it'd go here } }; })
然后你可以把它粘贴到表单标签,它会工作.因为该指令没有定义一个范围,它只会附加到FormCtrl的范围.
<body ng-app="TestApp"> <form ng-controller="FormCtrl" name="testForm"> <input name="firstInput" ng-model="data.first"> <input name="secondInput" ng-model="data.second"> <div city-select></div> <button ng-click="submit()">Submit</button> </form> </body>
对指令进行参数化
编辑:
显然这样做是有效的:
scope: {someParameter: "="},template: '<div><select ng-model="someParameter"></select></div>'
你只需要在没有curlies的情况下执行,它会绑定.我的猜测是父范围是绑定到子范围中的someParameter,然后select被绑定到子范围中的somParameter.
=====
但是这个问题是我的citySelect指令有一个硬编码的ng模型绑定,所以如果我创建了一些通用的小部件,我不能使用一个以上的形式.不幸的是,这似乎不起作用:
scope: {someParameter: "="},template: '<div><select ng-model="{{ someParameter }}"></select></div>'
我已经得到这个工作的唯一方法是在链接函数中手动构建DOM元素,但我不知道这是否可行.我会感谢任何人关于这个实现的意见:
<body ng-app="TestApp"> <form ng-controller="FormCtrl" name="testForm"> <input name="firstInput" ng-model="data.first"> <input name="secondInput" ng-model="data.second"> <div city-select bind-to="data.homeCity"></div> <div city-select bind-to="data.workCity"></div> <button ng-click="submit()">Submit</button> </form> </body> app.directive('citySelect',function($compile) { return { replace: true,template: '<div></div>',but it'd go here } link: function(scope,iElem,iAttrs) { var html = '<div><select ng-bind="' + iAttrs['bindTo'] + '"></div>'; iElem.replaceWith($compile(html)(scope)); } }; })
在表单上混合参数
由于为每个表单创建了单独的FormCtrl实例,因此可以在FormCtrl中重用很多功能.但是,您还可以在表单标签上使用其他指令来添加参数或分离功能.例如:
<form ng-controller="FormCtrl" name="testForm" post-form post-path="/path/to/resource/"> app.directive('postForm',function() { return { controller: function($scope) { $scope.post = function() { // Some generic POST behavior }; },link: function(scope,iAttr) { scope.postPath = iAttr['postPath']; },}; });
然后窗体的范围将从FormCtrl和postForm组合范围,以便一切都可访问.在我的实验中,FormCtrl看起来像是优先的,所以如果在FormCtrl和PostForm中定义了一些像$scope.submit()这样的东西,那么FormCtrl会优先考虑)(也就是说,这是异步加载的一个竞争条件,不知道
而不是使用ng控制器,我想你也可以使用范围:true在mixin指令(postForm)或者更安全的范围:{}.