yarkov
@yarkov
Помог ответ? Отметь решением.

$scope.$watch и немного магии. Где ошибка?

Смотрим демо с открытой консолью: ДЕМО
Имеем сервис dataService.js
/*global angular*/

(function() {
    'use strict';

    angular
        .module('App')
        .service('dataService', ['$http', dataService]);
        
    function dataService($http){
    	var self = this;
    	
        self.data = [
				{
					"id": "bf2ff391-b5f1-44f5-9fcf-c7cd081dd290",
					"url": "mail.ru",
					"login": "user",
					"password": "password"
				},
				{
					"id": "dbf66cd2-89d9-4a20-a303-18c5703ec510",
					"url": "toster.ru",
					"login": "user",
					"password": "password"
				},
				{
					"id": "f7d50ae5-c3a6-4bc7-8d4b-adf711e19462",
					"url": "ya.ru",
					"login": "user",
					"password": "password"
				}
			];
        
        self.columnNames = ['№', 'URL страницы', 'Логин', 'Пароль'];
        
		/**
		 * Метод загрузит из localStorage список учетных данных, если он там есть и он не пуст.
		 *
		 * @method getLocalData
		 *
		 * @return {Array} Список учетных данных.
		 */
        self.getLocalData = function(){
            // Если ключ с именем "data" существует в localStorage
			if (localStorage["data"]) {
				var data = JSON.parse(localStorage["data"]);
				// Если это массив и он не пустой
				if (angular.isArray(data) && data.length > 0) {
					self.data = data;
					console.log("SERVICE LOAD:", self.data);
				}
			}
			return self.data;
        }
        
		/**
		 * Метод сохранит в localStorage список учетных данных, переданный в параметре dataArray.
		 *
		 * @method setLocalData
		 * 
		 * @param  {Array} dataArray Список учетных данных.
		 *
		 * @return {Array} Список учетных данных.
		 */
        self.setLocalData = function(dataArray){
        	self.data = dataArray;
            localStorage["data"] = JSON.stringify(dataArray);
            console.log("SERVICE SAVE:", self.data);
        }
    }
    
    dataService.$inject = ['$http'];

})();

И контроллер AppCtrl.js
/*global angular*/

(function() {
    'use strict';

	angular
	    .module('App')
		.controller('AppCtrl', ['$scope', 'dataService', 'cryptoService', AppCtrl]);

	/**
	 * Основной контроллер приложения.
	 *
	 * @method AppCtrl
	 *
	 * @param  {dependence} $scope Основная зависимость контроллера.
	 *
	 * @param  {AngularService} dataService Сервис для получения данных для формирования списка записей.
	 * 
	 * @param  {AngularService} cryptoService Сервис содержащий криптографические методы.
	 */
	function AppCtrl($scope, dataService, cryptoService) {
		/* jshint validthis: true */
		var vm = this;

		vm.addFormUrl = '';
		vm.addFormLogin = '';
		vm.addFormPassword = '';
		vm.selectedAll = false;
		// Загружаем названия заголовков таблицы из localStorage
		vm.columnNames = dataService.columnNames;
		// Загружаем список учетных данных из localStorage
		vm.data= dataService.getLocalData();


		/**
		 * Метод добавит элемент в список учетных записей.
		 *
		 * @method addItem
		 */
		vm.addItem = function () {
			// Избегаем записи пустых полей
			if ((!vm.addFormUrl || vm.addFormUrl.length < 1) || 
				(!vm.addFormLogin || vm.addFormLogin.length < 1) || 
				(!vm.addFormPassword || vm.addFormPassword.length < 1)) {
				return;
			}
			
			var uuid = cryptoService.getUUID();

			// Добавляем запись в список
			vm.data.push({
				id: uuid, // Получаем из метода сервиса значение для id записи
				url: vm.addFormUrl,
				login: vm.addFormLogin,
				password: vm.addFormPassword
			});

			// Подчищаем за собой
			vm.addFormUrl = '';
			vm.addFormLogin = '';
			vm.addFormPassword = '';
		}

		/**
		 * Метод удалит элемент из списка на текущей строке.
		 *
		 * @method removeItem
		 *
		 * @param  {Number} index Индекс элемента в массиве Model.data.
		 *
		 * @return {Null} Ничего не возвращает.
		 */
		vm.removeItem = function (index) {
			try{
				vm.data.splice(index, 1);
			}
			catch(e){

			}
		}

		/**
		 * Метод удалит все отмеченные чекбоксами элементы из списка.
		 *
		 * @method removeAllSelected
		 *
		 * @return {Null} Ничего не возвращает.
		 */
		vm.removeAllSelected = function () {
			// Найдем все элементы массива, у которых 'selected' == true
			var rItems = vm.data.findAll({'selected': true});
			// В цикле пройдемся по найденному массиву и удалим все элементы
			angular.forEach(rItems, function(item){
				var index = vm.data.indexOf(item);
				if(index > -1){
					vm.data.splice(index, 1);
				}
			});
			// Подчищаем за собой
			rItems = null;
			// Снимаем выделение с чекбоксов
			vm.selectedAll = false;
		}

		/**
		 * Метод выделит или снимет выделение со всех чекбоксов в списке.
		 *
		 * @method allItemsToggleSelection
		 *
		 * @return {Null} Ничего не возвращает.
		 */
		vm.allItemsToggleSelection = function () {
			if (vm.selectedAll) {
				vm.selectedAll = true;
			} else {
				vm.selectedAll = false;
			}
			angular.forEach(vm.data, function (item) {
				item.selected = vm.selectedAll;
			});
		}

		// Следим за изменениями списка учетных данных и поддерживаем в localStorage актуальное состояние
		$scope.$watch(
			'vm.data',
			function (newVal, oldVal, scope) {
				console.log("$scope.$watch is worked:", vm.data);
				dataService.setLocalData(vm.data);
			},
			true
		);

	}

	AppCtrl.$inject = ['$scope', 'dataService', 'cryptoService'];
	
})();

Так вот. До выноса логики в сервис все работало. Теперь $watch отрабатывает один раз при загрузке приложения и больше не реагирует на изменения vm.data. То есть элементы удаляются и добавляются, но в localStorage не сохраняются.
  • Вопрос задан
  • 232 просмотра
Решения вопроса 1
yarkov
@yarkov Автор вопроса
Помог ответ? Отметь решением.
Сам спросил - сам отвечу )))
Инфа отсюда: stackoverflow
Вся проблема в области видимости как я понял. В общем меняем код на этот:
$scope.$watch(
	angular.bind(vm, function () { 
		return vm.data;
	}),
	function (newVal, oldVal, scope) {
		console.log("$scope.$watch is worked:", vm.data);
		if (newVal) {
			dataService.setLocalData(vm.data);
		}
	},
	true
);

И наслаждаемся ))
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы