Javascript-форум (https://javascript.ru/forum/)
-   Angular.js (https://javascript.ru/forum/angular/)
-   -   Как правильно изменять наблюдаемый объект? (https://javascript.ru/forum/angular/53764-kak-pravilno-izmenyat-nablyudaemyjj-obekt.html)

capscom 17.02.2015 14:01

Как правильно изменять наблюдаемый объект?
 
Здравствуйте !
Есть большая форма, с зависимыми между собой элементами. При изменении значений формы, нужно слать запрос, для получения ответа от сервера.

<select ng-model="form.brandId" ng-options="brand.id as brand.name for brand in brands"></select>
  <select ng-model="form.modelId" ng-options="model.id as model.name for model in models"></select>


$scope.form = {};

$scope.$watchCollection('form', function(form){                       
       if ( ! form.brandId && form.modelId){
            delete form.modelId;    
       }                      
      console.log('load data ...');
});


И возникает проблема в самом $watch-ре, если нужно удалить значение модели, когда выбран бренд, то функция вызовется повторно, т.к. наблюдаемый объект изменился. И из-за этой ситуации, появляются лишние запросы к серверу.

Подскажите, пожалуйста, как работать с множеством зависимых элементов, чтобы не допускать повторных вызовов $watchCollection ?

ksa 17.02.2015 14:59

capscom, ты бы примерчик тестовый нормально сделал для начала... К чему эти огрызки? Они что-то могут объяснить?

capscom 17.02.2015 15:10

Цитата:

Сообщение от ksa (Сообщение 356988)
capscom, ты бы примерчик тестовый нормально сделал для начала... К чему эти огрызки? Они что-то могут объяснить?

Исправляюсь. Вот пример, на базе кода описанного в задаче. Пихать огромную форму с проекта, нет смысла, там очень много условий, помимо текущих.

plnkr


Собственно проблема видна при выполнении delete form.modelId. После чего функция запускается повторно, так как объект изменился. Вопрос как сделать так, чтобы можно было изменять в объекте разом несколько свойств и функция в $watchCollection отрабатывала разово.

ksa 17.02.2015 15:38

Цитата:

Сообщение от capscom
Пихать огромную форму с проекта, нет смысла

Она тут никому и не нужна... :D

Пример должен быть максимально прост и выложен прямо тут. Причем с возможностью запуска...
А твоя ссылка дает мне чистую страницу.

capscom 17.02.2015 16:17

Цитата:

Сообщение от ksa (Сообщение 356997)
Она тут никому и не нужна... :D

Пример должен быть максимально прост и выложен прямо тут. Причем с возможностью запуска...
А твоя ссылка дает мне чистую страницу.

Странно, а так ?
jsfiddle

ksa 17.02.2015 16:20

Цитата:

Сообщение от capscom
а так ?

Второй вариант рабочий... :yes:

Но я предлагаю таки тут показывать, так оно и не потеряется. ;)

Вот примерчик, два селекта...

<!DOCTYPE html>
<html ng-app>
<head>
<script src="http://code.angularjs.org/1.1.4/angular.min.js"></script>
<!--
<script src='http://code.jquery.com/jquery-latest.js'></script>
<link rel='stylesheet type=text/css href=tmp.css' />
-->
<style type='text/css'>
</style>
<script type='text/javascript'>
function cntrl($scope) {
	$scope.items1 = [
		{name: 0},
		{name: 1},
		{name: 2},
		{name: 3},
		{name: 4}
	];
	$scope.items2 = [
		{name: 0},
		{name: 1},
		{name: 2},
		{name: 3},
		{name: 4}
	];
	$scope.$watch(
		"items1", 
		function(newVal, oldVal) {
			// получили изменение
		},
		true
	);
	$scope.$watch(
		"items2", 
		function(newVal, oldVal) {
			// получили изменение
		},
		true
	);
	$scope.item1 = $scope.items1[1];
	$scope.item2 = $scope.items2[2];
}
</script>
</head>
<body> 
<div ng-controller="cntrl">
	<select ng-model="item1" ng-options="o.name for o in items1"></select>
	<select ng-model="item2" ng-options="o.name for o in items2"></select>
</div>
</body>
</html>

Что ты с ними хотел замутить?

capscom 17.02.2015 16:32

Суть простая, если мы в первом селекте убираем значение, то автоматом сбрасывается значение в связанном селекте. Например, есть селекты: марка и модель авто, если юзер сбрасывает марку, то и значение модели не нужно.

В объекте form, хранятся все выбранные значения юзером. И при изменении свойства шлется запрос постом к серваку.

$scope.$watchCollection('form', function(form){                                     
	      $scope.posts = PostService.getPosts(form);
});



Как-то не хочется вешать по $watch на каждый отдельный селект. У меня на форме порядка 30 элементов, и явно будет все подтупливать. Хотел как-то красиво обойтись одним. Да вот столкнулся с траблой, что если сбрасывать значения связанных селектов, непосредственно в функции $watchCollection, получаем кучу левых запросов.

ksa 17.02.2015 16:50

Цитата:

Сообщение от capscom
если юзер сбрасывает марку, то и значение модели не нужно

Тогда зачем вообще это "слежение"? :blink:

Можно просто повесить обработчик на селект и все дела...

<!DOCTYPE html>
<html ng-app>
<head>
<script src="http://code.angularjs.org/1.1.4/angular.min.js"></script>
<!--
<script src='http://code.jquery.com/jquery-latest.js'></script>
<link rel='stylesheet type=text/css href=tmp.css' />
-->
<style type='text/css'>
</style>
<script type='text/javascript'>
function cntrl($scope) {
	$scope.brands = [{id: null, name: 'B1'}, {id: 1, name: 'B2'}, {id: 2, name: 'B3'}];
	$scope.models = [{id: 1, name: 'M1'}, {id: 2, name: 'M2'}];
	$scope.brand = null;
	$scope.model = null;
	$scope.newBrand = function() {
		if ($scope.brand==null) {
			$scope.model=null;
		};
	};
}
</script>
</head>
<body> 
<div ng-controller="cntrl">
	<label>Бренды
		<select ng-model="brand" ng-options="o.name for o in brands" ng-change='newBrand()'>
			<option></option>
		</select>
	</label>
	<label>Модели
		<select ng-model="model" ng-options="o.name for o in models"></select>
	</label>
</div>
</body>
</html>

ksa 17.02.2015 16:52

capscom, сдается мне ты эти следилки не к месту используешь...

capscom 17.02.2015 17:01

Цитата:

Сообщение от ksa (Сообщение 357008)
capscom, сдается мне ты эти следилки не к месту используешь...

А в чем ошибка использования ? Вариант с ng-change, нравится больше)


Часовой пояс GMT +3, время: 04:50.