Как удалить пустую опцию после того, как фильтр изменит раскрывающийся список в Angular?

Я использую Angularjs 1.4.2, и мне нужно создать раскрывающийся список, который представляет собой комбинацию чисел и текста. Это массив объектов с двумя свойствами. Поэтому я использую числа как тип метки и конвертирую значение 0 и значения -1 в текст в верхней и нижней части списка.

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

Однако я продолжаю получать пустую опцию в списке, а текст «Выбрать элемент» по умолчанию для 0 не может быть предварительно выбран, когда появляется раскрывающийся список.

Я обнаружил, что

пустая опция генерируется, когда значение, на которое ссылается ng-model, не существует в наборе опций, переданных в ng-options

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

Мой код отлично работает без фильтра, но когда я пытаюсь применить фильтр, я получаю следующую ошибку: Ошибка: [$ rootScope: infdig] Достигнуто 10 итераций $ digest (). Прерывание!

В раскрывающемся списке есть правильные значения из фильтра, но пустая опция все еще там, и она выбрана вместо текста «Выбрать элемент», что я и хочу.

HTML:

<!DOCTYPE html>
<html ng-app="app">
  <head>
    <script data-require="[email protected]" data-semver="1.4.2" src="https://code.angularjs.org/1.4.2/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

   <body>
    <div ng-controller="Test">
        <p>selected item is : {{selectedItem}}</p>
      <p> The distance of selected item is : {{selectedItem.distance}} </p>
      <select ng-model="selectedItem" ng-options="item.distanceSize for item in items | myFilter" ng-init="selectedItem = items[0]">
      </select>
    </div>
  </body>
</html>

script.js

var app = angular.module('app',[]);

app.controller('Test',function($scope){
   $scope.items = [{"distance": "0", "distanceSize": 0},{"distance": "25", "distanceSize": 25},{"distance": "50", "distanceSize": 50},{"distance": "-1", "distanceSize": -1}];
});

app.filter('myFilter', function () {
  return function (items) {
    var valuesArray = [];
            if(items) {
                for(var i = 0; i < items.length; i++) {
                    var myObject = {};

                    if(items[i].distanceSize === 0) {
                        myObject.distanceLabel = "0";
                        myObject.distanceSize = "Select Item";
                        valuesArray.push(myObject);
                    }else if(items[i].distanceSize == 25) {
                        myObject.distanceLabel = "25";
                        myObject.distanceSize = 25;         
                        valuesArray.push(myObject);
                    }
                    else if(items[i].distanceSize == 50) {
                        myObject.distanceLabel = "50";
                        myObject.distanceSize = 50;         
                        valuesArray.push(myObject);
                    }
                    else if(items[i].distanceSize == -1) {
                        myObject.distanceLabel = "-1";
                        myObject.distanceSize = "Select Everything";            
                        valuesArray.push(myObject);
                    }
                }
            }
            return valuesArray;
  };
});

Поскольку мой раскрывающийся список изменен фильтром, как удалить или замаскировать пустой параметр и почему фильтр выдает ошибки?


person James Drinkard    schedule 19.06.2017    source источник


Ответы (1)


Достигнуто 10 итераций $ digest (). Прерывание!

Это хорошо известная проблема. Я бы обратился к этому вопросу о переполнении стека: Как устранить ошибку Angular «Достигнуто 10 итераций $ digest ()», в частности его ответ о возвращении новых объектов. Каждый раз, когда angular вызывает myFilter, он получает новый массив значений, который не === старый массив значений . Angular рассматривает это как изменение и вызывает фильтр снова и снова, пока он не прервет работу с ошибкой.

Вместо того, чтобы применять фильтр ко всему массиву, примените фильтр к метке. Это изменяет ваши параметры ng с:

ng-options="item.distanceSize for item in items | myFilter"

to

ng-options="item as (item.distanceSize | myFilter) for item in items"

Затем измените свой фильтр для обработки одного элемента:

app.filter('myFilter', function () {
    return function (distanceSize) {
        if (distanceSize === 0)
            return "Select Item";

        if (distanceSize === -1)
            return "Select Everything";

        return distanceSize;
    }
});

Вы можете увидеть пример в этом плунжере.

Пустая опция присутствует, потому что $scope.selectedItem является нулевым значением. Вы можете либо установить для него значение по умолчанию (как я сделал в плункере), либо вы можете жестко закодировать один элемент со значением, установленным в пустую строку. Затем этот элемент будет представлять нулевой или «не выбранный» вариант. Это может заменить ваш вариант «Выбрать элемент». Дополнительную информацию об этом можно найти в документации ngOptions.

person Jonathan Gawrych    schedule 19.06.2017
comment
Не понимая полностью процесса, стоящего за этим, я чрезмерно усложнял свой фильтр. Спасибо, что уделили время этому! - person James Drinkard; 20.06.2017