jQuery自动完成 + AngularJS存在的问题

20
我在我的页面上使用AngularJS,并想添加一个字段以使用来自jqueryui的自动完成功能,但自动完成不会触发ajax调用。
我在没有AngularJS(ng-app和ng-controller)的页面上测试了该脚本,它可以正常工作,但是当我将脚本放在带有AngularJS的页面上时,它就停止工作了。
有什么想法吗?
jquery脚本:
$(function () {

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

            alert(request.term);

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

        }
    });

});
  • 有趣的一点是:当我在Chrome检查器中调用脚本时,自动完成开始工作!
  • 版本:AngularJS:1.0.2 - JqueryUI:1.9.0

结论: 来自jQueryUI的自动完成小部件必须从AngularJS的自定义指令内初始化,例如:

标记

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

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

    </div>
</div>

Angular脚本

<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>

你应该尝试在$(document).ready()中加载它们;还要检查firebug控制台中的错误。 - Sachin Prasad
同意 - 您需要检查AngularJS和JQuery之间的冲突。在简单的测试中似乎没有任何问题:http://jsfiddle.net/mccannf/w69Wt/ - mccannf
1
可能与您遇到的问题无关,但我认为您应该在自定义指令(链接函数)中使用jQuery。 - Tosh
谢谢大家,对我有用的解决方案是由Tosh建议的,为此创建一个自定义指令!!! - Flavio CF Oliveira
3个回答

38

也许你只需要按照"Angular方式"去处理...也就是使用指令来设置DOM元素和事件绑定,使用服务来获取数据,并使用控制器来处理业务逻辑...同时利用Angular提供的依赖注入机制。

一个服务可以获取自动完成数据...

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

一个指令来做设置自动完成插件的工作。

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

将它用在您的标记中...注意使用ng-model将所选内容设置为$scope上的值。

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

这只是基础知识,但希望能有所帮助。


elem.autocomplete 需要被改为 $(elem).autocomplete。 - Ash McConnell
3
如果在Angular之前在页面上注册了jQuery,那么传递给link函数的elem参数已经是一个jQuery对象,因此不需要使用$()。 Angular做得很好。 - Ben Lesh
谢谢!我不知道这个,明天回到工作时我会检查导入顺序的!(你是指导入的顺序吗?) - Ash McConnell
只要你的<script src="jquery.js"></script><script src="angular.js"></script>之前,Angular中的元素应该使用jQuery对象而不是jqLite对象。 - Ben Lesh
如何在Jade模板中放置<input type="text" ng-model="foo" auto-complete/>?它设置了auto-complete="auto-complete" - Zeeshan
我发现需要在“select”事件上更新ngModel。 - Joseph Nields

14

我需要进行更多的工作才能使用 $http 服务使其正常工作。

该服务:

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

指令:

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();
                }
            });
        }
    };
}]);

HTML:

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

我遇到了以下错误'错误:autocompleteResult未定义'。 - sar
你的服务是否返回任何信息?例如,在我的服务中,我正在返回response.data。如果你也在返回它,请确保你的服务调用也返回数据。 - Jason
@Jason:你能否给我展示一下get方法返回json数据的格式? - jsduniya
1
@Siddesh Bhalke:你的服务可以返回任意的JSON数据。在这个例子中,autocompleteResults是一个对象数组,每个对象都有一个名为'YourDisplayProperty'的属性。 - Jason
我遇到了一个问题,就是列表在任何人点击之前就消失了。我通过这个问题的解决方案(来自此链接:https://dev59.com/Y2025IYBdhLWcg3wX070),用Corolla提供的方法来解决了这个问题。 - Mariusz.W
使用: if ($scope.$root.$$phase != '$apply' && $scope.$root.$$phase != '$digest') { $scope.$apply(); } - Cristian Martinez

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


                }
            }
        });

脚本文件导入顺序

  • 所有的jQuery文件
  • AngularJs库
  • 用于自动完成的Angular脚本

希望这能帮助到某些人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接