如何创建AngularJS jQueryUI自动完成指令
我正在尝试创建一个使用jQueryUI的autocomplete小部件的自定义指令。我希望这是尽可能声明性的。这是所需的标记:如何创建AngularJS jQueryUI自动完成指令,angularjs,jquery-ui,autocomplete,Angularjs,Jquery Ui,Autocomplete,我正在尝试创建一个使用jQueryUI的autocomplete小部件的自定义指令。我希望这是尽可能声明性的。这是所需的标记: <div> <autocomplete ng-model="employeeId" url="/api/EmployeeFinder" label="{{firstName}} {{surname}}" value="id" /> </div> 因此,在上面的示例中,我希望指令对指定的url进行AJAX调用,当返回数据时
<div>
<autocomplete ng-model="employeeId" url="/api/EmployeeFinder" label="{{firstName}} {{surname}}" value="id" />
</div>
因此,在上面的示例中,我希望指令对指定的url进行AJAX调用,当返回数据时,在文本框中显示根据结果的表达式计算的值,并将id属性设置为employeeId。这是我对指令的尝试
app.directive('autocomplete', function ($http) {
return {
restrict: 'E',
replace: true,
template: '<input type="text" />',
require: 'ngModel',
link: function (scope, elem, attrs, ctrl) {
elem.autocomplete({
source: function (request, response) {
$http({
url: attrs.url,
method: 'GET',
params: { term: request.term }
})
.then(function (data) {
response($.map(data, function (item) {
var result = {};
result.label = item[attrs.label];
result.value = item[attrs.value];
return result;
}))
});
},
select: function (event, ui) {
ctrl.$setViewValue(elem.val(ui.item.label));
return false;
}
});
}
}
});
app.directive('autocomplete',函数($http){
返回{
限制:'E',
替换:正确,
模板:“”,
要求:'ngModel',
链接:函数(范围、元素、属性、ctrl){
自动完成元素({
来源:功能(请求、响应){
$http({
url:attrs.url,
方法:“GET”,
参数:{term:request.term}
})
.then(功能(数据){
响应($.map)(数据、功能(项){
var result={};
result.label=项目[attrs.label];
result.value=项目[attrs.value];
返回结果;
}))
});
},
选择:函数(事件,ui){
ctrl.$setViewValue(元素值(ui.item.label));
返回false;
}
});
}
}
});
因此,我有两个问题-如何计算label属性中的表达式,以及如何将value属性的属性设置为我作用域上的ngModel
(function () {
'use strict';
angular
.module('app')
.directive('myAutocomplete', myAutocomplete);
myAutocomplete.$inject = ['$http', '$interpolate', '$parse'];
function myAutocomplete($http, $interpolate, $parse) {
// Usage:
// For a simple array of items
// <input type="text" class="form-control" my-autocomplete url="/some/url" ng-model="criteria.employeeNumber" />
// For a simple array of items, with option to allow custom entries
// <input type="text" class="form-control" my-autocomplete url="/some/url" allow-custom-entry="true" ng-model="criteria.employeeNumber" />
// For an array of objects, the label attribute accepts an expression. NgModel is set to the selected object.
// <input type="text" class="form-control" my-autocomplete url="/some/url" label="{{lastName}}, {{firstName}} ({{username}})" ng-model="criteria.employeeNumber" />
// Setting the value attribute will set the value of NgModel to be the property of the selected object.
// <input type="text" class="form-control" my-autocomplete url="/some/url" label="{{lastName}}, {{firstName}} ({{username}})" value="id" ng-model="criteria.employeeNumber" />
var directive = {
restrict: 'A',
require: 'ngModel',
compile: compile
};
return directive;
function compile(elem, attrs) {
var modelAccessor = $parse(attrs.ngModel),
labelExpression = attrs.label;
return function (scope, element, attrs) {
var
mappedItems = null,
allowCustomEntry = attrs.allowCustomEntry || false;
element.autocomplete({
source: function (request, response) {
$http({
url: attrs.url,
method: 'GET',
params: { term: request.term }
})
.success(function (data) {
mappedItems = $.map(data, function (item) {
var result = {};
if (typeof item === 'string') {
result.label = item;
result.value = item;
return result;
}
result.label = $interpolate(labelExpression)(item);
if (attrs.value) {
result.value = item[attrs.value];
}
else {
result.value = item;
}
return result;
});
return response(mappedItems);
});
},
select: function (event, ui) {
scope.$apply(function (scope) {
modelAccessor.assign(scope, ui.item.value);
});
if (attrs.onSelect) {
scope.$apply(attrs.onSelect);
}
element.val(ui.item.label);
event.preventDefault();
},
change: function () {
var
currentValue = element.val(),
matchingItem = null;
if (allowCustomEntry) {
return;
}
if (mappedItems) {
for (var i = 0; i < mappedItems.length; i++) {
if (mappedItems[i].label === currentValue) {
matchingItem = mappedItems[i].label;
break;
}
}
}
if (!matchingItem) {
scope.$apply(function (scope) {
modelAccessor.assign(scope, null);
});
}
}
});
};
}
}
})();
(函数(){
"严格使用",;
有棱角的
.module('应用程序')
.指令(“myAutocomplete”,myAutocomplete);
myAutocomplete.$inject=['$http'、'$interpolate'、'$parse'];
函数myAutocomplete($http、$interpolate、$parse){
//用法:
//对于一个简单的项目数组
//
//对于简单的项数组,具有允许自定义项的选项
//
//对于对象数组,label属性接受表达式。NgModel设置为所选对象。
//
//设置值属性将NgModel的值设置为选定对象的属性。
//
var指令={
限制:“A”,
要求:'ngModel',
编译:编译
};
返回指令;
函数编译(元素、属性){
var modelacessor=$parse(attrs.ngModel),
labelExpression=attrs.label;
返回函数(范围、元素、属性){
变量
MappeItems=null,
allowCustomEntry=attrs.allowCustomEntry | | false;
元素自动完成({
来源:功能(请求、响应){
$http({
url:attrs.url,
方法:“GET”,
参数:{term:request.term}
})
.成功(功能(数据){
MappeItems=$.map(数据、函数(项){
var result={};
如果(项目类型=='string'){
result.label=项目;
结果值=项目;
返回结果;
}
result.label=$interpolate(labelExpression)(项目);
if(属性值){
result.value=项目[attrs.value];
}
否则{
结果值=项目;
}
返回结果;
});
返回响应(MappeItems);
});
},
选择:功能(事件、用户界面){
范围.$apply(功能(范围){
modelAccessor.assign(范围、ui.item.value);
});
如果(属性onSelect){
范围:$apply(属性选择);
}
element.val(ui.item.label);
event.preventDefault();
},
更改:函数(){
变量
currentValue=element.val(),
matchingItem=null;
如果(allowCustomEntry){
返回;
}
如果(映射项){
对于(变量i=0;i
很抱歉吵醒您。。。这是一个很好的解决方案,但它不支持ng repeat
我目前正在调试它,但我对Angular还没有足够的经验:)
编辑:
发现了问题。elem.autocomplete指向发送到编译函数的elem参数。它需要指向返回链接函数中的元素参数。这是由于ng repeat对元素进行了克隆。以下是更正后的代码:
app.directive('autocomplete', function ($http, $interpolate, $parse) {
return {
restrict: 'E',
replace: true,
template: '<input type="text" />',
require: 'ngModel',
compile: function (elem, attrs) {
var modelAccessor = $parse(attrs.ngModel),
labelExpression = attrs.label;
return function (scope, element, attrs, controller) {
var
mappedItems = null,
allowCustomEntry = attrs.allowCustomEntry || false;
element.autocomplete({
source: function (request, response) {
$http({
url: attrs.url,
method: 'GET',
params: { term: request.term }
})
.success(function (data) {
mappedItems = $.map(data, function (item) {
var result = {};
if (typeof item === "string") {
result.label = item;
result.value = item;
return result;
}
result.label = $interpolate(labelExpression)(item);
if (attrs.value) {
result.value = item[attrs.value];
}
else {
result.value = item;
}
return result;
});
return response(mappedItems);
});
},
select: function (event, ui) {
scope.$apply(function (scope) {
modelAccessor.assign(scope, ui.item.value);
});
elem.val(ui.item.label);
event.preventDefault();
},
change: function (event, ui) {
var
currentValue = elem.val(),
matchingItem = null;
if (allowCustomEntry) {
return;
}
for (var i = 0; i < mappedItems.length; i++) {
if (mappedItems[i].label === currentValue) {
matchingItem = mappedItems[i].label;
break;
}
}
if (!matchingItem) {
scope.$apply(function (scope) {
modelAccessor.assign(scope, null);
});
}
}
});
}
}
}
});
app.directive('autocomplete',函数($http,$interpolate,$parse){
返回{
限制:'E',
替换:正确,
模板:“”,
要求: