20

i'm using AjgularJS on my page and want to add a field to use autocomplete from jqueryui and the autocomplete does not fires the ajax call.

i've tested the script on a page without angular (ng-app and ng-controller) and it works well, but when i put the script on a page with angularjs it stops working.

any idea?

jquery script:

$(function () {

    $('#txtProduct').autocomplete({
        source: function (request, response) {

            alert(request.term);

        },
        minLength: 3,
        select: function (event, ui) {

        }
    });

});
  • interesting note: when i call the script on Chrome inspector the autocomplete starts working!!!
  • Versions: AngularJS: 1.0.2 - JqueryUI: 1.9.0

CONCLUSION: The autocomplete widget from jQueryUI must be initializes from inside a custom directive of AngularJS as the example:

Markup

<div ng-app="TestApp">
    <h2>index</h2>
    <div ng-controller="TestCtrl">

        <input type="text" auto-complete>ddd</input>

    </div>
</div>

Angular script

<script type="text/javascript">

    var app = angular.module('TestApp', []);

    function TestCtrl($scope) { }

    app.directive('autoComplete', function () {
        return function postLink(scope, iElement, iAttrs) {

            $(function () {
                $(iElement).autocomplete({
                    source: function (req, resp) {
                        alert(req.term);
                    }
                });
            });

        }
    });

</script>
4
  • You should try loading them in $(document).ready(); Also check for errors in firebug console. Commented Oct 18, 2012 at 17:56
  • Agreed - you will need to check for conflicts between AngularJS and JQuery. There don't appear to be any in a simple test: jsfiddle.net/mccannf/w69Wt Commented Oct 18, 2012 at 23:18
  • 1
    It may not be relevant from the problem you are seeing, but I think you should be use jquery inside the custom directive (link function). Commented Oct 19, 2012 at 1:04
  • Thanks guys, the solution that work for me is the suggested by tosh, creating a custom directive for that!!! Commented Oct 19, 2012 at 10:38

3 Answers 3

38

Perhaps you just need to do it in an "angular way"... that is, to use a directive to set up your DOM elements and do event bindings, use a service to get your data, and use a controller to do your business logic... all while leveraging the dependency injection goodness that is Angular...

A service to get your autocomplete data...

app.factory('autoCompleteDataService', [function() {
    return {
        getSource: function() {
            //this is where you'd set up your source... could be an external source, I suppose. 'something.php'
            return ['apples', 'oranges', 'bananas'];
        }
    }
}]);

a directive to do the work of setting up the autocomplete plugin.

app.directive('autoComplete', function(autoCompleteDataService) {
    return {
        restrict: 'A',
        link: function(scope, elem, attr, ctrl) {
                    // elem is a jquery lite object if jquery is not present,
                    // but with jquery and jquery ui, it will be a full jquery object.
            elem.autocomplete({
                source: autoCompleteDataService.getSource(), //from your service
                minLength: 2
            });
        }
    };
});

And using it in your markup... notice the ng-model to set a value on the $scope with what you select.

<div ng-controller="Ctrl1">
    <input type="text" ng-model="foo" auto-complete/>
    Foo = {{foo}}
</div>

That's just the basics, but hopefully that helps.

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

6 Comments

The elem.autocomplete needs to be $(elem).autocomplete
@AshMcConnell: if jQuery is registered on the page before Angular, the elem argument to the link function is a jQuery object already. So no $() required. ;) Angular is slick like that.
thanks! I didn't know that, I'll check the import order when I get back to work tomorrow! (It's just the order of imports you mean?)
Correct, as long as your <script src="jquery.js"></script> is before your <script src="angular.js"></script>, it should use jQuery objects rather than jqLite objects for Elements within Angular.
How to put <input type="text" ng-model="foo" auto-complete/> in Jade Template? It sets auto-complete="auto-complete"
|
14

I had to do a bit more work to get this working using an $http service.

The service:

app.factory("AutoCompleteService", ["$http", function ($http) {
    return {
        search: function (term) {
            return $http.get("http://YourServiceUrl.com/" + term).then(function (response) {
                return response.data;
            });
        }
    };
}]);

The directive:

app.directive("autocomplete", ["AutoCompleteService", function (AutoCompleteService) {
    return {
        restrict: "A",
        link: function (scope, elem, attr, ctrl) {
            elem.autocomplete({
                source: function (searchTerm, response) {
                    AutoCompleteService.search(searchTerm.term).then(function (autocompleteResults) {
                        response($.map(autocompleteResults, function (autocompleteResult) {
                            return {
                                label: autocompleteResult.YourDisplayProperty,
                                value: autocompleteResult 
                            }
                        }))
                    });
                },
                minLength: 3,
                select: function (event, selectedItem) {
                    // Do something with the selected item, e.g. 
                    scope.yourObject= selectedItem.item.value;
                    scope.$apply();
                    event.preventDefault();
                }
            });
        }
    };
}]);

The html:

<input ng-model="YourObject" autocomplete />

6 Comments

I am getting following error 'Error: autocompleteResult is not defined'
Is your service returning any information? For example, in my service I'm returning response.data. If you are also returning that, make sure your service call is also returning data.
@Jason: can u please show me the format for json return data from get method.
@Siddesh Bhalke: Any arbitrary json can be returned by your service. In this example, autocompleteResults is an array of objects each of which has a property named 'YourDisplayProperty'.
I had a problem that the list was disappearing before anyone could click anything. I fixed that with the solution by corolla from this question: stackoverflow.com/questions/6043506/…
|
0

HTML

 <input type="text" class="form-control ml-2" employeesearchautocomplete ng-model="employeeName" name="employeeName">

JS

 var myApp = angular.module("employeeSearchModule",[]);

        myApp.controller("employeeSearchController",function($scope,$http){

            $scope.message= "Welcome to angular js..."

        });

        myApp.directive('employeesearchautocomplete', function() {
            return {
                restrict: 'A',
                require : 'ngModel',
                link : function (scope, element, attrs, ngModelCtrl) {
                      element.autocomplete({
                          source : function(request, response) {
                            $.ajax({
                                type : "POST",
                                url : "searchEmployee.html",
                                data : request,
                                success : response,
                                dataType : 'json'
                            });
                        },
                        select : function(event, ui) {
                            event.preventDefault();
                            if (ui.item.value == '-1') {
                                scope.employeeName ='';
                                scope.$apply();
                            } else {
                                scope.employeeName = ui.item.label;
                                scope.$apply();

                            }
                        },
                        focus : function(event, ui) {
                            event.preventDefault();
                            scope.employeeName = ui.item.label;
                            scope.$apply();
                        },
                        change : function(event, ui) {
                            if (!ui.item) {
                                scope.employeeName ='';
                                scope.$apply();

                            }
                        }
                      },{
                            minLength : 2
                      });


                }
            }
        });

Order of script files import

  • All your jquery
  • AngularJs library
  • your angular script for autocomplete

I hope this will help someone.

Comments

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.