自定义 ngTagsInput &自动完成指令 (AngularJS) [英] Customizing ngTagsInput & autoComplete directives (AngularJS)
问题描述
我是 AngularJS 的新手,目前正在研究一个输入字段,该字段可以一次接受多个标签以及自动完成功能,该功能将可用标签显示为下拉选项.为此,我使用了我在网上找到的 ngTagsInput
指令(http://mbenford.github.io/ngTagsInput/),它给了我一个自定义的 HTML 元素
.这很好用:
index.html
:
<div ng-app="plunker" ng-controller="MainCtrl"><tags-input ng-model="tags" add-on-paste="true" display-property="text" placeholder="添加标签" add-from-autocomplete-only="true"><auto-complete max-results-to-show="4" min-length="2" source="loadTags($query)"></auto-complete></tags-input>
tags.json
:
但是我想使用标准的 HTML <input>
元素而不是自定义的 <tags-input>
元素随指令一起出现,所以很多帮助和使用 <script src="https://code.jquery.com/jquery-3.1.0.js"integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="crossorigin="anonymous"></script>
我可以在这里做到:
这是新的index.html
:
<div ng-app="plunker" ng-controller="MainCtrl"><input tags-input-attr ng-model="tags" add-on-paste="true" display-property="tagname" placeholder="在此处添加标签..." add-from-autocomplete-only="真实"><auto-complete max-results-to-show="3" min-length="2" source="loadTags($query)"></auto-complete></input>
还有新的tags.json
:
如您所见,包装了
的新指令 tagsInputAttr
提供了相同的功能,可以在 中使用.input>
标记作为一个属性以及其他属性,例如 ng-model
、display-property
等.所以我不必使用
元素直接.问题是
放在 标签内不起作用.
为此,我需要更改我的指令,考虑以下几点:
注意:我不想为此使用jquery
我的问题是如何将
包裹在同一个 元素中:
作为同一
元素内的属性
或作为标准 HTML 元素(如
或)内的属性,包裹在相同的
元素.
如果不是以上两个,那么作为最后的手段,将
标签包裹在同一个元素
感谢所有帮助.提前致谢.
解决方案我对 previus 指令进行了一些更改,现在它接受从
attribute
到element
指令.您仍然拥有
elem-as-attr
属性,但现在您必须指定它的value
,它将成为element
代码>将替换.示例:
您的应用程序 JavaScript:
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 = 函数(查询){返回 $scope.allTags;};});
指令代码:
app.directive('elemAsAttr', function($compile) {返回 {限制:'A',要求:'?ngModel',替换:真的,范围:真实,编译:函数(tElement,tAttrs){返回函数($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") {继续;}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-from-autocomplete-only="真实"><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-from-autocomplete-only="true"><div elem-as-attr="auto-complete" max-results-to-show="10" display-property="tagname" min-length="2" source="loadTags($query)">
Plunker:
<块引用>请注意,您不能将 input
元素用于 tagsInput
因为 input
元素在 HTML 中没有结束标记.所以您将无法将 auto-complete
元素放入其中.
I am new to AngularJS and am currently working on an input field, which can accept multiple tags at a time along with the auto-complete feature, which display the available tags as dropdown options. For this I am using the ngTagsInput
directive I found on the web(http://mbenford.github.io/ngTagsInput/), which gives me a custom HTML element <tags-input>
. This works beautifully:
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" }
]
However I wanted to use the standard HTML <input>
element instead of the custom <tags-input>
element which comes along with the directive, so with a lot of help and using <script src="https://code.jquery.com/jquery-3.1.0.js" integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" crossorigin="anonymous"></script>
I was able to do it here:
Here is the new 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>
And the new 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" }
]
As you can notice,the new directive tagsInputAttr
, which wraps the <tags-input>
provides the same functionality and can be used inside <input>
tag as an attribute along with the rest of attributes such as ng-model
, display-property
etc. So I don't have to use the <tags-input>
element directly. The problem is that the <auto-complete>
placed inside the <input>
tag doesn't work.
For this I need to alter my directive, considering the following:
Note: I do not want to use jquery for this
My question is how do I wrap the <auto-complete>
inside the same <input tags-input-attr>
element:
Either as an attribute inside the same
<input tags-input-attr>
elementor as an attribute inside a standard HTML element like
<div>
or<span>
, wrapped inside the same<input tags-input-attr>
element.If not the above two, then as last resort, as the
<auto-complete>
tag wrapped inside the same<input tags-input-attr>
element
All help is appreciated. Thanks in advance.
I made some changes on the previus directive and now it accepts all kind of transformation from attribute
to element
directive.
You still have the elem-as-attr
attribute, but now you have to specify the value
of it, that it will be the element
that will replace.
Example:
<div elem-as-attr="tags-input"></div>
Your application JavaScript:
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;
};
});
The directive code:
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 code:
Element way:
<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>
Attribute way:
<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>
Plunker:
Note that you cannot use the
input
element for thetagsInput
because theinput
element does not have the closing tag in HTML. So you will not be able to put theauto-complete
element inside it.
这篇关于自定义 ngTagsInput &自动完成指令 (AngularJS)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!