0

我有一个简单的应用程序,它从 Flickr 获取图像并呈现它们。该应用程序分为两个视图,SearchViewPhotoListView。以前,当将这些视为一个视图时,一切正常,并且渲染了照片。现在,当共享控制器时,两者都被渲染,但照片列表永远不会被填充。调试时,我可以看到确实提取了照片。

我是 Angular 的新手,所以我真的没有很好地猜测问题可能是什么,但可能这两个视图没有正确共享范围?

这是路由(使用ui-router):

// app.js

'use strict';

angular.module('pruApp', ['ui.state'])
    .config(function ($httpProvider, $stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise('/photos');
        $stateProvider
            .state('/', {
                url: '/photos',
                views: {
                    'SearchView': {
                        templateUrl: '/views/search.html',
                        controller: 'PhotoCtrl'
                    },
                    'PhotoListView': {
                        templateUrl: '/views/photo-list.html',
                        controller: 'PhotoCtrl'
                    }
                }
            });

        // Remove X-Requested-With header to enable CORS
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
    });

与 Flickr 服务对话的控制器和工厂:

// photo.js

'use strict';

angular.module('pruApp')
    .controller('PhotoCtrl', function ($scope, PhotoFactory) {
        $scope.search = function() {
            PhotoFactory.getPhotos($scope.searchQuery).then(function (data) {
                $scope.photos = [];

                var parsedData = angular.fromJson(data);
                var items = parsedData.photos.photo;

                for (var i = 0; i < items.length; ++i) {
                    var photo = items[i];
                    $scope.photos.push({
                        title: photo.title,
                        image: 'http://farm' + photo.farm + '.staticflickr.com/' + photo.server + '/' + photo.id + '_' + photo.secret + '_m.jpg',
                        link: 'http://www.flickr.com/photos/' + photo.owner + '/' + photo.id
                    });
                }
            });
        };
    });

angular.module('pruApp')
    .factory('PhotoFactory', function ($http, $q) {
        return {
            _get: function(url) {
                var deferred = $q.defer();

                $http.get(url)
                    .success(function (data) {
                        deferred.resolve(data);
                    })
                    .error(function (data, status) {
                        deferred.reject('An error occured: ' + status);
                    });

                return deferred.promise;
            },
            getPhotos: function (searchQuery) {
                return this._get('http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=<MY_KEY>&tags=' + searchQuery + '&format=json&nojsoncallback=1');
            }
        };
    });

这是注入视图的地方:

<!-- index.html -->

<div class="main" role="main">
    <div class="search" ui-view="SearchView"></div>
    <div class="results" ui-view="PhotoListView"></div>
</div>

搜索模板:

<!-- search.html -->

<h2 class="struct">Search</h2>
<form>
    <fieldset>
        <div class="cell">
            <input type="search" name="search-query" class="search-query" placeholder="Search photos by tags (e.g. lolcat, rageface, bronie)" ng-model="searchQuery" required>
        </div>
        <div class="cell">
            <button type="submit" name="search-button" class="search-button" ng-click="search()">Search</button>
        </div>
    </fieldset>
</form>

照片列表模板:

<!-- photo-list.html -->

<h2 class="struct">Search results</h2>
<ul>
    <li ng-repeat="photo in photos">
        <h3>{{ photo.title }}</h3>
        <a href="{{ photo.link }}"><img ng-src="{{ photo.image }}" alt="{{ photo.title }}"></a>
        <p class="author">Author: <span>{{ photo.author }}</span></p>
    </li>
</ul>
4

1 回答 1

0

因此,您的问题似乎是您正在调用该方法以在控制器的一个实例上获取照片,但这并不与您的另一个控制器共享数据。在第一次阅读时,我错过了您的工厂定义,但问题仍然是控制器范围内的变量位于不同的实例中。

处理这个问题的方法是始终从工厂/服务返回一个承诺给控制器,在控制器中使用承诺分配范围。这样,如果服务已经有可用的数据,它将自动填充到您的控制器范围内,如果没有,则可以在可用时立即填充。

确实,看起来您正在执行我在上一段中所说的操作,但我看不到在控制器中调用搜索功能的位置。本质上,您应该在控制器中有一些东西直接从服务中填充 $scope.photos 数组。然后,您应该分别拥有搜索功能,该功能会触发对传递参数的服务的调用。

另一种选择是 $watch 您在工厂/服务中的属性,并在更改时更新控制器 $scope 中的变量。

angular.module('pruApp')
    .factory('PhotoFactory', function ($http, $q) {
        return {
            photos: [],
            _get: function(url) {
                var deferred = $q.defer();

                $http.get(url)
                    .success(function (data) {
                        this.photos = [];

                        var parsedData = angular.fromJson(data);
                        var items = parsedData.photos.photo;

                        for (var i = 0; i < items.length; ++i) {
                            var photo = items[i];
                            this.photos.push({
                                title: photo.title,
                                image: 'http://farm' + photo.farm + '.staticflickr.com/' + photo.server + '/' + photo.id + '_' + photo.secret + '_m.jpg',
                                link: 'http://www.flickr.com/photos/' + photo.owner + '/' + photo.id
                            });
                        }
                        deferred.resolve(data);
                    })
                    .error(function (data, status) {
                        deferred.reject('An error occured: ' + status);
                    });

                return deferred.promise;
            },
            getPhotos: function (searchQuery) {
                return this._get('http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=<MY_KEY>&tags=' + searchQuery + '&format=json&nojsoncallback=1');
            }
        };
    });

并在控制器中

angular.module('pruApp')
    .controller('PhotoCtrl', function ($scope, PhotoFactory) {
            $scope.$watch(function () { return PhotoFactory.photos; }, function(data) {
                 $scope.photos = data;
            }); // initialize the watch

            $scope.search = function() {
                PhotoFactory.getPhotos($scope.searchQuery);
            };
        }
    });
于 2013-07-13T09:18:03.200 回答