2

It's a simple webshop. So I'd like to load several things before show the home page and the controller.

I decided that the index.html will be also the Master Page containing a header, the ui-view for routing templates , a sidebar containing the categories and a footer.

<body ng-app="app">
    <header ng-include="'./templates/masterPage/header.html'"></header>
    <div ui-view></div>
    <sidebar ng-include="'./templates/masterPage/sideBar.html'"></sidebar>
    <footer ng-include="'./templates/masterPage/footer.html'"></footer>
</body>

The things on header, sidebar and footer will came from a json file containgin everything I need such as categories, currency, name of the webshop and others things that's will never changes after load.

So, I created the following app.js...

angular
.module('app', [
    'ui.router'
])
.config(['$urlRouterProvider', '$stateProvider',
    function ($urlRouterProvider, $stateProvider) {
        $urlRouterProvider.otherwise('/');
        $stateProvider
            .state('home', {
                url: '/',
                templateUrl: 'templates/common/home.html',
                controller: 'homeCtrl',
            })
}])
.run(function ($rootScope, $http) {
    $rootScope.api = "http://127.0.0.1:5000/demoShop";
    var call = $rootScope.api + "/frontEnd/loadStructure";
    $rootScope.webshop = $http.get(call).then(function (response) {
        console.log('1');
        return response.data;
    });
    console.log("2");
})

The problem is: check the console.logs in the end....2 executes before 1 because I can't make the $http to wait until go to the next line. How can I do it ?

I need to populate the webshop variable on rootscope before do anything.

Xm7X
  • 861
  • 1
  • 11
  • 23
Marco Jr
  • 6,496
  • 11
  • 47
  • 86

3 Answers3

0

Simple answer: You can't.

Longer answer: You can wait for the AJAX request to finish. That's what you're already doing - it's the function in .then. You can put your code there. Question is - why do you need it to be finished first? Or maybe better question is why do you need to do the request in the controller? Isn't it a bit too late for that? See related answer from Misko Hevery.

Community
  • 1
  • 1
Tomáš Fejfar
  • 11,129
  • 8
  • 54
  • 82
  • Because....Imagine a webshop: you have the header, the sidebar and the footer. There is dozes of links populated such as categories on the sidebar and others. When you change the views, the footer, sidebar and header never will change - Will always be the same - It's a "master page". So I need to lead everything before show my home page or even another page on my ui-view. – Marco Jr Nov 19 '14 at 19:53
  • if I don't wait for this to be finished, I can't, for example display {{webshop}} on the sidebar because the sidebar will be rendered before finish the $http. An alternative way that's works is to use {{webshop.$$state.value}} - But it's looks like a dirty way to solve the things (Yes, works...but sounds like a MacGaiver..I don't think that this is the best and clean way) – Marco Jr Nov 19 '14 at 19:56
  • I don't get it why you can't display webshop in sidebar. You can. It will be shown when the AJAX call is ready. That the whole point of doing it using AJAX call. If you don't need ajax call you can have the data hardcoded in the page. – Tomáš Fejfar Nov 19 '14 at 23:23
  • Other option would be to create the request by hand and make it synchronous. – Tomáš Fejfar Nov 21 '14 at 19:24
0

I would suggest resolving the data when the homeCtrl for the root-route loads. Then you can access you webshop data apon instaciation of the controller. Consider the example below:

angular
.module('app', [
    'ui.router'
])
.config(['$urlRouterProvider', '$stateProvider',
    function ($urlRouterProvider, $stateProvider) {
      var resolveLoadStructure = function() {
        $rootScope.api = "http://127.0.0.1:5000/demoShop";
        var call = $rootScope.api + "/frontEnd/loadStructure";
        return $http.get(call);
      };

      $urlRouterProvider.otherwise('/');
      $stateProvider
      .state('home', {
        url: '/',
        templateUrl: 'templates/common/home.html',
        controller: 'homeCtrl',
        resolve: {
          loadStructure: resolveLoadStructure
        }
      });
}])
.controller('homeCtrl', function($scope, loadStructure) {
  $scope.webshop = loadStructure;
})
cbass
  • 2,548
  • 2
  • 27
  • 39
  • This will not work for me...because the home is not necessarily the start point of my application. If someone decide to click in a link, for example..at Google pointing directly to a product, it's a different template, different controller as well..but thanks anyway :) – Marco Jr Nov 19 '14 at 19:50
0

I found the problem. My mistaken is to set the $rootScope directly - Instead I set this inner the callback. I just made a small surgery and everything works fine. Take a look

.run(function ($rootScope, $http) {
    $rootScope.nodeshop = "http://127.0.0.1:5000/rawDemo";
    var call = $rootScope.nodeshop + "/frontEnd/loadStructure";
    var head = {}; 
    $http.get(call).then(function (response) {
        $rootScope.webshop = response.data; //See ? this variable is no longer set as result of the $http return !
        return response.data;
    });
})
Marco Jr
  • 6,496
  • 11
  • 47
  • 86