0

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');
            }
        }
    };
},

1 Answer 1

0

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.

plunker

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Yes Exactly, I can now pass any extra param like what you did in ng-my-model .... Thank you for the answer.
You're welcome! And also, you can use "ngAnotherAttribute": "@" to represent a String non-variable parameter, like a mask or a title.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.