Reputation: 1155
I have a helper function used to bind input with jQuery autocomplete with set of extra options like show bootstrap popover on hover, ability to use secondary label, etc... I'm facing a problem that my ngModel is not updating when item selected from autocomplete list. This autocomplete select will update text field (for displayed value) and hidden field (for the value). I want to change that to a directive and notify ngModel in text & value fields that item selected.
bindAutocomplete: function (textSelector, valSelector, serviceUrl,
secondaryLabel, minLength, selectCallback,
tooltipPlacement, showOnTopOfField) {
if (!tooltipPlacement) {
tooltipPlacement = "right";
}
var autoCOmpletePosition = { my: "left bottom", at: "left top", collision: "flip" };
if (!showOnTopOfField || showOnTopOfField == false) {
var autoCOmpletePosition = { my: "left top", at: "left bottom", collision: "none" };
}
if (!minLength)
minLength = 2;
var jTextSelector = $(textSelector),
jValSelector = $(valSelector),
jTextSelectorId = jTextSelector.attr("id");
jTextSelector.autocomplete({
source: serviceUrl,
minLength: minLength,
position: autoCOmpletePosition,
select: function (event, ui) {
jValSelector.val(ui.item.id);
if (selectCallback) {
selectCallback(event, ui);
}
},
response: function (event, ui) {
jQuery.data(jTextSelector[0], jTextSelectorId, ui.content); // Store Filtered result in jQuery data store
}
});
if (secondaryLabel) {
var uiAutoCompleteData = jTextSelector.data("ui-autocomplete");
if (uiAutoCompleteData) {
uiAutoCompleteData._renderItem = function (ul, item) {
return $("<li>")
.append("<a><b>" + item.label + "</b><br><span style='font-size:0.8em;'>" + item.desc + "</span></a>")
.appendTo(ul);
};
}
}
jTextSelector.hover(function () { // On Hover
bindPopOver(this);
jTextSelector.popover('show');
},
function () { // On Unhover
jTextSelector.popover('destroy');
});
function bindPopOver(element) {
if (!$(element).val()) {
jValSelector.val("");
jTextSelector.popover('destroy');
}
else {
var listContent = jQuery.data(jTextSelector[0], jTextSelectorId); // Get Filtered result from jQuery data store
var text = jTextSelector.val();
var item = _.find(listContent, function (itemInList) {
return itemInList.label.toLowerCase() == text.toLowerCase();
});
if (item) {
jValSelector.val(item.id);
jTextSelector.popover('destroy');
jTextSelector.popover({
title: text,
trigger: 'hover',
content: item.desc,
placement: tooltipPlacement
});
}
else if (!item && text == "") {
jValSelector.val("");
jTextSelector.popover('destroy');
}
}
};
},
Upvotes: 0
Views: 121
Reputation: 2163
You can use directive techniques to transmit data from/to DOM components and angularjs.
I create a simple code with will help us to make the bind.
the main rule is the "link" of directive, aided with "scope" definition to reflect external data:
scope: { ngMyModel: '=' }
link: function(scope, el, attrs) {
scope.$watch('ngMyModel', function (val) {
el.val(val);
});
el.on('change input', function() {
scope.$apply(function(scope) {
scope.ngMyModel = el.val();
});
});
}
Where at first part I reflect on input (or another component, like datepicker, etc) any changes on angularjs data.
At second part, I capture events from element and use "scope.$apply" technique to reflect on angularjs data.
Upvotes: 0