2015-05-08 25 views
16

Tôi có một bộ điều khiển có chức năng nhận một số cảnh báo từ API và cập nhật số đếm trên giao diện người dùng của trang web bị ràng buộc vào cảnh báo.AngularJS - ng-ràng buộc không cập nhật

Thật không may thuộc tính ng-bind tôi đang sử dụng dường như không cập nhật số lượng trực tiếp, mặc dù đơn giản console.log() cho tôi biết rằng số lượng cảnh báo thực tế đang được cập nhật trong bộ điều khiển.

Front-end

<div class="modeSelector modeSelector_oneUp" data-ng-controller="MyLivestockController as vm"> 
    <a class="modeSelector-mode" data-ui-sref="my-livestock"> 
     <div class="modeSelector-type">Alerts</div> 

     <img class="modeSelector-icon" src="/inc/img/_icons/envelope-black.svg" onerror="this.src=envelope-black.png" /> 

     <span data-ng-bind="vm.alertCount"></span> 
    </a> 
</div> 

khiển

(function() { 

    'use strict'; 

    function MyLivestockController(userService) { 

    var vm = this; 

    vm.myLivestockNotification = { 
     isLoading: true, 
     hasError: false 
    }; 

    vm.alertsNotification = { 
     isLoading: true, 
     hasError: false, 
     hasData: false 
    }; 

    vm.deleteAlert = function(id) { 

     vm.currentAlert = void 0; 
     vm.alertsNotification.isLoading = true; 

     userService.deleteAlert(vm.user.id, id).then(function() { 

     // Remove the alert from our Array 
     vm.alerts = vm.alerts.filter(function(alert) { 
      return alert.id !== id; 
     }); 

     // Refresh the alert count for the user 
     vm.getAlerts(vm.user.id); 

     vm.alertsNotification.isLoading = false; 
     vm.alertsNotification.hasError = false; 
     }, function() { 
     vm.alertsNotification.hasError = true; 
     }); 
    }; 

    vm.getAlerts = function(id) { 
     userService.getAlerts(id).then(function(alertData) { 
      vm.alertCount = alertData.length; 

      if (vm.alertCount > 0) { 
      vm.alertsNotification.hasData = true; 
      } else { 
      vm.alertsNotification.hasData = false; 
      } 

      vm.alerts = alertData; 

      vm.alertsNotification.isLoading = false; 
      vm.alertsNotification.hasError = false; 
     }, function() { 
      vm.alertsNotification.hasError = true; 
     }); 
    }; 

    // Init 
    (function() { 
     userService.getCurrentUser().then(function(data) { 
     vm.myLivestockNotification.hasError = false; 
     vm.myLivestockNotification.isLoading = false; 

     vm.user = data; 

     // Get alert count for the user 
     vm.getAlerts(vm.user.id); 
     }, function() { 
     vm.myLivestockNotification.hasError = true; 
     }); 
    })(); 
    } 

    angular 
    .module('abp') 
    .controller('MyLivestockController', MyLivestockController); 

})(); 

Dịch vụ

(function() { 

    'use strict'; 

    function userService($q, $sessionStorage, $localStorage, $filter, user) { 

    var service = this; 

    service.getAlerts = function(id) { 
     var deferred = $q.defer(); 

     user.alerts({ userID: id }, function(response) { 
     if (response.hasOwnProperty('data')) { 

      // Convert dates to valid Date 
      angular.forEach(response.data, function(alert) { 
      /* jshint camelcase: false */ 
      if (alert.created_at) { 
       alert.created_at = $filter('abpDate')(alert.created_at); 
      /* jshint camelcase: true */ 
      } 
      }); 

      deferred.resolve(response.data); 
     } 
     else { 
      deferred.reject('DATA ERROR'); 
     } 
     }, function(e) { 
     deferred.reject(e); 
     }); 

     return deferred.promise; 
    }; 

    angular 
    .module('abp') 
    .service('userService', userService); 

})(); 

Như bạn thấy, tôi đã có chức năng getAlerts() được gọi mỗi khi một cảnh báo bị xóa, bằng cách sử dụng chức năng deleteAlert(), nhưng <span data-ng-bind="vm.alertCount"></span> trên giao diện người dùng chỉ cập nhật sau khi làm mới trang, nơi tôi muốn cập nhật trực tiếp.

+0

Các bạn đã thử ng mô hình –

+1

thay đổi nó để '' 'ng mô hình = "vm.alertCount"' '' mà nên làm việc –

+0

@PaulFitzgerald. [ng-model] (https://docs.angularjs.org/api/ng/directive/ngModel) không thể được sử dụng với 'span'. – Zee

Trả lời

21

Ràng buộc của bạn không cập nhật vì bạn thay đổi giá trị của cảnh báoCount bên ngoài chu kỳ tiêu hóa của ứng dụng góc của bạn. Khi bạn làm mới ứng dụng, thông báo sẽ chạy và do đó giá trị của bạn sẽ được cập nhật. Quấn bản cập nhật của biến trong $ scope.apply() như vậy:

$scope.$apply(function(){ 
    vm.alertCount = alertData.length; 
}); 

Điều này sẽ buộc tiêu hóa và cập nhật giá trị trực tiếp.
Nếu bạn có nhiều giá trị được cập nhật bên ngoài tiêu hóa (bất kỳ gọi lại, hứa vv), bạn có thể buộc tiêu hóa chu kỳ bằng cách gọi:

$scope.$apply(); 

Hy vọng nó giúp.

EDIT -----
Với bản cập nhật của bạn với mã đầy đủ, tôi thấy rằng bạn đang không tiêm phạm vi bất cứ nơi nào trong điều khiển của bạn, các bộ điều khiển tôi viết thường bắt đầu như thế:

(function() { 

var app = angular.module('mainModule'); 

app.controller('myController', ['$scope', '$myService', function ($scope, $myService) { 

    //logic 
}]); 
}()); 

EDIT - ----
đây là một cách nhanh chóng đi tôi đã có trên mã của bạn:

(function() { 
'use strict'; 


var app = angular.module('abp'); 

app.controller('MyLivestockController', ['$scope', 'userService', function($scope, userService) { 

    var vm = {}; 
    $scope.vm = vm; 

    vm.myLivestockNotification = { 
     isLoading: true, 
     hasError: false 
    }; 

    vm.alertsNotification = { 
     isLoading: true, 
     hasError: false, 
     hasData: false 
    }; 

    vm.deleteAlert = function(id) { 

     vm.currentAlert = void 0; 
     vm.alertsNotification.isLoading = true; 

     userService.deleteAlert(vm.user.id, id).then(function() { 

      // Remove the alert from our Array 
      vm.alerts = vm.alerts.filter(function(alert) { 
       return alert.id !== id; 
      }); 

      // Refresh the alert count for the user 
      vm.getAlerts(vm.user.id); 

      vm.alertsNotification.isLoading = false; 
      vm.alertsNotification.hasError = false; 
     }, function() { 
      vm.alertsNotification.hasError = true; 
     }); 
    }; 

    vm.getAlerts = function(id) { 
     userService.getAlerts(id).then(function(alertData) { 
      vm.alertCount = alertData.length; 

      if (vm.alertCount > 0) { 
       vm.alertsNotification.hasData = true; 
      } else { 
       vm.alertsNotification.hasData = false; 
      } 

      vm.alerts = alertData; 

      vm.alertsNotification.isLoading = false; 
      vm.alertsNotification.hasError = false; 

      //important, this is promise so we have to apply the scope to update view 
      $scope.$apply(); 
     }, function() { 
      vm.alertsNotification.hasError = true; 
     }); 
    }; 

    // Init 
    (function() { 
     userService.getCurrentUser().then(function(data) { 
      vm.myLivestockNotification.hasError = false; 
      vm.myLivestockNotification.isLoading = false; 

      vm.user = data; 

      // Get alert count for the user 
      vm.getAlerts(vm.user.id); 
     }, function() { 
      vm.myLivestockNotification.hasError = true; 
     }); 
    })(); 
}]); 

})(); 

ý tưởng chung là:

  1. bạn tạo một ứng dụng (angular.module)
  2. bạn tạo một bộ điều khiển trong ứng dụng này, với $ phạm vi tiêm
  3. bất kỳ giá trị mà bạn muốn được cập nhật trên quan điểm của bạn, bạn thêm vào $ phạm vi
  4. nếu bạn có bất kỳ cập nhật phạm vi $ nào trong một cuộc gọi lại, sự kiện hoặc lời hứa, bạn quấn chúng vào (hoặc theo sau) $ scope.$ Áp dụng cuộc gọi

Tôi nghĩ rằng điều này sẽ làm việc cho bạn :)

+0

Cảm ơn, Daniel. Tôi đang đấu tranh để áp dụng '$ scope.apply()', tuy nhiên, khi tôi nhận được lỗi giao diện điều khiển khi làm như vậy. Tôi đã cập nhật mã ban đầu của tôi để cung cấp rõ ràng và bộ điều khiển đầy đủ, tôi có phải suy nghĩ của tôi '$ phạm vi không được xác định' lỗi là bởi vì tôi tham chiếu phạm vi như' vm'? –

+0

Tôi đã chỉnh sửa câu trả lời của mình bằng mã sẽ hoạt động cho bạn. –

1

tôi đã cố gắng để tái tạo mã của bạn dưới đây với một userService giả, và một số thay đổi nhỏ về quan điểm html vì vậy chúng tôi có thể thấy rõ hơn cảnh báo và xóa chúng. Tôi chưa sửa đổi Bộ điều khiển của bạn.

Điều này dường như hoạt động, phải không?

Điều này khiến tôi tin rằng có thể có một số vấn đề với việc triển khai UserService của bạn. Nếu bạn có thể đăng các mã có liên quan, tôi có thể cập nhật câu trả lời này với một giải pháp làm rõ.

CẬP NHẬT: Khi bạn đã cập nhật câu hỏi của mình với mã userService, tôi đã cập nhật bên dưới để phù hợp hơn. Tôi vẫn có dịch vụ mô phỏng đứng ở vị trí phụ thuộc user của userService. Ngoài ra, tôi đã thực hiện một vài chỉnh sửa nhỏ đối với lớp Trình điều khiển để trong khi các lời hứa vẫn đang giải quyết, chúng tôi có thể thấy 'Đang cập nhật ...' thay cho số lượng cảnh báo.

Tất cả điều này vẫn có vẻ hiệu quả, trừ khi tôi hiểu lầm - sẽ nghĩ nhiều hơn và cập nhật 'câu trả lời' này khi tôi có thể nghĩ đến nơi khác để điều tra nguồn gốc của vấn đề. tái sản xuất nó!

(function() { 
 

 
    'use strict'; 
 

 
    function MyLivestockController(userService) { 
 

 
    var vm = this; 
 

 
    vm.myLivestockNotification = { 
 
     isLoading: true, 
 
     hasError: false 
 
    }; 
 

 
    vm.alertsNotification = { 
 
     isLoading: true, 
 
     hasError: false, 
 
     hasData: false 
 
    }; 
 

 
    vm.deleteAlert = function(id) { 
 

 
     vm.currentAlert = void 0; 
 
     vm.alertsNotification.isLoading = true; 
 

 
     return userService.deleteAlert(vm.user.id, id).then(function() { 
 

 
     // Remove the alert from our Array 
 
     vm.alerts = vm.alerts.filter(function(alert) { 
 
      return alert.id !== id; 
 
     }); 
 

 
     // Refresh the alert count for the user 
 
     vm.getAlerts(vm.user.id).then(function() { 
 
      vm.alertsNotification.isLoading = false; //put here, loading isn't really finished until after .getAlerts() is done 
 
      vm.alertsNotification.hasError = false; 
 
     }); 
 

 
     }, function() { 
 
     vm.alertsNotification.hasError = true; 
 
     }); 
 
    }; 
 

 
    vm.getAlerts = function(id) { 
 

 
     vm.alertsNotification.isLoading = true; 
 

 
     return userService.getAlerts(id).then(function(alertData) { //return the promise so we can chain .then in .deleteAlert() 
 
     vm.alertCount = alertData.length; 
 

 
     if (vm.alertCount > 0) { 
 
      vm.alertsNotification.hasData = true; 
 
     } else { 
 
      vm.alertsNotification.hasData = false; 
 
     } 
 

 
     vm.alerts = alertData; 
 

 
     vm.alertsNotification.isLoading = false; 
 
     vm.alertsNotification.hasError = false; 
 
     }, function() { 
 
     vm.alertsNotification.hasError = true; 
 
     }); 
 
    }; 
 

 
    // Init 
 
    (function() { 
 
     userService.getCurrentUser().then(function(data) { 
 
     vm.myLivestockNotification.hasError = false; 
 
     vm.myLivestockNotification.isLoading = false; 
 

 
     vm.user = data; 
 

 
     // Get alert count for the user 
 
     vm.getAlerts(vm.user.id); 
 
     }, function() { 
 
     vm.myLivestockNotification.hasError = true; 
 
     }); 
 
    })(); 
 
    } 
 

 
    function userMock($q, $timeout, $log) { 
 
    var _alerts = { 
 
     data: [{ 
 
      id: 1, 
 
      message: "He doesn't sleep, he waits..." 
 
     }, { 
 
      id: 2, 
 
      message: "He doesn't mow his lawn, he stands outside and dares it to grow." 
 
     }, { 
 
      id: 3, 
 
      message: "Some magicians can walk on water. He can swim through land." 
 
     }] 
 
     }, 
 
     _currentUser = { 
 
     id: 'Q2h1Y2sgTm9ycmlz' 
 
     }; 
 

 
    return { 
 
     getCurrentUser: function getCurrentUser() { 
 
     $log.log("getCurrentUser"); 
 
     //return $q.when(_currentUser); 
 
     return $timeout(function() { //use $timeout to simulate some REST API latency... 
 
      return _currentUser; 
 
     }, 500); 
 
     }, 
 
     getAlerts: function getAlerts(id) { 
 
     $log.log("getAlerts: " + id); //not doing anything with the id in this mock... 
 
     $log.log(_alerts.data); 
 
     //return $q.when(_alerts); 
 
     return $timeout(function() { 
 
      return _alerts; 
 
     }, 500); 
 
     }, 
 
     deleteAlert: function deleteAlert(userId, id) { 
 
     $log.log("deleteAlert: " + userId + " :: " + id); 
 

 
     //return $q.when(_alerts); 
 
     return $timeout(function() { 
 

 
      for (var i = 0; i < _alerts.data.length; i++) { 
 
      if (_alerts.data[i].id === id) { 
 
       _alerts.data.splice(i, 1); 
 
       $log.log("alert found and deleted"); 
 
       break; 
 
      } 
 
      } 
 

 
      $log.log(_alerts.data); 
 

 
      return _alerts; 
 
     }, 500); 
 
     } 
 
    }; 
 
    } 
 

 
    function userService($q, $timeout, $log, userMock) { 
 

 
    var service = this; 
 

 
    service.getCurrentUser = userMock.getCurrentUser; 
 

 
    service.getAlerts = function(id) { 
 
     var deferred = $q.defer(); 
 

 
     userMock.getAlerts(id).then(function(response) { 
 
     if (response.hasOwnProperty('data')) { 
 

 
      // Convert 'he' to 'Chuck Norris' 
 
      angular.forEach(response.data, function(alert) { 
 
      if (alert.message) { 
 
       alert.message = alert.message.replace(/he/gi, "Chuck Norris"); 
 
      } 
 
      }); 
 

 
      deferred.resolve(response.data); 
 
     } else { 
 
      deferred.reject('DATA ERROR'); 
 
     } 
 
     }, function(e) { 
 
     deferred.reject(e); 
 
     }); 
 

 
     return deferred.promise; 
 
    }; 
 

 
    service.deleteAlert = function(userId, id) { 
 
     var deferred = $q.defer(); 
 

 
     userMock.deleteAlert(userId, id).then(function(response) { 
 
     deferred.resolve(response.data); 
 
     }, function(e) { 
 
     deferred.reject('DATA ERROR'); 
 
     }); 
 

 
     return deferred.promise; 
 
    }; 
 

 
    return service; 
 
    }; 
 

 

 
    angular 
 
    .module('abp', []) 
 
    .service('userMock', userMock) 
 
    .service('userService', userService) 
 
    .controller('MyLivestockController', MyLivestockController); 
 

 
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script> 
 
<div ng-app="abp"> 
 

 
    <div data-ng-controller="MyLivestockController as vm"> 
 
    <div>Alerts</div> 
 
    <span data-ng-bind="vm.alertsNotification.isLoading ? 'Updating...' : vm.alertCount"></span> 
 
    <div data-ng-repeat="alert in vm.alerts"> 
 
     {{alert.id}}: {{alert.message}} 
 
     <button ng-click="vm.deleteAlert(alert.id)">Delete</button> 
 
    </div> 
 
    </div> 
 

 
</div>

+0

Xin chào @ JcT, cảm ơn bạn đã trả lời, tôi đã cập nhật bài đăng gốc với dịch vụ người dùng. –

+0

Cảm ơn, @AlexRyans, vui lòng trợ giúp - Tôi cũng đã thực hiện cập nhật nhanh ở trên, nhưng vẫn cố gắng không ở trên đó; nếu tôi có thể tìm ra cách để tái tạo vấn đề, hy vọng sẽ có may mắn hơn trong việc tìm kiếm nguồn gốc của nó! – JcT

+0

Tôi nghĩ bước tiếp theo sẽ cố gắng tìm ra bộ mã đơn giản nhất để tái tạo vấn đề trong một đoạn trích hoặc một đoạn văn bản; có lý? – JcT

Các vấn đề liên quan