3

我正在 AngularJS 中实现一个表单构建器,需要在运行时插入和重新排序指令。甚至不知道从哪里开始寻找 - 所有示例似乎都只展示了指令的静态树。实现动态行为的两个选项是:a)动态编译和插入模板,b)使用所有可能指令的巨大 ng-switch。两种方式都很丑。

任何人都可以提出更好的实施方案吗?

下面是我认为 formbuilder 在理想世界中应该如何看待的 JS 和 html 代码,请帮我填写 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>
4

1 回答 1

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) ); 
      }
    };
 })
于 2013-05-03T00:18:59.587 回答