web-dev-qa-db-fra.com

ng-options avec lignes désactivées

Est-il possible d'utiliser ng-options qui sera rendu dans les lignes désactivées en fonction de critères? 

ce:

 <select ng-options="c.name group by c.shade for c in colors">

peut-être possible de se transformer en quelque chose comme ceci:

 <select ng-options="c.name group by c.shade for c in colors | disabled(c.shade)">

et disons via un filtre qui pourrait renvoyer disabled='disabled' pour toutes les couleurs qui ont shade = "dark"

<select>
   <optgroup label="dark">
      <option value="0" disabled="disabled">black</option>
      <option value="2" disabled="disabled">red</option>
      <option value="3" disabled="disabled">blue</option>
   </optgroup>
   <optgroup label="light">
      <option value="1">white</option>
      <option value="4">yellow</option>
   </optgroup>
 </select>
50
iLemming

La réponse de @ lucuma (à l'origine la réponse acceptée) était correcte, mais devrait maintenant être mise à jour, car cela a été corrigé dans Angular 1.4. Voir les docs de ng-options qui contient également un exemple .

J'utilise Angular 1.5 et cela fonctionne pour moi:

Vue

<select ng-model="$ctrl.selectedItem" ng-options="item as item.label disable when item.disabled for item in $ctrl.listItems">

Manette

vm.items = [ { id: 'optionA', label: 'Option A' }, { id: 'optionB', label: 'Option B (recommended)' }, { id: 'optionC', label: 'Option C (Later)', disabled: true } ]; vm.selectedItem = vm.items[1]; 

46
Bart

Comme indiqué par @Lod Angular, la prise en charge de ceci dans 1.4.0-beta.5.

Pour js angulaire > = 1.4.0-beta.5.

<select ng-options="c.name disable when c.shade == 'dark' 
group by c.shade for c in colors">

Et pour js <1.4.0-beta.5 angulaire, reportez-vous à la solution ci-dessous:

Semblable à celui donné par @lucuma mais sans dépendance jQuery.

Vérifiez ceci http://jsfiddle.net/dZDLg/46/

Manette

<div ng-controller="OptionsController">
    <select ng-model="selectedport" 
        ng-options="p.name as p.name for p in ports"
        options-disabled="p.isinuse for p in ports"></select>
    <input ng-model="selectedport">
</div>

Directive

angular.module('myApp', [])
.directive('optionsDisabled', function($parse) {
    var disableOptions = function(scope, attr, element, data, 
                                  fnDisableIfTrue) {
        // refresh the disabled options in the select element.
        var options = element.find("option");
        for(var pos= 0,index=0;pos<options.length;pos++){
            var elem = angular.element(options[pos]);
            if(elem.val()!=""){
                var locals = {};
                locals[attr] = data[index];
                elem.attr("disabled", fnDisableIfTrue(scope, locals));
                index++;
            }
        }
    };
    return {
        priority: 0,
        require: 'ngModel',
        link: function(scope, iElement, iAttrs, ctrl) {
            // parse expression and build array of disabled options
            var expElements = iAttrs.optionsDisabled.match(
                /^\s*(.+)\s+for\s+(.+)\s+in\s+(.+)?\s*/);
            var attrToWatch = expElements[3];
            var fnDisableIfTrue = $parse(expElements[1]);
            scope.$watch(attrToWatch, function(newValue, oldValue) {
                if(newValue)
                    disableOptions(scope, expElements[2], iElement, 
                        newValue, fnDisableIfTrue);
            }, true);
            // handle model updates properly
            scope.$watch(iAttrs.ngModel, function(newValue, oldValue) {
                var disOptions = $parse(attrToWatch)(scope);
                if(newValue)
                    disableOptions(scope, expElements[2], iElement, 
                        disOptions, fnDisableIfTrue);
            });
        }
    };
});

Note: Cette solution ne fonctionne pas avec group by, comme le dit tout le monde à juste titre. Reportez-vous à la solution ci-dessous par @DHlavaty si vous souhaitez le faire fonctionner avec group by.

53
Vikas Gulati

Angular a ajouté le support pour cela dans 1.4.0-beta.5

<select ng-options="c.name disable when c.shade == 'dark' group by c.shade for c in colors">
26
lod

Je ne crois pas qu'il existe un moyen de faire ce que vous demandez en utilisant simplement ng-options. Cette question a été soulevée sur le projet angular et est toujours ouverte:

https://github.com/angular/angular.js/issues/638

Il semble que le travail consiste à utiliser une directive qui est référencée ici et dans le numéro de github: http://jsfiddle.net/alalonde/dZDLg/9/

Voici le code complet du jsfiddle à titre de référence (le code ci-dessous provient du jsfiddle d’alande):

<div ng-controller="OptionsController">
    <select ng-model="selectedport" 
        ng-options="p.name as p.name for p in ports"
        options-disabled="p.isinuse for p in ports"></select>
    <input ng-model="selectedport">
</div>

angular.module('myApp', [])
.directive('optionsDisabled', function($parse) {
    var disableOptions = function(scope, attr, element, data, fnDisableIfTrue) {
        // refresh the disabled options in the select element.
        $("option[value!='?']", element).each(function(i, e) {
            var locals = {};
            locals[attr] = data[i];
            $(this).attr("disabled", fnDisableIfTrue(scope, locals));
        });
    };
    return {
        priority: 0,
        require: 'ngModel',
        link: function(scope, iElement, iAttrs, ctrl) {
            // parse expression and build array of disabled options
            var expElements = iAttrs.optionsDisabled.match(/^\s*(.+)\s+for\s+(.+)\s+in\s+(.+)?\s*/);
            var attrToWatch = expElements[3];
            var fnDisableIfTrue = $parse(expElements[1]);
            scope.$watch(attrToWatch, function(newValue, oldValue) {
                if(newValue)
                    disableOptions(scope, expElements[2], iElement, newValue, fnDisableIfTrue);
            }, true);
            // handle model updates properly
            scope.$watch(iAttrs.ngModel, function(newValue, oldValue) {
                var disOptions = $parse(attrToWatch)(scope);
                if(newValue)
                    disableOptions(scope, expElements[2], iElement, disOptions, fnDisableIfTrue);
            });
        }
    };
});

function OptionsController($scope) {
    $scope.ports = [{name: 'http', isinuse: true},
                    {name: 'test', isinuse: false}];

    $scope.selectedport = 'test';
}
15
lucuma

Depuis février 2015, il existe un moyen de désactiver les options de votre balise ng-options.

Ce lien montre l'ajout de la fonctionnalité sur github

J'ai trouvé qu'en utilisant la version 1.4.7 angulaire, la syntaxe avait été modifiée de «désactiver par» à «désactiver quand».

La syntaxe est la suivante:

'ng-options': 'o.value as o.name disable when o.unavailable for o in options'
7
dafyddPrys

Un effet similaire peut être obtenu en utilisant ng-repeat et ng-disabled sur l'option elle-même, en évitant l'utilisation d'une nouvelle directive.

HTML

<div ng-controller="ExampleController">
    <select ng-model="myColor">
        <option ng-repeat="c in colors" ng-disabled="c.shade=='dark'" value="{{$index}}">
            {{c.name}}
        </option>
    </select>
</div>

Manette

function ExampleController($scope, $timeout) {
    $scope.colors = [
      {name:'black', shade:'dark'},
      {name:'white', shade:'light'},
      {name:'red', shade:'dark'},
      {name:'blue', shade:'dark'},
      {name:'yellow', shade:'light'}
    ];
    $timeout(function() {
        $scope.myColor = 4; // Yellow
    });
}

Fiddle

http://jsfiddle.net/0p4q3b3s/

Problèmes connus: 

  • N'utilise pas ng-options
  • Ne fonctionne pas avec group by
  • Sélectionne l'index, pas l'objet
  • Requiert $timeout pour la sélection initiale
6
Wasmoo

J'ai eu une situation intéressante. Un tableau de listes déroulantes et il me faut désactiver les options déjà sélectionnées dans chacune des listes déroulantes, mais j'ai également besoin de cette option pour conserver l'activation de celle déjà sélectionnée ...

voici mon plunker: Activer/Désactiver les valeurs avec ng-options

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

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

  // disable the fields by default
  $scope.coverage = [
    { CoverageType: '', CoverageName: 'No Coverage' },
    { CoverageType: 'A', CoverageName: 'Dependent Only' },
    { CoverageType: 'B', CoverageName: 'Employee Plus Children' },
    { CoverageType: 'C', CoverageName: 'Employee Only' },
    { CoverageType: 'D', CoverageName: 'Employee Plus One' },
    { CoverageType: 'E', CoverageName: 'Employee Plus Two' },
    { CoverageType: 'F', CoverageName: 'Family' },
];
            
            
  // values already set ex: pulled from db          
  $scope.rates = ['A','C', 'F'];     

  $scope.changeSelection = function (index, rate){
     $scope.rates[index] = rate;
     disableRecords();
  }
  
  // start by disabling records
  disableRecords(); 
  
  function disableRecords () {
      // set default values to false
      angular.forEach($scope.coverage, function (i, x) {
             i.disable = false; 
      });
      // set values to true if they exist in the array
      angular.forEach($scope.rates, function (item, idx) {
          angular.forEach($scope.coverage, function (i, x) {
              if (item == i.CoverageType) {
                   i.disable = true; 
              }
          });
      });
  }
  

});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="ngoptions">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script data-require="[email protected]" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <table>
      <thead></thead>
      <tbody>
        <tr ng-repeat="rate in rates">
          <td>
            <select 
            ng-model="rate" 
            ng-change="changeSelection($index, rate)" 
            ng-options="type.CoverageType as type.CoverageName disable when (type.disable == true && type.CoverageType != rate) for type in coverage"></select>
          </td>
        </tr>
      </tbody>
    </table>
  </body>

