Angular - 需要 ngModel 并在自定义指令的控制器中使用它,而不是链接函数

tec*_*her 5 javascript angularjs angularjs-directive angular-ngmodel angularjs-validation

谁能告诉我是否可以在自定义 Angular 指令的控制器中要求和使用 ngModel 。我试图远离链接功能。我看到大多数示例都使用链接函数,但我认为必须有某种方法可以在指令控制器内使用它?或者只能在链接函数中访问?我见过的一种方法(如下所示)给了我未定义的信息。不知道还有没有其他方法??我正在尝试验证组件并在错误对象上设置无效的类。

//directive
angular.module('myApp', [])
  .directive('validator', function (){
    return {
      restrict: 'E',
      require: {
           ngModelCtrl: 'ngModel',
           formCtrl: '?^form'
      },
      replace: true,
      templateUrl: 'view.html',
      scope: {},
      controllerAs: 'ctrl',
      bindToController: {
         rows: '=',
         onSelected: '&?' //passsed selected row outside component
         typedText: '&?' //text typed into input passed outside so developer can create a custom filter, overriding the auto
         textFiltered: '@?' //text return from the custom filter
         ngRequired: "=?" //default false, when set to true the component needs to validate that something was selected on blur. The selection is not put into the input element all the time so it can't validate based on whether or not something is in the input element itself. I need to validate inside the controller where I can see if 'this.ngModel' (selectedRow - not passed through scope) is undefined or not.
      },
      controller: ["$scope", "$element", function ($scope, $element){
         var ctrl = this;
         ctrl.rowWasSelected;

         //called when a user clicks the dropdown to select an item
          ctrl.rowSelected = function (row){
               ctrl.rowWasSelected = true;
               ctrl.searchText = row.name; //place the name property of the dropdown data into ng-model in the input element
          }

         ctrl.$onInit = $onInit;
         function $onInit (){
             ctrl.ngModelCtrl.$validators.invalidInput = validate;            
          }

        function validate (modelValue, viewValue) {
             var inputField = ctrl.formCtrl.name;
             var ddField = ctrl.formCtrl.listData;

             inputField.$setValidity('invalidInput', ddField.$touched && ctrl.rowWasSelected);

            return true;
          }          
       }];
   }
});

//template
<form name="validatorForm" novalidate>
  <div class="form-group" ng-class="{ng-invalid:validatorForm.name.$error.invalid}">
     <label for="name">Names</label>
     <input type="name" class="form-control" name="name" placeholder="Your name" ng-change="typedText(text)" ng-model="ctrl.textFiltered" ng-blur="ctrl.validate()" ng-required="ctrl.ngRequired">
  </div>
  <ul ng-show="show list as toggled on and off" name="listData" required>
    <li ng-repeat="row in ctrl.rows" ng-click="ctrl.rowSelected({selected: row}) filterBy:'ctrl.textFiltered' ng-class="{'active':row === ctrl.ngModel}">{{row}}<li>
  </ul>
</form>

//html
<validator
   rows="[{name:'tim', city:'town', state:'state', zip: 34343}]"
   on-selected="ctrl.doSomethingWithSelectedRow(selected)"
   typed-text="ctrl.manualFilter(text)"
   text-filtered="ctrl.textReturnedFromManualFilter"
   ng-required="true">
</validator>
Run Code Online (Sandbox Code Playgroud)

小智 0

访问自定义指令中 ngModel 提供的信息的最简单方法是将范围设置为 false。默认情况下应该会发生这种情况,但如果您正在使用多个指令,则明确设置它会很有帮助。这样,该指令将继承控制器和控制器别名,就好像它完全是视图其余部分的本机一样。

该指令:

.directive('myValidator', function (){
return {
  restrict: 'E',
  replace: true,
  templateUrl: 'view.html',
  scope: false
  };
}
Run Code Online (Sandbox Code Playgroud)

您不必对模板进行太多更改。只需确保 ng-model="ctrl.name" 绑定到主控制器上的某些内容,或者您​​用于视图其余部分的任何控制器。您也可以将验证功能移至主控制器。或者,到服务并注入控制器等。

在自定义指令中使用编译或链接可以使其更加通用。但您基本上是在传递指令、属性或 html 标记的值。ngModel 可用,但您可能不会在每次使用自定义指令时都使用 ctrl.user。通过编译或链接,您可以在每次使用指令时设置 ngModel 的值。