goofiw
goofiw

Reputation: 607

Angular bindings not updating within $interval and $http

I've tried different variations of $apply() and $digest() to no avail.

The binding should update once the courier is no longer null with the name of the courier, however nothing is happening. I've been able to log the name of the courier when they are assigned, however the dom element is not updating. I'm using jade and compiling to html without any issues elsewhere in the application. I'm also calling the refreshDelivery function immediately prior to rendering the view shown below, which is working correctly.

app.js:

    var storeController = require('./controllers/controller');



var storeApp = angular.module('AngularStore', ['ngRoute']).
  config(['$routeProvider', function($routeProvider) {
  $routeProvider.
    when('/store', { 
      templateUrl: 'views/store.html',
      controller: storeController }).
    when('/products/:productSku', {
      templateUrl: 'views/product.html',
      controller: storeController }).
    when('/cart', { 
      templateUrl: 'views/shoppingCart.html',
      controller: storeController }).
    when('/delivery', {
      templateUrl: 'views/delivery.html',
      controller: storeController }).
    otherwise({
      redirectTo: '/store' });
}])
  .controller('storeController', storeController);

controller.js:

      function storeController($scope, $routeParams, $http, $interval, DataService) {

  // get store and cart from service
  $scope.store = DataService.store;
  $scope.cart = DataService.cart;
  $scope.mapInit = DataService.mapInit;

  // use routing to pick the selected product
  if ($routeParams.productSku != null) {
    $scope.product = $scope.store.getProduct($routeParams.productSku);
  }

  // var locationOptions = {
  //   enableHighAccuracy: true,
  //   timeout: 5000,
  //   maximumAge: 0
  // }

  // navigator.geolocation.getCurrentPosition(function(pos){
  //   var mapOptions = {
  //     center: { lat: pos.coords.latitude, lng: pos.coords.longitude},
  //     zoom: 13
  //   };
  //   var map = new google.maps.Map(document.getElementById('map'),
  //       mapOptions);
  // });

  $scope.search = function(query){
    var responseObject;
    console.log('in search');
    $http({
      url:'/apiCall', 
      data: {data: '/products?keyword=' + query + '&latlong=36.125962,-115.211263'},
      method: 'POST'
    })
    .then(function(response){
      responseObject = response.data.data;
      responseObject.forEach(function(data){
        var productData = {
          sku: data.Id.SkuPartNumber,
          productName: data.Description.Name,
          desc: data.Description.BrandName,
          price: data.Price.DisplayPrice,
          url: data.Description.ImageURL,
          storeNumber: data.StoreNumber
        }
        var temp = new product(productData)
        $scope.store.addProduct(temp)
      });
    });
  }

  $scope.getDeliveryQuote = function(){
    var responseObject;
    $scope.quoted = false;
    var storeNumber = $scope.cart.items[0].storeNumber
    console.log($scope.cart.items[0].storeNumber);
    var url = '/delivery_quote?drop_off_latlong=36.125962,-115.211263&pickup_store_number='.concat(storeNumber);
    $http({
      url: '/apiCall/',
      data: {data: url},
      method: 'POST'
    })
    .then(function(response){
      $scope.quoted = true;
      console.log(response.data.id);
      $scope.quote = response.data.fee;
      $scope.quoteId = response.data.id
    })
  }

  $scope.submitOrder = function(){
    var url = '/submit_delivery?drop_off_latlong=36.125962,-115.211263&pickup_store_number=0001709&manifest=puppies&phone_number=555-555-5555&quote_id=' + $scope.quoteId + '&customer_name=Arnold';
    $http({
      url: '/apiCall/',
      data: {data: url},
      method: 'POST'
    })
    .then(function(response){
      console.log(response);
      $scope.deliveryId = response.data.id;
      $scope.refreshDelivery();
      window.location.href='/#/delivery';
    })
  }

  $scope.refreshDelivery = function() {
    var url = '/update?delivery_id='.concat($scope.deliveryId);
    var promise = $interval(function(){
      $http({
        url: '/apiCall/',
        data: {data: url},
        method: 'POST'
      })
      .then(function(resp) {
        $scope.update = resp.data;
        if (resp.data.courier){
          $scope.update.courier = resp.data.courier;
          console.log($scope.update.courier.name);//outputs correct name
          $scope.$apply();
        }
        //stops when complete
        if ($scope.update.complete){
          $interval.cancel(promise);
        }
      })
    }, 5000 );
  }
}

module.exports = storeController;

Jade before compiling to HTML:

Partial:

p.text-info {{update.courier.name}} is on their way!

Default:

html(ng-app='AngularStore')
  head
    // includes for jquery, angular, and bootstrap 
    script(src="https://maps.googleapis.com/maps/api/js?sensor=false")
    script(src='bower_components/jquery/dist/jquery.min.js') 
    script(rel='stylesheet' href='bower_components/bootstrap/dist/css/bootstrap.min.css')
    script(src='bower_components/angular/angular.js')
    script(src='bower_components/angular-route/angular-route.js')
    // includes for the Angular Store app
    script(src='/js/main.js')     
    script(src='/js/bundle.js')     
    link(href='/styles/main.css', rel='stylesheet', type='text/css')
    |   
  body
    .container-fluid
      .row-fluid
        .span10.offset1
          h1.well
            a(href='default.html')
            |                     Angular Store

          div(ng-view='')

Upvotes: 2

Views: 446

Answers (1)

goofiw
goofiw

Reputation: 607

I found a way around the $scope issue by creating a separate controller to handle updates.

app:

var storeController = require('./controllers/storeController'),
    deliveryController = require('./controllers/deliveryController');



var storeApp = angular.module('AngularStore', ['ngRoute']).
  config(['$routeProvider', function($routeProvider) {
  $routeProvider.
    when('/store', { 
      templateUrl: 'views/store.html',
      controller: storeController }).
    when('/products/:productSku', {
      templateUrl: 'views/product.html',
      controller: storeController }).
    when('/cart', { 
      templateUrl: 'views/shoppingCart.html',
      controller: storeController }).
    when('/delivery/:id', {
      templateUrl: 'views/delivery.html',
      controller: deliveryController }).
    otherwise({
      redirectTo: '/store' });
}])
  .controller('storeController', storeController);

new deliveryController

function deliveryController($scope, $routeParams, $http, $interval) {
  console.log($routeParams);

  var refreshDelivery = function(id) {
    var url = '/update?delivery_id='.concat(id);
    var promise = $interval(function(){
      $http({
        url: '/apiCall/',
        data: {data: url},
        method: 'POST'
      })
      .then(function(resp) {
        $scope.update = resp.data;
        if (resp.data.courier){
          $scope.update.courier = resp.data.courier;
          console.log($scope.update.courier.name);//outputs correct name
        }
        //stops when complete
        if ($scope.update.complete){
          $interval.cancel(promise);
        }
      })
    }, 5000 );
  }
  refreshDelivery($routeParams.id);
}

module.exports = deliveryController;

Upvotes: 1

Related Questions