2013-05-02 66 views
3

我正在AngularJS中實現表單構建器,並且需要在運行時插入和重新排序指令。 甚至不知道從哪裏開始尋找 - 所有的例子似乎只是演示靜態的指令樹。實現動態行爲的兩個選項是:a)即時編譯和插入模板,以及b)使用所有可能指令的巨大ng開關。兩種方式都很醜陋。如何將角度指令存儲在作用域變量中?

任何人都可以提出更好的實施?

以下是JS和html代碼,我認爲formbuilder應該在理想世界中看起來,請幫我填寫3個TODO實例。

JSFiddle的JavaScript:

angular.module('components', []) 
    .directive('checkbox', function() { 
    return { 
     restrict: 'E', 
     template: '<div class=f><input type=checkbox>{{name}}</input></div>' 
    }; 
    }) 
    .directive('textfield', function() { 
    return { 
     restrict: 'E', 
     template: '<div class=f><input type=text placeholder="{{name}}"></input></div>' 
    }; 
    }) 

function FormBuilder($scope, $locale) { 
    $scope.title = 'test form'; 
    $scope.fields = []; 
    $scope.add_checkbox = function() { 
     console.log('adding checkbox'); 
     var field = null; // TODO: how do I instantiate a directive? 
     $scope.fields.push(field); 
    }; 
    $scope.add_textfield = function() { 
     console.log('adding textfield'); 
     var field = null; // TODO: how do I instantiate a directive? 
     $scope.fields.push(field); 
    }; 
} 

HTML:

<div ng-app=components ng-controller=FormBuilder> 
    <button ng:click="add_checkbox()">new checbox</button> 
    <button ng:click="add_textfield()">new text field</button> 
    <h3>{{ title }}</h3> 
    <checkbox></checkbox> 

    <textfield></textfield> 

    <div ng:repeat="field in fields"> 
     <!-- TODO field.get_html() - how? --> 
    </div> 
</div> 

回答

2

我認爲你有幾種方法可以做到這一點,你提到的。既然你不想做,你可以創建一個開關每個指令的模板文件。即checkbox.html,textfield.html並把每個指令。然後用['checkbox.html', 'textarea.html']填充您的域陣列,當你在你的循環加你只是單純的<div ng-include='field'></div>

這裏是一個演示:http://plnkr.co/edit/w6n6xpng6rP5WJHDlJ3Y?p=preview

您還可以創建在您輸入型通並將其注入到另一個指令模板。這裏就是一個演示,讓您避免申報模板,讓一條指令創建它們基於字段類型:

http://plnkr.co/jhWGuMXZTuSpz8otsVRY

<div ng:repeat="field in fields"> 
    <master-field type='field'></master-field> 
</div> 

該主場指令只是編譯基於模板字段的值。

.directive('masterField', function($compile) { 
    return { 
     restrict: 'E', 
     replace:true, 
     transclude: true, 
     scope:{ 
     type:'=' 
     }, 
     template: '<div></div>', 
     controller: function ($scope, $element, $attrs) {}, 
     link: function(scope, element, attrs) { 

     element.append($compile('<' + scope.type+ '/></' +scope.type + '>')(scope)); 
     } 
    }; 
}) 
+0

很好的答案,謝謝你花了這麼多時間。還有一點是我缺少的是如何將特定於字段的數據綁定到動態模板?我的意思是如果$ scope.fields = [{type:'checkbox',name:'agree',selected:false},{type:'textfield',name:'email',defvalue:'[email protected]'} ],我希望模板內的{{name}}解析爲字段的名稱,而不是最頂層控制器的$ scope.name。我如何實現這樣的事情? – Paul 2013-05-03 02:08:08

+0

我認爲這是一個很好的問題,但都是一個單獨的問題。您的指令都沒有構建爲一個範圍:http://docs.angularjs.org/guide/directive#directivedefinitionobject – lucuma 2013-05-03 13:15:27

+0

您可能需要檢查此問題:http://stackoverflow.com/questions/16358706/using-指令 - 內部指令 - 原因 - 綁定 - 問題 – lucuma 2013-05-03 13:48:55