поле выбора: отображать текст «ошибка», если значение не существует в массиве

У меня есть пара значений ключа, определенная, как показано ниже, которая используется для выбора с использованием ng-options.

 $scope.BucketEnum = [
    { display: 'Error', value: 0 },
    { display: '1', value: 1 },
    { display: '2', value: 2 },
    { display: '3', value: 3 },
    { display: '4', value: 4 },
    { display: '5', value: 5 },
    { display: 'Flows', value: 125 },
    { display: 'Recovery', value: 151 }
];

Я использую эту пару значений ключа для отображения поля выбора в ng-options.

     <select ng-model="selectedBucket" ng-options="row.value as rows.display for row in BucketEnum" multiple="multiple" ></select>

теперь, если я установлю ng-model, т.е. $scope.selectedBucket = 10, я хочу отобразить текст Error. Можно ли показать значение Error для всех значений, которых нет в массиве $scope.BucketEnum.

ПРИМЕЧАНИЕ

Я смотрю на более общий способ сделать это, например, фильтр для этого

СЦЕНАРИЙ

В базе данных есть определенные исторические данные, в которых есть мусор и хорошие данные.

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


person harishr    schedule 27.10.2014    source источник
comment
Я думаю, что вы не можете сделать это с $filter, фильтр просто фильтрует данные с помощью некоторого процесса или условий и возвращает данные для замены оригинала.. поэтому я думаю, что вы должны реализовать директиву, соответствующую вашим потребностям.   -  person rahpuser    schedule 05.11.2014
comment
фильтр получает список объектов, поэтому это должно быть возможно   -  person harishr    schedule 05.11.2014
comment
на самом деле вы не можете использовать фильтр для ng-repeat, а также вы не можете использовать фильтр для назначения ng-модели, поэтому единственный способ, которым я представляю, - это вызвать фильтр в области видимости, см. мой ответ .. надеюсь, будет полезно .. Редактировать: Я думаю, это будет только для установки значений инициалов, верно?   -  person rahpuser    schedule 05.11.2014
comment
Что вы имеете в виду, когда значения ошибок могут быть случайными?   -  person rahpuser    schedule 05.11.2014
comment
Итак, если ваши инициалы 1,2,5,10,12, вам нужно добавить 10 и 12 с ошибкой как «отображение» в вашем выборе?   -  person rahpuser    schedule 05.11.2014
comment
я бы скорее сказал .. если значение поля ведра для текущей строки в таблице не равно 1,2,5, то добавьте его в список с отображением как ошибка   -  person harishr    schedule 05.11.2014
comment
Я предполагаю, что это произойдет только при правильной установке значений инициалов? если это так, возможно, это сработает для вас jsfiddle.net/rahpuser/vzsahavn/1   -  person rahpuser    schedule 05.11.2014


Ответы (3)


Будет ли это соответствовать вашим потребностям?

jsfiddle

app.filter('bootstrapValues', function(){
    return function(initial, baseBucket){
        var result = [];
        for(var i=0; i<initial.length; i++){
            var flag = false;
            for(var j=1; j<baseBucket.length; j++){ //from 1 or 0.. you call
                if(initial[i] === baseBucket[j].value){
                    flag = true;
                    result.push(baseBucket[j]);
                    break; // if there are repeated elements
                }
            }
            if(!flag)
                result.push(baseBucket[0])
        }
        return result;
    };
});

Используя его для запуска selectedBucket, в вашем контроллере:

   // setting initials
        $scope.selectedBucket = $filter('bootstrapValues')(initialSet, $scope.bucketEnum);

Это помогает?

Изменить: вот другой jsfiddle с небольшими изменениями, если значение не находится в ведре, оно добавляет элемент в список с ошибкой отображать и как выбранное значение.

person rahpuser    schedule 05.11.2014
comment
обновленная скрипка сделала свое дело... именно то, что я искал. хотя требует небольшой модификации, учитывая, что значения ошибок приходят как часть ответа API, поэтому у меня нет списка ошибок с самого начала... - person harishr; 06.11.2014

Использование ng-options генерирует несколько элементов HTML <select> для каждого элемента в вашем массиве BucketEnum и «возвращает» выбранное значение в вашей переменной ng-model: selectedBucket. Я думаю, что единственный способ отобразить параметры без дополнительной пустой записи — убедиться, что значение selectedBucket является допустимой записью в BucketEnum.

В вашем вопросе говорится:

