我有这个指令,它基本上是 bootstrap 中 typeahead 插件的包装器。一切都像魅力一样运作。但现在我必须在 typeahead 的输入字段中设置初始值。该值在 attrs.init 中作为字符串传递。但我不知道如何将其插入文本字段。
angular.module('rcApp')
.directive('rcAutocomplete', ['$injector', function ($injector) {
return {
scope: {
model: '@',
search: '@',
key: '@',
show: '@',
init: '@',
ngModel: '='
},
template: '<input type="text">',
replace: true,
restrict: 'E',
require: 'ngModel',
link: function (scope, element, attrs) {
// inject model service
var service = $injector.get(attrs.model);
// define search function
var searchFunction = attrs.search;
// holds picked object id
scope.id = 0;
// holds objects that matched query, mapped by "show" value
scope.map = {};
element.on('focusout ac.itempicked', function () {
scope.$apply(function () {
scope.ngModel = scope.id;
});
});
// launch typehead plugin
element.typeahead(
{
source: function (query, process) {
// clear cache
scope.id = 0;
scope.map = {};
service[searchFunction](query).then(function (result) {
var dataValues = [];
var fieldsToShow = scope.show.split('|');
$.each(result.data, function (index, dataItem) {
// generate key-show string
var valueHash = '';
for (var i = 0; i < fieldsToShow.length; i++) {
valueHash += dataItem[fieldsToShow[i]] + ' ';
}
valueHash = $.trim(valueHash);
// map results
scope.map[valueHash] = dataItem;
// prepare return strings
dataValues.push(valueHash);
});
// return content
process(dataValues);
});
},
updater: function (item) {
if (typeof scope.key === 'undefined') {
scope.id = scope.map[item];
}
else {
scope.id = scope.map[item][scope.key];
}
element.trigger('ac.itempicked');
return item;
}
}
);
}
};
}]);
** 更新 **
对我有用的解决方案是将这样的代码添加到链接功能:
// init value
if (typeof attrs.init !== 'undefined') {
window.setTimeout(function () {
element.val(attrs.init);
scope.$apply();
}, 10);
}
但我仍然不太明白为什么“element.val(attrs.init);” 不要更新视图,调用 scope.$apply() 会,但会抛出“$digest already in progress”错误。将它包装在 window.setTimeout 中会有所帮助,但这对我来说也是一个技巧......
它必须是一种让它更清洁/更简单的方法......