我想构建一个列表,其功能类似于给定参数的select或multiselect。例如。如果参数为false,请选择A->选择B,取消选择A并选择B.
<ul>
<li>a,</li>
<li>b, and</li>
<li>c</li>
</ul>
我最初的方法看起来像:
<ul myDirective>
<li ng-model="a">a,</li>
<li ng-model="b">b, and</li>
<li ng-model="c">c</li>
</ul>
mydirective监视LI的点击。单击它确定是否需要取消选择或取消设置任何内容。然后选择新值an并应用选定的类。
我不认为我遵循了有棱有角的范式,我正在寻找一些帮助,找到正确的前进道路。
**编辑** 我希望提供以下用户体验:http://jsfiddle.net/qbt2myj8/
答案 0 :(得分:2)
在我看来,自已使用AngularJS后,自定义指令将使您的代码更加干净。
以下是使用AngularJS Custom Directive的完整解决方案,该指令完全可以重复用于代码组织。
<强> HTML 强>
自定义指令默认行为
<ul data-my-directive class="list">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
(这只是截图预览。请参阅下面的PLAYGROUND
链接进行播放)
<强> HTML 强>
使用自定义属性
<ul data-my-directive data-multi-select="true" class="list">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
(这只是截图预览。请参阅下面的PLAYGROUND
链接进行播放)
<强>的Javascript 强>
angular.module('app',[])
.directive('myDirective', function(){
return {
transclude: true,
template: '<div ng-transclude></div>',
link: function(scope, element, attrs){
function addClickListener(i, callback){
selections[i].addEventListener('click', function(){
callback(i);
}, false);
}
// Set up attribute value. Goes to default if attribute is not set up
attrs.multiSelect = attrs.multiSelect || 'false';
scope.isSelected = [];
var selections = element[0].getElementsByTagName('li');
if(attrs.multiSelect === "true"){
for(var i = 0; i < selections.length; i++){
scope.isSelected[i] = false;
addClickListener(i, function(i){
if(scope.isSelected[i] === true){
// if previously it is selected (red color), now make it unselected (black color / default color)
angular.element(selections[i]).removeClass('selected');
scope.isSelected[i] = false;
} else {
// previously black color, so change it to red color
angular.element(selections[i]).addClass('selected');
scope.isSelected[i] = true;
}
});
}
} else {
var currentSelection = -1;
for(var i = 0; i < selections.length; i++){
scope.isSelected[i] = false;
addClickListener(i, function(i){
if(scope.isSelected[i] === true){
// do nothing
} else {
// previously black color, so change it to red color
angular.element(selections[i]).addClass('selected');
scope.isSelected[i] = true;
angular.element(selections[currentSelection]).removeClass('selected');
scope.isSelected[currentSelection] = false;
currentSelection = i;
}
});
}
}
}
}
});
最后,终极
玩耍!
我希望它能清除你的要求。祝你有愉快的一天:)
答案 1 :(得分:1)
我的方法(首先)根本不是制定指令,而是自定义JavaScript数据结构。我想到的简单例子:
/**
* Makes a selector data structure
* @param items elements to be listed
* @param multi whether multiple selection is supported
* @returns {{cells: *, selectedItems: selectedItems, unselectAll: unselectAll}}
*/
function makeSelector (items, multi) {
var cells = items.map(function (item) {
// each cell wraps an item and a selected flag
return {
item: item,
selected: false
};
});
// returns an array of the currently selected items
function selectedItems() {
return cells
.filter(function (cell) {
return cell.selected;
})
.map(function (cell) {
return cell.item;
});
}
// unselects all items
function unselectAll() {
cells.forEach(function (cell) {
cell.selected = false;
})
}
// adding methods to cells
cells.forEach(function (cell) {
cell.selectMe = (multi
? function () {
cell.selected = true;
}
: function () {
unselectAll();
cell.selected = true;
});
cell.unselectMe = function () {
cell.selected = false;
};
cell.toggle = function () {
if (cell.selected) {
cell.unselectMe();
} else {
cell.selectMe();
}
}
});
return {
cells: cells,
selectedItems: selectedItems,
unselectAll: unselectAll
};
}
这样您就可以轻松检索控制器中所选项目的列表:
// ...
$scope.abcSelector = makeSelector(['A','B','C'],false);
var getSelectedItems = $scope.abcSelector.selectedItems; // to do something with them in your controller
// ...
然后使用Angular数据绑定在HTML中反映这种数据结构:
<h3>List of items :</h3>
<ul>
<li ng-repeat="cell in abcSelector.cells" ng-click="cell.toggle()"
ng-class="{'active': cell.selected}">
{{cell.item}}
</li>
</ul>
<h3>List of selected items :</h3>
<ul>
<li ng-repeat="item in abcSelector.selectedItems()">
{{item}}
</li>
</ul>
如果你喜欢它会在指令中考虑到这一点,这通常会将所选项目的列表绑定到ng-model
。