1

我已经为表单字段创建了一个动态的templateUrl,我试图在ng-repeat中附加ng模型。父指令和表单字段指令都可以工作并生成,但是当我使用ng模型时,它似乎不工作,预输出不会改变?在这个用例中应用ng-model有一个窍门吗?它工作,如果我只是使用硬编码的形式输入。我一直在关注AngularJS文档中的example。围绕表单字段AngularJS ng模型不工作在动态创建的输入字段

周边标记:

<form role="form" ng-controller="FormController as formCtrl" novalidate> 

    <div ng-repeat="field in panel.form_fields"> 

     <form-field field="field"></form-field> 

    </div> 

    <fieldset class="form-group clearfix"> 
     <button type="submit" class="btn btn-primary pull-right">Save Progress</button> 
    </fieldset> 

    <pre>form = {{models | json}}</pre> 
    <pre>master = {{master | json}}</pre> 
</form> 

表单字段的指令:使用

angular.module('formField.directives', []) 

.directive('formField', [ '$http', '$compile', function($http, $compile) { 

    var getTemplateUrl = function(field) { 

     var type = field.field_type; 
     var templateUrl = ''; 

     switch(type) { 
      case 'textfield': 
       templateUrl = 'components/form-field/fields/textfield.html'; 
       break; 
      case 'email': 
       templateUrl = 'components/form-field/fields/email.html'; 
       break; 
      case 'currency': 
       templateUrl = 'components/form-field/fields/currency.html'; 
       break; 
      case 'date': 
       templateUrl = 'components/form-field/fields/date.html'; 
       break; 
      case 'dropdown': 
       templateUrl = 'components/form-field/fields/dropdown.html'; 
       break; 
      case 'textarea': 
       templateUrl = 'components/form-field/fields/textarea.html'; 
       break; 
      case 'hidden': 
       templateUrl = 'components/form-field/fields/hidden.html'; 
       break; 
      case 'password': 
       templateUrl = 'components/form-field/fields/password.html'; 
       break; 
      case 'checkbox': 
       templateUrl = 'components/form-field/fields/checkbox.html'; 
       break; 
      case 'radio': 
       templateUrl = 'components/form-field/fields/radio.html'; 
       break; 
     } 

     return templateUrl; 
    } 

    var linker = function(scope, element) { 

     var templateUrl = getTemplateUrl(scope.field); 
     $http.get(templateUrl).success(function(data) { 
      element.html(data); 
      $compile(element.contents())(scope); 
     }); 
    } 

    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      field: '=' 
     }, 
     link: linker 
    } 
}]); 

表单字段模板:

<fieldset class="form-group"> 

    <label for="{{field.field_name}}">{{field.field_label}}</label> 
    <input type="text" 
      class="form-control" 
      id="{{field.field_id}}" 
      name="{{field.field_name}}" 
      value="{{field.field_value}}" 
      placeholder="{{field.field_prompt}}" 
      ng-required="field.field_required" 
      ng-disabled="field.field_disabled" 
      ng-model="models[field.field_name]"> // model.test also doesn't work, and need to be able to reference the model dynamically 

</fieldset> 

控制器从实施例中使用在AngularJS文档:

.controller('FormController', ['$scope', function($scope) { 

    $scope.master = {}; 
    $scope.models = {}; 

    $scope.update = function(models) { 
     console.info('Update'); 
     $scope.master = angular.copy(models); 
    }; 

    $scope.submit = function() { 
     console.info('Form Submitted'); 
    }; 

    $scope.cancel = function() { 
     console.info('Form Cancelled'); 
    }; 

    $scope.clear = function() { 
     console.info('Form Clear'); 
     $scope.models = {};    
    } 

    $scope.reset = function() { 
     console.info('Form Reset'); 
     $scope.models = angular.copy($scope.master); 
    }; 

    $scope.reset(); 

}]); 
+0

你可以准备演示吗?你的指令如何看起来像 – PSL 2014-09-03 01:10:16

+0

你可以添加“表单字段”指令的声明吗? – Josep 2014-09-03 01:12:21

+3

您正在使用独立作用域,它不知道上下文之外的“模型”是什么。现在看它http://plnkr.co/edit/HOxGGw?p=preview – PSL 2014-09-03 01:21:01

回答

3

您的指令适用于隔离范围(.$new(true)),这意味着您在指令中所做的更改不会直接在外部范围中提供(除非您使用双向绑定等)。所以ng-model="models[field.field_name]"models里面你的指令不是models对象在你的作用域上的父控制器中。所以你可以通过使用双向绑定来传递模型来修复它。

虽然耗时: -

<form-field field="field" model="models[field.field_name]"></form-field> 

在你的指令模板: -

<input type="text" 
     class="form-control" 
     id="{{field.field_id}}" 
     name="{{field.field_name}}" 
     value="{{field.field_value}}" 
     placeholder="{{field.field_prompt}}" 
     ng-required="field.field_required" 
     ng-disabled="field.field_disabled" 
     ng-model="model"> <!-- Here just set the model on the scope 2-way B --> 

,并在你的指令隔离声明范围做: -

scope:{field:'=', model:'='}, 
    //or set a reference to the object on scope holding models in the field property itself. 

Plnkr

请注意,在指定模板中,当您指定value="{{field.field_value}}"ng-model时,它根本不会设置默认值。你需要在ngModel中默认它。

+3

很好的答案! @mtpultz你可能想看看这个:https://docs.angularjs.org/guide/scope。此外,您用于'fieldset'标签的语义有点不协调。 'fieldset'标签应该用于分组字段,所以不要为每个字段创建'fieldset'标签,也许你应该使用它来保存它们。 – Josep 2014-09-03 03:28:10

+0

@Josep这是一个很好的观点。我没有注意到模板中有一个fieldset .. :) – PSL 2014-09-03 03:30:40

+0

感谢@PSL,这是一个很好的解释,同时也感谢您指出了有关默认值的问题。干杯:) – mtpultz 2014-09-03 06:11:48