ng-opciones con filas deshabilitadas
¿Es posible usar ng-options
que se procesará en filas deshabilitadas según los criterios?
Esto:
<select ng-options="c.name group by c.shade for c in colors">
Tal vez sea posible convertirse en algo como esto:
<select ng-options="c.name group by c.shade for c in colors | disabled(c.shade)">
Y digamos a través de un filtro que podría devolver disabled='disabled'
para todos los colores que tienen 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>
11 answers
La respuesta de@lucuma (originalmente la respuesta aceptada) era correcta, pero ahora debería actualizarse, porque esto se arregló en Angular 1.4. Vea los documentos de ng-options que también contiene un ejemplo .
Estoy usando Angular 1.5 y esto funciona para mí:
Ver
<select ng-model="$ctrl.selectedItem" ng-options="item as item.label disable when item.disabled for item in $ctrl.listItems">
Controlador
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];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-12 23:16:10
Como señaló @Lod Angular agregó soporte para esto en 1.4.0-beta.5.
Para angular js >= 1.4.0-beta.5.
<select ng-options="c.name disable when c.shade == 'dark'
group by c.shade for c in colors">
Y para angular js refiérase a la solución siguiente:
Similar al dado por @lucumapero sin dependencia de jQuery.
Compruebe esto http://jsfiddle.net/dZDLg/46 /
Controlador
<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>
Directiva
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);
});
}
};
});
Nota: Esta solución no funciona con group by
como bien señaló todo el mundo. Consulte la solución a continuación por @DHlavaty si está buscando hacer que funcione con group by
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:38
Angular agregó soporte para esto en 1.4.0-beta.5
<select ng-options="c.name disable when c.shade == 'dark' group by c.shade for c in colors">
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-08 08:23:47
No creo que haya una manera de hacer lo que estás pidiendo solo usando ng-options
. Este problema se planteó en el proyecto angular y todavía está abierto:
Https://github.com/angular/angular.js/issues/638
Parece que la solución es usar una directiva a la que se hace referencia aquí y en el problema de github: http://jsfiddle.net/alalonde/dZDLg/9 /
Aquí está el código completo del jsfiddle para referencia (el código a continuación es de alande jsfiddle):
<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';
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-24 22:49:33
Desde febrero de 2015 ha habido una forma de deshabilitar las opciones en su etiqueta ng-options.
Este enlace muestra la adición de la característica en github
Encontré que usando angular 1.4.7, la sintaxis había cambiado de 'deshabilitar por' a 'deshabilitar cuando'.
La sintaxis para esto es:
'ng-options': 'o.value as o.name disable when o.unavailable for o in options'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-23 16:57:48
Se puede lograr un efecto similar utilizando ng-repeat
y ng-disabled
en la propia opción, evitando el uso de una nueva directiva.
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>
Controlador
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
Problemas conocidos:
- No utiliza
ng-options
- no funciona con
group by
- Selecciona el índice, no el objeto
- Requiere
$timeout
para la selección inicial
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-26 15:04:38
Tuve una situación interesante. Una matriz de desplegables y la necesito para deshabilitar las opciones que ya se seleccionaron en cada uno de los desplegables, pero también la necesito para mantener activa la que ya se seleccionó...
Aquí está mi émbolo: Habilitar / Deshabilitar valores con 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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-04 20:24:18
Solución "sin jQuery" similar a la de @Vikas-Gulati , pero funciona con group by
En mi caso, group by
no funciona, porque mi primer <option>
no tenía valor, solo con Please select and item from dropdown
texto. Esta es una versión ligeramente modificada, que corrige esta situación particular:
El uso es similar a @Vikas-Gulati respuesta: https://stackoverflow.com/a/20790905/1268533
Directiva
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);
});
}
};
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:05
Puede desactivar el uso de ngOptions en angular 1.4.1 o superior
Plantilla 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>
Código del controlador
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}];
})
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-20 08:12:56
Como no puedo actualizar a la última AngularJS, por lo que creó una directiva más simple para manejarlo.
.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');
}
}
});
}
}])
Para más detalles: https://github.com/farazshuja/disabled-options
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-30 11:01:33
También oculté las opciones deshabilitadas agregando la línea de barbecho:
$(this).css("display", fnDisableIfTrue(scope, locals) ? "none" : "block");
Era necesario, ya que no podía simplemente filtrarlos, ya que el valor inicial de esta selección podría ser una de las opciones deshabilitadas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-22 10:55:28