если я установлю ng-модель, т.е. $scope.selectedBucket = 10, я хочу отобразить текст Error.

Я предполагаю, что вы хотите отобразить значение: {{BucketEnum[selectedBucket].display}}

Итак... начиная с $scope.selectedBucket = 10, нам нужен какой-то общий способ реализации select с использованием ng-options, который сбросит это значение до значения по умолчанию.

Вы можете сделать это, внедрив директиву атрибута, позволяющую писать:

<select ng-model="selectedBucket" select-default="BucketEnum"
        ng-options="row.value as row.display for row in BucketEnum" 
        multiple="multiple">

Пример такого подхода показан ниже. Обратите внимание, что это предполагает, что значение по умолчанию равно нулю и не обрабатывает несколько вариантов выбора (вам придется перебирать варианты выбора при сравнении с каждым элементом в BucketEnum и решать, что делать, если есть сочетание допустимых и недопустимых вариантов выбора).

app.directive("selectDefault",function(){
    return{
        restrict: 'A',
        scope: false,
        link:function(scope,element,attrs){
            var arr= scope[attrs.selectDefault];    // array from attribute  
            scope.$watch(attrs.ngModel,function(){
                var i, ok=false;
                var sel= scope[attrs.ngModel];      // ng-model variable
                for( i=0; i<arr.length; i++){       // variable in array ?
                    if( arr[i].value == sel )       // nasty '==' only for  demo
                        ok= true;
                }
                if( ! ok )
                    scope[attrs.ngModel]=0;    // set selectedBucket to 0
            });
        }
    };
});

Я запустил здесь jsfiddle

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

Если это то решение, которое вы искали, вы можете расширить директиву всеми возможными способами, например:

<select ng-model="selectResult"
        select-default="99" array="BucketEnum" initial="selectedBucket"
        ng-options="row.value as row.display for row in BucketEnum" 
        multiple="multiple">

... идея состоит в том, что директива select-default будет читать значение по умолчанию (здесь "99"), значения array и initial, а затем соответственно устанавливать selectResult

person TonyWilk    schedule 06.11.2014
comment
Я проверил это следующим образом: $timeout(function(){ $scope.selectedBucket = 10; // начать с недопустимого сегмента console.log(value 10) }, 5000); отлично работает - person harishr; 06.11.2014

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

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

<div ng-app="myApp">
    <div ng-controller="myController">
        <p>Select something</p>
    <select ng-model="selectedBucket" 
     ng-options="row as row.display for row in bucketEnum" multiple="multiple">
    </select>
    </div>
</div>

.

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

app.controller('myController', function ($scope) {

     var initialSet = [1, 5, 10];

     $scope.bucketEnum = [
        { display: 'Error', value: 0 },
        { display: '1', value: 1 },
        { display: '2', value: 2 },
        { display: '3', value: 3 },
        { display: '4', value: 4 },
        { display: '5', value: 5 },
        { display: 'Flows', value: 125 },
        { display: 'Recovery', value: 151 }
     ];

    var selected = [];
    var error = $scope.bucketEnum[0];
    angular.forEach(initialSet, function(item) {
        var found;
        angular.forEach($scope.bucketEnum, function (e) {
            if (+item == +e.value) {
                console.log('Found ', e);
              found = item;
              selected.push(e);
            }
        });
        if (typeof found === 'undefined') {
            selected.push(error);
        }
        $scope.selectedBucket = selected;
        console.log(selected);
      });
 });
person Ian Mercer    schedule 01.11.2014
comment
могу ли я как-то не вставлять это в фильтр или что-то в этом роде, чтобы сделать его универсальным... Я искал более общее решение, иначе просто нужно выполнить поиск и установить ошибку, если он не найден... - person harishr; 01.11.2014
comment
Вы можете написать угловой фильтр для фильтрации bucketEnum, чтобы получить только те, которые соответствуют initialSet, но впоследствии вам все равно нужно будет добавить ошибку. Вы можете сделать это, сравнив длину отфильтрованного списка с длиной начального набора, если они не равны, какой-то элемент не совпал, но вы не можете сделать это внутри цикла. Но это не звучит проще/легче для чтения, чем приведенный выше код. - person Ian Mercer; 01.11.2014
comment
Вы также можете переместить этот код в директиву или службу, чтобы сделать его более пригодным для повторного использования и сохранить «тощий» контроллер. - person Ian Mercer; 01.11.2014