共享控制器时视图不起作用

Non-functioning view when sharing controller

本文关键字:不起作用 视图 控制器 共享      更新时间:2023-09-26

我有一个简单的应用程序,可以从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>

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

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

实际上,看起来你在做我在上面一段中所说的,但我看不出在控制器中搜索函数是在哪里调用的。从本质上讲,你应该在控制器中有一些东西,直接从服务中填充$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);
            };
        }
    });