</html>

3

Solution "sans jQuery" similaire à @ Vikas-Gulati ', mais fonctionne avec group by

Dans mon cas, group by ne fonctionne pas, car mon premier <option> était sans valeur, avec juste le texte Please select and item from dropdown. Ceci est une version légèrement modifiée, qui corrige cette situation particulière:

L'utilisation est similaire à @ Vikas-Gulati answer: https://stackoverflow.com/a/20790905/1268533

Directive

angular.module('disabledModule', [])
    .directive('optionsDisabled', function($parse) {
        var disableOptions = function(scope, attr, element, data, fnDisableIfTrue) {
            var realIndex = 0;
            angular.forEach(element.find("option"), function(value, index){
                var elem = angular.element(value);
                if(elem.val()!="") {
                    var locals = {};
                    locals[attr] = data[realIndex];
                    realIndex++; // this skips data[index] with empty value (IE first <option> with 'Please select from dropdown' item)
                    elem.attr("disabled", fnDisableIfTrue(scope, locals));
                }
            });
        };
        return {
            priority: 0,
            require: 'ngModel',
            link: function(scope, iElement, iAttrs, ctrl) {
                // parse expression and build array of disabled options
                var expElements = iAttrs.optionsDisabled.match(/^\s*(.+)\s+for\s+(.+)\s+in\s+(.+)?\s*/);
                var attrToWatch = expElements[3];
                var fnDisableIfTrue = $parse(expElements[1]);
                scope.$watch(attrToWatch, function(newValue, oldValue) {
                    if(newValue)
                        disableOptions(scope, expElements[2], iElement, newValue, fnDisableIfTrue);
                }, true);
                // handle model updates properly
                scope.$watch(iAttrs.ngModel, function(newValue, oldValue) {
                    var disOptions = $parse(attrToWatch)(scope);
                    if(newValue)
                        disableOptions(scope, expElements[2], iElement, disOptions, fnDisableIfTrue);
                });
            }
        };
    });
