将自定义指令添加到已具有角度指令的现有输入[ng-model/ng-required]

Dav*_*wys 7 javascript angularjs angularjs-directive

我想用装饰有一个标准的输入控制ng-modelng-required,然后添加自己的自定义属性的指令,它提供uib-typeahead的功能来控制.

我用这个链接让我的指令部分工作.

在AngularJS中添加指令中的指令

PLUNKR - 指令的版本2无法与ng-model一起正常工作

我的指令确实添加了typeahead功能并且运行良好,但是在选择项目后它不会将模型绑定到控件上.

我有两个版本的指令.

版本1:是一个元素样式指令,我已经成功使用了一段时间,但是当我不想对输入元素进行更多控制时,它就失败了,特别是当我想使用ng-required ='时true'和其他ng-message指令.

版本2:是一个属性样式指令,我接受了这个,因为我觉得最好只添加我想要的任何标准HTML的typeahead功能ng-required='true',ng-model等等......

虽然这个指令大部分都在工作,但它没有正确地与之交互ng-model,我不知道如何让它工作

angular.module(APP)

.directive('wkLocationSuggest', ['$compile', function ($compile) {
  return {
    restrict: 'A',
    require: 'ngModel',
    replace: false,
    //terminal: true,
    //priority: 0,
    scope: {
      wkApiModel: '=' // Provide access to the internal data that is returned via the API lookup
    },
    controller: 'LocationSuggestController',
    link: function (scope, element, attrs, ngModelCtrl) {
      if (!ngModelCtrl) {
        return;
      }

      element.attr('typeahead', 'location as row.location for row in typeAhead($viewValue)');
      element.attr('typeahead-wait-ms', '750');
      element.attr('typeahead-on-select', 'onSelectInternal($item, $model, $label)');
      element.attr('typeahead-min-length', '2');
      element.attr('typeahead-focus-first', 'true');

      element.removeAttr("wk-location-suggest");        //remove the location-suggest to avoid indefinite loop
      element.removeAttr("data-wk-location-suggest");   //also remove the same attribute with data- prefix if it exists

      // None of this is working
      //// invoked when model changes from the outside
      //ngModelCtrl.$render = function () {
      //  //scope.innerModel = ngModelCtrl.$modelValue;
      //};

      ////// invoked when model changes from the inside
      //scope.onChange = function (value) {
      //  ngModelCtrl.$setViewValue(scope.innerModel);
      //};

      scope.onSelectInternal = function ($item, $model, $label) {

        // This fires, but it effects the ng-model on the first input, 
        // but not the input that this directive is attached too
        ngModelCtrl.$setViewValue($item.location);

      };

      $compile(element)(scope);

    }
  };
}]);
Run Code Online (Sandbox Code Playgroud)

这两个图像演示了部分问题,可能更好地使用上面的PLUNKR测试自己

该指令的第1版和第2版正在实施中

版本2无法正常工作

Ahm*_*eri 2

我最初尝试通过结合's方法在输入元素上实现来动态地将验证器添加到您的wk-location-suggest-new指令中;但不知道到底是什么阻止了事件的触发。blurngModel$setValidity

因此,我转向另一个指令wk-location-suggest-old并对其进行了一些调整以适应两种所需的行为。

在那里,我注意到您遗漏了几件事:

  • 首先,为了使表单元素与表单本身粘合wkProfileCompany(在您的情况下)并使用ng-model该元素(在指令模板中)需要一个名称
  • 其次,仅当ng-required( 或required) 作为属性添加到指令模板中的元素(而不是编译到包含该元素的模板的指令)时,它才适用于表单。

指令定义

您可能会注意到,我已将两个属性从外部作用域传递到指令的内部作用域,即:

  • name输入元素的,
  • 以及一个isRequired标志来指定是否需要输入

.directive('wkLocationSuggestOld', [function () {
  return {
    restrict: 'E',
    require: '?ngModel',
    scope: {
      name: '@',      // <==
      isRequired: '=' // <==
    },
    template: '<input name="{{name}}" type="text" class="{{innerClass}}" ng-model="innerModel"'
       + ' ng-change="onChange()" uib-typeahead="location as row.location for row in typeAhead($viewValue)" '
       + ' typeahead-wait-ms="750" typeahead-on-select="onSelectInternal($item, $model, $label)" '
       + ' typeahead-min-length="2" typeahead-focus-first="true" '
       + ' ng-required="isRequired">',  // <== added ng-required here
    controller: 'LocationSuggestController',
    link: function (scope, element, attrs, ngModel) {
      if (!ngModel) {
          return;
      }          
      ...
}])
Run Code Online (Sandbox Code Playgroud)

超文本标记语言

最后,您可以在 HTML 中使用调整后的指令,如下所示:

<wk-location-suggest-old class="form-control" type="text" name="location2" ng-model="location2" is-required="true"></wk-location-suggest-old>
Run Code Online (Sandbox Code Playgroud)

普朗克


更新

ng-model指令中未正确绑定wk-location-suggest-new到提供的值(location3)的可能原因之一是您将整个DOM元素替换为新的自定义DOM元素,该元素是使用指令本身的隔离进行编译的。 scope

由于该指令wk-location-suggest-new具有隔离范围,因此该范围完全不知道location3,因为location3以及所有其他位置值)是在指令本身的范围中定义的MainCtrl,而不是在指令本身的范围中;因此,您最终会将输入的值绑定到undefined属性。

link: function (scope, element, attrs, ngModelCtrl) {
   if (!ngModelCtrl) {
     return;
   }
 ...
$compile(element)(scope); // <== here
Run Code Online (Sandbox Code Playgroud)