简体   繁体   中英

How can I implement resolve in my app.config with these snippets?

This is my code:

Service Module

(function () {
var servicesSushi = angular.module('SushiServices', ['ngResource']);

servicesSushi.factory('Data', ['$resource',
    function ($resource) {
        return $resource('Data/:name.json', {}, {
            getInfoMenu: { method: 'GET', params: { name: 'sushiMenu' },      isArray: true },
            getInfoPlaces: { method: 'GET', params: { name:    'sushiPlaces' }, isArray: true }
        });
    }]);
})();

In my app.config

(function () {
var app = angular.module('Sushi', ['ngRoute','SushiServices', 'SushiControllers']);

app.config(['$routeProvider',
    function ($routeProvider) {
        $routeProvider.
            when('/menu', {
                templateUrl: 'partials/_menu.html',
                controller: 'MenuController'
            }).
            when('/places', {
                templateUrl: 'partials/_places.html',
                controller: 'PlacesController'

    }]); //I have removed the other .whens and the otherwise for simplicity.
})();

My controlls module

(function () {
var SushiAppControllers = angular.module('SushiControllers', ['ngSanitize']);
SushiAppControllers.controller('MenuController', ['$scope', 'Data',
    function ($scope, Data) {
        $scope.pos = 1;
        $scope.dataMenu = Data.getInfoMenu();
        $scope.setPos = function (value) {
            $scope.pos = value;
        };
        $scope.isPos = function (value) {
            return $scope.pos === value;
        };
    }]);
SushiAppControllers.controller('PlacesController', ['$scope', '$sce', 'Data',
    function ($scope, $sce, Data) {
        $scope.pos = 1;
        $scope.dataPlaces = Data.getInfoPlaces();
        $scope.urlMap = function () {
            return $sce.trustAsResourceUrl($scope.dataPlaces[$scope.pos - 1].map);
        };
        $scope.setPos = function (value) {
            $scope.pos = value;
        };
    }]);
})();

My problem: When I first try to visit the view associated with places, nothing shows; then, whenever I visit it again, everything works fine. I think I get that part, the view is ready before the data arrives, right? The thing is, I don't want the user to have to click a button twice in order to get results, how can I prevent that from happening?

Also, please explain the resolve property in the simplest way you can possibly find.

Side note, getInfoMenu throws Invalid Token Exception . I've checked thoroughly, my json is lengthy but valid. BTW Sorry if all that sushi made you hungry.

I'm sorry if this seems duplicated, but I can't really understand this resolve thing. I've read the blog with the three stories, and some of the questions, eg this , this , this ; but I haven't been able to understand any of the approaches.

EDIT Actually, all of my views take two clicks before they load correctly. Let me explain further, I have a navbar, I click the first button, nothing happens, go to second button, nothing happens go to third and fourth button, nothing happens. But when I return to the first and so forth after the first click, it works! The Unexpected Token thingy is still happening, though.

First thing i spotted: Your working with a promise. Data.getInfoMenu() returns a promise which needs to be resolved. Your assigning the promise to your scope:

$scope.dataMenu = Data.getInfoMenu();

Instead you should be doing this:

Data.getInfoMenu().$promise.then(function(dataMenu) {
  $scope.dataMenu = dataMenu;
});

Now it waits untill the promise is resolved then it assigns the retrieved data to your scope. Here's a very simple explanation on how promises work in Angular: http://andyshora.com/promises-angularjs-explained-as-cartoon.html

Now for the resolve object in your route: In it's simplest form it works like this:

$routeProvider.when('/menu', {
    templateUrl: 'partials/_menu.html',
    controller: 'MenuController',
    resolve: {
        dataMenu: function () {
            return [
                'Chirashizushi',
                'Inarizushi'
            ];
        }
    }
});

Now in your controller you can inject dataMenu :

SushiAppControllers.controller('MenuController', [
    '$scope',
    'dataMenu',
    function ($scope, dataMenu) {
        $scope.dataMenu = dataMenu;
    }
]);

The dataMenu array is now available in your scope. But the real beauty of resolve is that you can use it to resolve promises from resources and/or services. It will wait untill they are resolved (hence the name) then it will instanciate your controller. Next example using your service:

$routeProvider.when('/menu', {
    templateUrl: 'partials/_menu.html',
    controller: 'MenuController',
    resolve: {
        dataMenu: ['Data', function (Data) {
            return Data.getInfoMenu();
        }]
    }
});

Now dataMenu is also available in your controller. The only difference is this time it comes from your service and your don't have to resolve the promise yourself, the route's resolve object fixes that for you.

Here's a nice but more detailed example of using resolve, only it's for ui.router not angular-route but the concept remains the same: https://github.com/angular-ui/ui-router/wiki#resolve

So that's about it, i can't explain it any simpler i think. Hope that helps, and here's a working example of the concept, with your sushi on Plunker: http://plnkr.co/edit/sXQBcczLxhHSnbXfYOJl?p=preview Now i'm really hungry ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM