Saya memiliki layanan berikut di app saya:
uaInProgressApp.factory('uaProgressService',
function(uaApiInterface, $timeout, $rootScope){
var factory = {};
factory.taskResource = uaApiInterface.taskResource()
factory.taskList = [];
factory.cron = undefined;
factory.updateTaskList = function() {
factory.taskResource.query(function(data){
factory.taskList = data;
$rootScope.$digest
console.log(factory.taskList);
});
factory.cron = $timeout(factory.updateTaskList, 5000);
}
factory.startCron = function () {
factory.cron = $timeout(factory.updateTaskList, 5000);
}
factory.stopCron = function (){
$timeout.cancel(factory.cron);
}
return factory;
});
Kemudian saya menggunakan controller seperti ini:
uaInProgressApp.controller('ua.InProgressController',
function ($scope, $rootScope, $routeParams, uaContext, uaProgressService) {
uaContext.getSession().then(function(){
uaContext.appName.set('Testing house');
uaContext.subAppName.set('In progress');
uaProgressService.startCron();
$scope.taskList = uaProgressService.taskList;
});
}
);
Jadi pada dasarnya saya update layanan pabrik.taskList
setiap 5 detik dan saya terkait hal ini pabrik.taskList
ke $scope.taskList
. Saya kemudian mencoba metode yang berbeda seperti $menerapkan
, $mencerna
tetapi perubahan pada pabrik.taskList
tidak tercermin dalam controller dan view $scope.taskList
.
Masih kosong di template saya. Apakah anda tahu bagaimana saya dapat menyebarkan perubahan ini ?
Saat menggunakan $jam
dapat memecahkan masalah, bukan solusi yang paling efisien. Anda mungkin ingin mengubah cara anda menyimpan data di layanan.
Masalahnya adalah bahwa anda mengganti lokasi memori yang anda taskList
dikaitkan untuk setiap kali anda menetapkan nilai baru sedangkan cakupan terjebak menunjuk ke lokasi lama. Anda dapat melihat hal ini terjadi dalam memetik.
Mengambil tumpukan foto-foto dengan Chrome ketika anda pertama kali memuat memetik dan, setelah anda mengklik tombol, anda akan melihat bahwa lokasi memori lingkup poin untuk tidak pernah diperbarui sementara daftar menunjuk ke lokasi memori yang berbeda.
Anda dapat dengan mudah memperbaikinya dengan memiliki layanan anda memegang sebuah objek yang mengandung variabel yang dapat berubah (sesuatu seperti data:{tugas:[], x:[], z:[]}
). Dalam hal ini "data" tidak boleh berubah tapi setiap anggotanya dapat berubah setiap kali anda perlu. Anda kemudian lulus ini data variabel ruang lingkup dan, asalkan anda don't menimpa dengan mencoba untuk menetapkan "data" untuk sesuatu yang lain, setiap kali sebuah field dalam data perubahan lingkup akan tahu tentang hal itu dan akan memperbarui dengan benar.
Ini memetik menunjukkan contoh yang sama berjalan dengan menggunakan perbaikan yang disarankan di atas. Tidak perlu menggunakan pengamat dalam situasi ini dan jika itu pernah terjadi bahwa ada sesuatu yang tidak diperbarui pada tampilan anda tahu bahwa semua yang perlu anda lakukan adalah menjalankan lingkup $apply
untuk memperbarui tampilan.
Dengan cara ini anda menghilangkan kebutuhan untuk pengamat yang sering membandingkan variabel untuk perubahan dan jelek setup yang terlibat dalam kasus-kasus ketika anda perlu untuk menonton banyak variabel. Satu-satunya masalah dengan pendekatan ini adalah bahwa pada pandangan anda (html) anda akan memiliki "data." awalan segala sesuatu di mana anda digunakan untuk hanya memiliki variabel nama.
Sudut (tidak seperti Ember dan beberapa framework lain), tidak menyediakan khusus wrapped benda-benda yang semi-magically tinggal di sync. Benda-benda yang anda memanipulasi polos objek javascript dan hanya seperti mengatakan var a = b;
tidak link variabel a
dan b
, katakan $scope.taskList = uaProgressService.taskList
tidak menghubungkan kedua nilai-nilai.
Untuk jenis link
-ing, sudut
menyediakan [$jam
pada $lingkup
](http://docs.angularjs.org/api/ng.$rootScope.Ruang lingkup). Anda dapat menonton nilai uaProgressService.taskList
dan update nilai pada $lingkup
ketika perubahan:
$scope.$watch(function () { return uaProgressService.taskList }, function (newVal, oldVal) {
if (typeof newVal !== 'undefined') {
$scope.taskList = uaProgressService.taskList;
}
});
Ekspresi pertama diteruskan ke $jam
fungsi ini dijalankan pada setiap $mencerna
loop dan argumen kedua adalah fungsi yang dipanggil dengan yang baru dan yang lama nilai.
I'm tidak yakin jika itu membantu, tapi apa yang saya lakukan adalah mengikat fungsi untuk $scope.nilai. Misalnya
angular
.module("testApp", [])
.service("myDataService", function(){
this.dataContainer = {
valA : "car",
valB : "bike"
}
})
.controller("testCtrl", [
"$scope",
"myDataService",
function($scope, myDataService){
$scope.data = function(){
return myDataService.dataContainer;
};
}]);
Kemudian aku hanya mengikat di DOM sebagai
<li ng-repeat="(key,value) in data() "></li>
Dengan cara ini anda dapat menghindari untuk menggunakan $menonton di kode anda.
Tidak ada $jam
atau dll. diperlukan. Anda hanya dapat mendefinisikan sebagai berikut
uaInProgressApp.controller('ua.InProgressController',
function ($scope, $rootScope, $routeParams, uaContext, uaProgressService) {
uaContext.getSession().then(function(){
uaContext.appName.set('Testing house');
uaContext.subAppName.set('In progress');
uaProgressService.startCron();
});
$scope.getTaskList = function() {
return uaProgressService.taskList;
};
});
Karena fungsi getTaskList
milik $lingkup
nilai kembali akan dievaluasi (dan diperbarui) pada setiap perubahan dari uaProgressService.taskList
Ringan alternatif adalah bahwa selama inisialisasi pengendali anda berlangganan notifier pola diatur dalam pelayanan.
Sesuatu seperti:
app.controller('YourCtrl'['yourSvc', function(yourSvc){
yourSvc.awaitUpdate('YourCtrl',function(){
$scope.someValue = yourSvc.someValue;
});
}]);
Dan layanan ini memiliki sesuatu seperti:
app.service('yourSvc', ['$http',function($http){
var self = this;
self.notificationSubscribers={};
self.awaitUpdate=function(key,callback){
self.notificationSubscribers[key]=callback;
};
self.notifySubscribers=function(){
angular.forEach(self.notificationSubscribers,
function(callback,key){
callback();
});
};
$http.get('someUrl').then(
function(response){
self.importantData=response.data;
self.notifySubscribers();
}
);
}]);
Hal ini dapat membiarkan anda fine tune lebih hati-hati ketika anda pengendali refresh dari layanan.
Seperti Gabriel Piacenti mengatakan, tidak ada jam tangan yang diperlukan jika anda membungkus mengubah data menjadi sebuah objek.
TETAPI untuk memperbarui mengubah layanan data di lingkup dengan benar, adalah penting bahwa ruang lingkup nilai controller yang menggunakan layanan data tidak menunjuk secara langsung untuk mengubah data (field). Bukan lingkup nilai harus menunjuk ke objek yang membungkus mengubah data.
Kode berikut akan menjelaskan hal ini lebih jelas. Dalam contoh, saya menggunakan NLS Layanan untuk menerjemahkan. NLS Token mendapatkan diperbarui melalui http.
Layanan:
app.factory('nlsService', ['$http', function($http) {
var data = {
get: {
ressources : "gdc.ressources",
maintenance : "gdc.mm.maintenance",
prewarning : "gdc.mobMaint.prewarning",
}
};
// ... asynchron change the data.get = ajaxResult.data...
return data;
}]);
Controller dan cakupan ekspresi
app.controller('MenuCtrl', function($scope, nlsService)
{
$scope.NLS = nlsService;
}
);
<div ng-controller="MenuCtrl">
<span class="navPanelLiItemText">{{NLS.get.maintenance}}</span>
</div>
Kode di atas bekerja, tapi pertama-tama saya ingin mengakses NLS Token langsung (lihat cuplikan berikut) dan di sini nilai-nilai yang tidak menjadi diperbarui.
app.controller('MenuCtrl', function($scope, nlsService)
{
$scope.NLS = nlsService.get;
}
);
<div ng-controller="MenuCtrl">
<span class="navPanelLiItemText">{{NLS.maintenance}}</span>
</div>