11

我正在创建一个 ajax 搜索页面,该页面将由一个搜索输入框、一系列过滤器下拉列表以及一个显示结果的 UL 组成。

由于搜索的过滤器部分将位于页面上的单独位置,我认为创建一个服务来处理协调输入和对搜索服务器端的 ajax 请求是一个好主意。然后可以由几个单独的控制器调用它(一个用于搜索框和结果,一个用于过滤器)。

我正在努力解决的主要问题是在调用 ajax 时刷新结果。如果我将 ajax 直接放在 SearchCtrl 控制器中,它可以正常工作,但是当我将 ajax 移到 Service 时,它​​会在调用 Service 上的 find 方法时停止更新结果。

我确定这是我错过的一些简单的事情,但我似乎看不到它。

标记:

<div ng-app="jobs">
    <div data-ng-controller="SearchCtrl">
        <div class="search">
            <h2>Search</h2>
            <div class="box"><input type="text" id="search" maxlength="75" data-ng-model="search_term" data-ng-change="doSearch()" placeholder="Type to start your search..." /></div>
        </div>
        <div class="search-summary">
            <p><span class="field">You searched for:</span> {{ search_term }}</p>
        </div>
        <div class="results">
            <ul>
                <li data-ng-repeat="item in searchService.results">
                    <h3>{{ item.title }}</h3>
                </li>
            </ul>
        </div>
    </div>
</div>

AngularJS:

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

app.factory('searchService', function($http) {
    var results = [];

    function find(term) {
        $http.get('/json/search').success(function(data) {
            results = data.results;
        });
    }

    //public API
    return {
            results: results,
            find: find
    };
});

app.controller("SearchCtrl", ['$scope', '$http', 'searchService', function($scope, $http, searchService) {
    $scope.search_term = '';
    $scope.searchService = searchService;

    $scope.doSearch = function(){
        $scope.searchService.find($scope.search_term);
    };

    $scope.searchService.find();
}]);

这是一个粗略的 JSFiddle,我已经注释掉了 ajax,我只是手动更新结果变量作为示例。为简洁起见,我没有包含过滤器下拉菜单。

http://jsfiddle.net/XTQSu/1/

我对AngularJS很陌生,所以如果我以完全错误的方式去做,请告诉我:)

4

2 回答 2

29

在您的 HTML 中,您需要引用在控制器的 $scope 上定义的属性。一种方法是在控制器中绑定一次$scope.searchService.resultssearchService.results

$scope.searchService.results = searchService.results;

现在这条线将起作用:

<li data-ng-repeat="item in searchService.results">

在你的服务中,使用angular.copy()而不是分配一个新的数组引用results,否则你的控制器的 $scope 将失去它的数据绑定:

var new_results = [{ 'title': 'title 3' }, 
                   { 'title': 'title 4' }];
angular.copy(new_results, results);

小提琴。在小提琴中,我注释掉了对 find() 的初始调用,因此当您在搜索框中输入内容时,您可以看到更新发生。

于 2013-03-11T18:22:41.253 回答
1

问题是您永远不会在您的范围内更新您的结果。有很多方法可以做到这一点,但根据您当前的代码,您可以首先修改您的find函数以返回结果:

function find(term) {
    $http.get('/json/search').success(function(data) {
            var results = data.results;

    });
    //also notice that you're not using the variable 'term' 
    //to perform a query in your webservice
    return results;
}

您在“公共 API”中使用模块模式,因此您的searchService返回find函数和数组results,但您想让函数find负责实际返回结果。

撇开这一点不谈,每当您在范围内调用doSearch()时,您都希望更新searchService返回的结果的当前结果

$scope.doSearch = function(){
    $scope.searchService.results = searchService.find($scope.search_term);
};

我用我的想法更新了你的 jsfiddle,它不起作用,但我添加了一些评论和日志来帮助你调试这个问题。http://jsfiddle.net/XTQSu/3/

于 2013-03-11T16:22:47.560 回答