问题
I'm pretty new to Angular and trying to achieve something "basic". I've been googling for 2 days without success and would appreciate some help.
I have an html page on which I'm trying to:
- Initialize data with a HTTP POST request
- Call a function via the ng-change event to update the data with another HTTP POST when elements used as filters are changed (i.e. categories, sorting asc/desc...)
My problem is that when I'm updating the model programmatically with the HTTP response (only in this case), it triggers the ng-change event attached to the element, which itself calls the update function and then enters in an infinite loop: ng-change -> updating function -> ng-change -> updating function
Note: I'm using Angular Material template but it doesn't change the code
HTML
<html ng-app="MyApp">
<body layout="column" ng-controller="SearchServiceController">
<h1 class="md-headline">Filter results</h1>
<form name="searchServiceForm" novalidate>
<md-input-container>
<md-select placeholder="Choose category" ng-model="searchService.selectedCategory" ng-change="changedSearchServiceCriteria()">
<md-option ng-value="category.value" ng-repeat="category in listOfCategories">{{ category.title }}</md-option>
</md-select>
</md-input-container>
<md-input-container>
<md-select placeholder="Sort by" ng-model="searchService.sortBy" ng-change="changedSearchServiceCriteria()">
<md-option ng-value="criteria.value" ng-repeat="criteria in sortByCriterias">{{ criteria.title }}</md-option>
</md-select>
</md-input-container>
</form>
<h1 class="md-headline">{{ selectedCategory.title }}</h1>
<p class="md-body-1">{{ selectedCategory.description }}</p>
</body>
</html>
JS
var app = angular.module('MyApp', ['ngMaterial']);
app.controller('SearchServiceController', function($scope, $http, $location) {
// Initialize data using the category id parameter in the URL
$http({
method: 'POST',
url: '/projets/get-offerings-list',
data: {selectedCategory: $location.path().split("/")[4]},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function(response) {
alert('INIT');
$scope.listOfCategories = response.listOfCategories;
$scope.sortByCriterias = response.sortByCriterias;
$scope.searchService = response.searchService;
})
.error(function(response) {
console.log('Failure occured');
});
// Update data
$scope.changedSearchServiceCriteria = function() {
$http({
method: 'POST',
url: '/projets/get-offerings-list',
data: {selectedCategory: $location.path().split("/")[4]},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function(response) {
alert('UPDATE');
$scope.listOfCategories = response.listOfCategories;
$scope.sortByCriterias = response.sortByCriterias;
$scope.searchService = response.searchService;
})
.error(function(response) {
console.log('Failure occured');
});
};
});
RESULT
INIT
Object {listOfCategories: Array[3], sortByCriterias: Array[2], searchService: Object}
UPDATE
Object {listOfCategories: Array[3], sortByCriterias: Array[2], searchService: Object}
UPDATE
Object {listOfCategories: Array[3], sortByCriterias: Array[2], searchService: Object}
UPDATE
Object {listOfCategories: Array[3], sortByCriterias: Array[2], searchService: Object}
UPDATE
Object {listOfCategories: Array[3], sortByCriterias: Array[2], searchService: Object}
UPDATE
Object {listOfCategories: Array[3], sortByCriterias: Array[2], searchService: Object}
....infinite loop....
This doesn't occur when I'm updating the model programmatically without using the response of the HTTP request. See here: http://plnkr.co/edit/baNjr85eAOkKVu4dnf1m?p=preview Would you have any ideas on how I could update the form element without provoking the ng-change event?
Thanks
Please note that I do not want to use a workaround using $watch like there: ngChange is called when model changed programmatically
回答1:
You should try to add a working example into http://jsfiddle.net/ or similar.
I would think at a guess and not tested that you need to keep the last search and only run the update AJAX request if it changes as it gets a new address (or whatever thats called in JS) every time - even though its the same value and re evaluates again
$scope.searchService = "";
$scope.lastSearch = ""
// Update data using form elements
$scope.changedSearch = function() {
if($scope.searchService != $scope.lastSearch){
$http({
method: 'POST',
url: '/projects/get-list',
data: $scope.searchService,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function(response) {
// Request succeeded? Display message
console.log('UPDATE');
console.log(response);
// Update data
$scope.listOfCategories = response.listOfCategories;
$scope.sortByCriterias = response.sortByCriterias;
$scope.searchForm = response.searchForm;
})
.error(function(response) {
// Request failed? Display message
console.log('Failure occured');
})
.complete(function(response) {
// do after success or error
$scope.lastSearch = $scope.searchService;
console.log('complete');
});
}
};
来源:https://stackoverflow.com/questions/31464323/setting-scope-mymodel-element-with-ng-change-enters-in-infinite-loop