Ng-options с отключенными строками
Можно ли использовать ng-options
, чтобы он отображался в отключенных строках на основе критериев?
<select ng-options="c.name group by c.shade for c in colors">
возможно, может получиться что-то вроде этого:
<select ng-options="c.name group by c.shade for c in colors | disabled(c.shade)">
и скажем через фильтр, который может вернуть disabled='disabled'
для всех цветов, которые имеют оттенок = "темный"
<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>
Ответы
Ответ 1
Ответ на @lucuma (первоначально принятый ответ) был правильным, но теперь должен быть обновлен, поскольку это было исправлено в Angular 1.4. См. docs ng-options, который также содержит example.
Я использую Angular 1.5, и это работает для меня:
Вид
<select ng-model="$ctrl.selectedItem" ng-options="item as item.label disable when item.disabled for item in $ctrl.listItems">
контроллер
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];
Ответ 2
Как указано @Lod Angular, добавлена поддержка этого в 1.4.0-beta.5.
Для 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">
И для Angular js < 1.4.0-beta.5 см. Решение ниже:
Подобно тому, который задан @lucuma, но без зависимости jQuery.
Отметьте http://jsfiddle.net/dZDLg/46/
контроллер
<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.
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);
});
}
};
});
Примечание. Это решение не работает с group by
, как правильно указано всем. Обратитесь к решению ниже @DHlavaty, если вы хотите, чтобы он работал с group by
.
Ответ 3
Angular добавлена поддержка этого в 1.4.0-beta.5
<select ng-options="c.name disable when c.shade == 'dark' group by c.shade for c in colors">
Ответ 4
Я не верю, что есть способ сделать то, что вы просите, просто используя ng-options
. Эта проблема была поднята в проекте angular и по-прежнему открыта:
https://github.com/angular/angular.js/issues/638
Кажется, что работа вокруг заключается в использовании директивы, которая упоминается здесь и в проблеме github: http://jsfiddle.net/alalonde/dZDLg/9/
Вот весь код из jsfiddle для справки (код ниже из 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';
}
Ответ 5
С февраля 2015 года существует способ отключить параметры в теге ng-options.
Эта ссылка показывает добавление функции в github
Я обнаружил, что с использованием angular 1.4.7 синтаксис изменился с "disable by" на "disable when".
Синтаксис для этого:
'ng-options': 'o.value as o.name disable when o.unavailable for o in options'
Ответ 6
Аналогичный эффект может быть достигнут с использованием ng-repeat
и ng-disabled
в самой опции, избегая использования новой директивы.
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>
контроллер
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/
Известные проблемы:
- Не использует
ng-options
- Не работает с
group by
- Выбирает индекс, а не объект
- Требуется
$timeout
для первоначального выбора
Ответ 7
У меня была интересная ситуация. Массив выпадающих списков, и мне нужно, чтобы он отключил параметры, которые уже были выбраны в каждом раскрывающемся списке, но мне также нужно, чтобы он включал тот, который был выбран уже...
вот мой плукер: Включить/отключить значения с помощью 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>
Ответ 8
Аналогичное "без jQuery" решение как @Vikas-Gulati, но оно работает с group by
В моем случае group by
не работает, потому что мой первый <option>
был без значения, просто с текстом Please select and item from dropdown
. Это слегка измененная версия, которая фиксирует эту конкретную ситуацию:
Использование сравнимо с ответом @Vikas-Gulati: fooobar.com/questions/130372/...
Директива
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);
});
}
};
});
Ответ 9
Вы можете отключить использование ngOptions в angular 1.4.1 или выше
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>
Код контроллера
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}];
})
Ответ 10
Поскольку я не могу выполнить обновление до последнего углового значения JJ, поэтому была создана более простая директива для его обработки.
.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');
}
}
});
}
}])
для более подробной информации: https://github.com/farazshuja/disabled-options
Ответ 11
Я также скрывал отключенные опции, добавляя строку подбора:
$(this).css("display", fnDisableIfTrue(scope, locals) ? "none" : "block");
Это было необходимо, поскольку я не мог просто отфильтровать их, так как начальное значение этого выбора может быть одним из отключенных параметров.