javascript - 具有模型拦截/过滤功能的 Angular Directive(指令)

标签 javascript angularjs angularjs-directive

我有一个包含 ngTagsInput 的自定义指令

在所有情况下,我的源数据结构都是相同的,但在一种特定情况下,我需要以动态方式更改保存回服务器的数据。

我的标签通常采用格式{id: '123', name: 'Some Text'},但对于我们数据库中的特定字段,我需要按以下格式映射数据{id: 'some-text', name: 'Some Text'}

目前我只是使用所选标​​签更新 ng-model

我正在考虑在更新 ng-model 之前拦截所选标签并将 id 从 '123' 更改为 'some-text' >

我创建了一个 Plunkr

示例

Example of expected data

我无法弄清楚如何在 Angular Directive(指令)中添加拦截器

Broken Code

页面 Controller

app.controller('MainCtrl', function($scope) {

  $scope.model = {
    skills: [],
    desired_skills: []
  };

  $scope.dashed = function(value)   {
    var result = _
      .words(value)
      .map(function(x) { return x.toLowerCase(); })
      .join('-');

    //console.log(result);
    return result;
  }

  $scope.intercept = function(item) {
    console.log('item: ' + JSON.stringify(item));

    return { id: $scope.dashed(item.name), name: item.name };
  }

})

指令 Controller

.controller('SkillTagInputController', ['$scope', '$filter', '$q', function($scope, $filter, $q) {


  $scope.loadTags = function (name) {
    return [
      {id: 5, name: "Some Text"},
      {id: 6, name: "More Text"},
      {id: 7, name: "Something Else"}
    ]
  };

}])

指令

.directive('wkSkillTagInput', [
  function() {
    return {
      restrict: 'E',
      require: '?ngModel',
      scope: {
        ngModel: '=',
        wkOnAddInterceptor: '&'
      },
      template: '<tags-input \
            ng-model="innerModel" \
            ng-change="onChange()" \
            add-on-paste="true" \
            display-property="name" \
            add-from-autocomplete-only="true" \
            replace-spaces-with-dashes="false"> \
                <auto-complete source="loadTags($query)" min-length="2"></auto-complete> \
            </tags-input>',

      controller: 'SkillTagInputController',
      link: function(scope, element, attrs, ngModel) {
        if (!ngModel) {
          return;
        }

        // invoked when model changes from the outside
        ngModel.$render = function() {
          scope.innerModel = ngModel.$modelValue;
        };

        // invoked when model changes from the inside
        scope.onChange = function() {
          if (scope.wkOnAddInterceptor) {
            // This is the area I need to get working
            // The intercepter should get called and change the nagure of the selected item
            //ngModel.$setViewValue(scope.$eval(scope.wkOnAddInterceptor));
            ngModel.$setViewValue(scope.innerModel);
          } else {
            ngModel.$setViewValue(scope.innerModel);
          }
        };
      }
    };
  }
])

最佳答案

首先主要问题是ng-tags-input中不存在onChange方法,您可以查看文档以获取更多信息http://mbenford.github.io/ngTagsInput/documentation/api

在此plunker ,我用onTagAdding代替了onChange,另一个变化是拦截器的调用方式。当您将函数传递给跨作用域的指令时,该函数始终会被定义,然后如果您检查 if (scope.wkOnAddInterceptor) 则始终返回 true。这是代码的一部分:

    scope.onTagAdding = function($tag) {
      var tag = scope.wkOnAddInterceptor({item: $tag})
      $tag.id = tag ? tag.id : $tag.id;
      return true;
    }

另一个错误(主要问题的外部)是在 ngModel.$render 中,您正在分配模型的引用,在这种情况下有效,因为您正在使用空数组初始化模型:

 $scope.model = {
    skills: [],
    desired_skills: []
  };

我建议您检查模型,制作一个干净的副本,并使用 ngModelCtrl 的内部方法。这篇文章很好地解释了ngModelCtrl流程http://www.chroder.com/2014/02/01/using-ngmodelcontroller-with-custom-directives/

关于javascript - 具有模型拦截/过滤功能的 Angular Directive(指令),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32599998/

相关文章:

javascript - FireFox 中的 For 循环问题

javascript - 如何在html中设置$compile代码

javascript - 在 angularjs 中有不同的页眉和页脚的最佳方法是什么?

angularjs - 用标准 Web 技术取代 Angular

angularjs - ng-click执行属于不同 Controller 的2个方法

javascript - HTML5 Web Audio API 在使用 AudioBuffer 播放 PCM 数据时出现奇怪的噪音

javascript - 使用 REST API 的可编辑 jQuery 网格推荐

javascript - Bootstrap 4 - 避免屏幕点击模式关闭

javascript - 如何使用 angularjs 指令动态添加表单验证属性?

css - 在没有 "snapping"的情况下,如何淡出一个元素并淡入另一个元素?