当前位置: 首页 > 面试题库 >

自定义ngTagsInput和autoComplete指令(AngularJS)

祁俊喆
2023-03-14
问题内容

我是AngularJS的新手,目前正在处理一个输入字段,该字段可以一次接受多个标签以及自动完成功能,该功能将可用标签显示为下拉选项。为此,我使用在ngTagsInputWeb上找到的指令(http://mbenford.github.io/ngTagsInput/),该指令为我提供了一个自定义HTML元素<tags- input>。这很漂亮:

index.html

<script>
var app = angular.module('plunker', ['ngTagsInput']);

app.controller('MainCtrl', function($scope, $http) {
  $scope.tags = [
    { text: 'Tag1' },
    { text: 'Tag2' },
    { text: 'Tag3' }
  ];

  $scope.loadTags = function(query) {
    return $http.get('tags.json');
  };
});
</script>
<div ng-app="plunker" ng-controller="MainCtrl">    
    <tags-input ng-model="tags" add-on-paste="true" display-property="text" placeholder="Add a Tag" add-from-autocomplete-only="true">
           <auto-complete max-results-to-show="4" min-length="2" source="loadTags($query)"></auto-complete>
    </tags-input>
</div>

tags.json

[
  { "text": "Tag1" },
  { "text": "Tag2" },
  { "text": "Tag3" },
  { "text": "Tag4" },
  { "text": "Tag5" },
  { "text": "Tag6" },
  { "text": "Tag7" },
  { "text": "Tag8" },
  { "text": "Tag9" },
  { "text": "Tag10" }
]

但是,我想使用标准HTML <input>元素而不是<tags-input>指令附带的自定义元素,因此,在很多帮助和使用下,<script src="https://code.jquery.com/jquery-3.1.0.js" integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" crossorigin="anonymous"></script>我可以在此处进行操作:

这是新的index.html

<script>
var app = angular.module('plunker', ['ngTagsInput']);

app.controller('MainCtrl', function($scope, $http) {
  $scope.tags = [
    { "id":1, "tagname": 'Tag1' },
    { "id":2, "tagname": 'Tag2' },
    { "id":3, "tagname": 'Tag3' },
    { "id":4, "tagname": 'Tag4' }
  ];

    $scope.loadTags = function(query) {
    return $http.get('tags.json');
  };

});

app.directive('tagsInputAttr', 
  function($compile){
    return {
      restrict: 'A',
      require: '?ngModel',
      scope:{
        ngModel: '='
      },
      link: function($scope, element, attrs, controller) {
        var attrsText = '';
        $.each($(element)[0].attributes, function(idx, attr) {
          if (attr.nodeName === "tags-input-attr" || attr.nodeName === "ng-model") 
            return;

          attrsText += " " + attr.nodeName + "='" + attr.nodeValue + "'";
        });

        var html ='<tags-input ng-model="ngModel" ' + attrsText + '></tags-input>';
        e =$compile(html)($scope);
        $(element).replaceWith(e);
      }
    };
  }
);
</script>
<div ng-app="plunker" ng-controller="MainCtrl">

    <input tags-input-attr ng-model="tags" add-on-paste="true" display-property="tagname" placeholder="Add tags here..." add-from-autocomplete-only="true">
      <auto-complete max-results-to-show="3" min-length="2" source="loadTags($query)"></auto-complete>
    </input>

  </div>

和新的tags.json

[
  { "id":1, "tagname": "Tag1" },
  { "id":2, "tagname": "Tag2" },
  { "id":3, "tagname": "Tag3" },
  { "id":4, "tagname": "Tag4" },
  { "id":5, "tagname": "Tag5" },
  { "id":6, "tagname": "Tag6" },
  { "id":7, "tagname": "Tag7" },
  { "id":8, "tagname": "Tag8" },
  { "id":9, "tagname": "Tag9" },
  { "id":10, "tagname": "Tag10" }
]

如您所见tagsInputAttr,包装了的new指令<tags- input>提供了相同的功能,并且可以在<input>标记中与其他属性(例如ng-modeldisplay- property等)一起用作属性使用,因此我不必<tags-input>直接使用该元素。该 问题 是,<auto- complete>放在里面<input>的标签不起作用。

为此,我需要考虑以下因素来更改我的指令:

注意: 我不想为此使用jquery

我的问题是如何包装<auto-complete>相同的<input tags-input-attr>元素:

  1. 作为同一<input tags-input-attr>元素内的一个属性

  2. 或作为包装在同一元素内的标准HTML元素(如<div>或)内的属性。<span>``<input tags-input-attr>

  3. 如果不是以上两个,则作为最后的选择,将<auto-complete>标签包裹在同一<input tags-input-attr>元素内

感谢所有帮助。提前致谢。


问题答案:

我对previus指令进行了一些更改,现在它接受从attributeelement指令的所有转换。

您仍然具有该elem-as-attr属性,但是现在您必须指定该属性,value它将被element替换。

例:

<div elem-as-attr="tags-input"></div>
var app = angular.module('plunker', ['ngTagsInput']);

app.controller('MainCtrl', function($scope, $http) {
  $scope.allTags = [
    { "id":1, "tagname": "Tag1" },
    { "id":2, "tagname": "Tag2" },
    { "id":3, "tagname": "Tag3" },
    { "id":4, "tagname": "Tag4" },
    { "id":5, "tagname": "Tag5" },
    { "id":6, "tagname": "Tag6" },
    { "id":7, "tagname": "Tag7" },
    { "id":8, "tagname": "Tag8" },
    { "id":9, "tagname": "Tag9" },
    { "id":10, "tagname": "Tag10" }
  ];

  $scope.myTags =[
    $scope.allTags[2],
    $scope.allTags[4],
    $scope.allTags[8]
  ];

  $scope.loadTags = function(query) {
    return $scope.allTags;
  };
});

指令代码:

app.directive('elemAsAttr', function($compile) {
  return {
    restrict: 'A',
    require: '?ngModel',
    replace: true,
    scope: true,
    compile: function(tElement, tAttrs) {
      return function($scope) {
        var attrs = tElement[0].attributes;

        var attrsText = '';
        for (var i=0; i < attrs.length; i++) {
          var attr = attrs.item(i);
          if (attr.nodeName === "elem-as-attr") {
            continue;
          }
          attrsText += " " + attr.nodeName + "='" + attr.nodeValue + "'";        
        }

        var hasModel = $(tElement)[0].hasAttribute("ng-model");
        var innerHtml = $(tElement)[0].innerHTML;
        var html = '<' + tAttrs.elemAsAttr  + attrsText + '>' + innerHtml + '</' + tAttrs.elemAsAttr + '>';

        var e = hasModel ? $compile(html)($scope) : html;
        $(tElement).replaceWith(e);
      };
    }
  }
});

HTML代码:

元素方式:

  <tags-input ng-model="myTags" add-on-paste="true" display-property="tagname" placeholder="Add a Tag" add-from-autocomplete-only="true">
    <auto-complete max-results-to-show="10" display-property="tagname" min-length="2" source="loadTags($query)"></auto-complete>
  </tags-input>

属性方式:

  <div elem-as-attr="tags-input" ng-model="myTags" add-on-paste="true" display-property="tagname" placeholder="Add tags here..." add-from-autocomplete-only="true">
    <div elem-as-attr="auto-complete" max-results-to-show="10" display-property="tagname" min-length="2" source="loadTags($query)"></div>
  </div>

柱塞:

https://plnkr.co/edit/9TqsXy

请注意,您不能将input元素用于,tagsInput 因为该input元素在HTML中没有结束标记。因此,您将无法将auto- complete元素放入其中。



 类似资料:
  • 创建自定义指令 第一步,创建一个自定义命令类文件,新建application/common/command/Hello.php <?php namespace app\common\command; use think\console\Command; use think\console\Input; use think\console\input\Argument; use think\con

  • 自定义指令可以使用 macro 指令来定义, 这是模板设计者所关心的内容。 Java程序员若不想在模板中实现定义指令,而是在Java语言中实现指令的定义, 这时可以使用 freemarker.template.TemplateDirectiveModel 类来扩展 (请参考 后续章节)。 基本内容 宏是有一个变量名的模板片段。可以在模板中使用宏作为自定义指令, 这样就能进行重复性的工作。例如,创建

  • 主要内容:实例,实例,钩子,实例,实例除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令。 下面我们注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点: 实例 <div id="app"> <p>页面载入时,input 元素自动获取焦点:</p> <input v-focus> </div> <script> // 注册一个全局自定义指令 v-focus Vue.d

  • 主要内容:实例,实例,钩子,实例,实例,实例除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令。 下面我们注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点: 实例 <div id="app"> <p>页面载入时,input 元素自动获取焦点:</p> <input v-focus> </div> <script> const app = Vue.createApp({}

  • 简介 除了默认设置的核心指令( v-model 和 v-show ),Vue 也允许注册自定义指令。注意,在 Vue2.0 里面,代码复用的主要形式和抽象是组件——然而,有的情况下,你仍然需要对纯 DOM 元素进行底层操作,这时候就会用到自定义指令。下面这个例子将聚焦一个 input 元素,像这样: Vue.directive('focus', { inserted: function (el)

  • 1. 前言 本小节我们介绍 Vue 中的自定义指令。包括全局指令的注册、局部指令的注册、指令钩子函数的使用以及动态指令传参。其中,指令钩子函数和动态指令参数是本节的难点。 同学们需要充分理解每个指令钩子函数执行的时机、对动态指令参数多加练习才能对指令的使用得心应手。 2. 慕课解释 Vue 除了提供了默认内置的指令外,还允许开发人员根据实际情况自定义指令,它的作用价值在于当开发人员在某些场景下需要