2
DHlavaty

Vous pouvez désactiver ngOptions dans les versions 1.4.1 et supérieures angulaires

Modèle HTML

<div ng-app="myapp">
<form ng-controller="ctrl">
    <select id="t1" ng-model="curval" ng-options='reportingType.code as reportingType.itemVal disable when reportingType.disable for reportingType in reportingOptions'>
        <option value="">Select Report Type</option>
    </select>

</form>

Code du contrôleur

angular.module('myapp',[]).controller("ctrl", function($scope){
$scope.reportingOptions=[{'code':'text','itemVal':'TEXT','disable':false}, {'code':'csv','itemVal':'CSV','disable':true}, {'code':'pdf','itemVal':'PDF','disable':false}];

})

2
Raja Rathinam

Comme je ne peux pas passer à la dernière angularJS, une directive plus simple a été créée pour la gérer.

.directive('allowDisabledOptions',['$timeout', function($timeout) {
    return function(scope, element, attrs) {
        var ele = element;
        var scopeObj = attrs.allowDisabledOptions;
        $timeout(function(){
            var DS = ele.scope()[scopeObj];
            var options = ele.children();
            for(var i=0;i<DS.length;i++) {
                if(!DS[i].enabled) {
                    options.eq(i).attr('disabled', 'disabled');
                }
            }
        });
    }
}])

pour plus de détails: https://github.com/farazshuja/disabled-options

1
FarazShuja