使用ng-change设置$ scope.myModel元素进入无限循环

时间:2015-07-16 20:53:30

标签: angularjs angularjs-scope angularjs-ng-change

我对Angular很新,并尝试实现“基本”的东西。我一直在谷歌搜索2天没有成功,并希望得到一些帮助。

我有一个html页面,我正在尝试:

  1. 使用HTTP POST请求初始化数据
  2. 通过ng-change事件调用函数,当用作过滤器的元素发生更改时,使用另一个HTTP POST更新数据(即类别,排序asc / desc ...)
  3. 我的问题是,当我使用HTTP响应(仅在这种情况下)以编程方式更新模型时,它会触发附加到元素的ng-change事件,该事件本身会调用更新函数然后进入无限循环: ng-change - >更新功能 - > ng-change - >更新功能

    注意:我正在使用Angular Material模板,但它不会更改代码

    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....
    

    当我在不使用HTTP请求的响应的情况下以编程方式更新模型时,不会发生这种情况。见这里:http://plnkr.co/edit/baNjr85eAOkKVu4dnf1m?p=preview 您是否对如何在不激发ng-change事件的情况下更新表单元素有任何想法?

    由于

    请注意,我不想使用$ watch这样的解决方法:ngChange is called when model changed programmatically

1 个答案:

答案 0 :(得分:0)

您应该尝试将工作示例添加到http://jsfiddle.net/或类似内容中。

我会猜测,并且没有测试过你需要保留最后一次搜索,只有当它每次都获得一个新地址(或者在JS中调用的任何内容)发生变化时才运行更新AJAX请求 - 即使它相同的值并重新评估

$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');
        });
    }
};