autocomplete con seleccion multiple

This commit is contained in:
Dani Herrero 2017-09-20 13:52:53 +02:00
parent d81d36217a
commit 1dad2147ca
7 changed files with 91 additions and 15 deletions

View File

@ -30,7 +30,7 @@
select-fields="surname" select-fields="surname"
label="Salesperson"> label="Salesperson">
<tpl-item> <tpl-item>
{{::$parent.$parent.item.name}} {{::$parent.$parent.item.surname}} {{$parent.$parent.item.name}} {{$parent.$parent.item.surname}}
</tpl-item> </tpl-item>
</vn-autocomplete> </vn-autocomplete>
<vn-autocomplete vn-one <vn-autocomplete vn-one

View File

@ -4,10 +4,11 @@
items="$ctrl.items" items="$ctrl.items"
show="$ctrl.showDropDown" show="$ctrl.showDropDown"
selected="$ctrl.field" selected="$ctrl.field"
search="$ctrl.displayValue" filter="true"
load-more="$ctrl.getItems()" load-more="$ctrl.getItems()"
show-load-more="$ctrl.maxRow" show-load-more="$ctrl.maxRow"
filter-action="$ctrl.findItems(search)" filter-action="$ctrl.findItems(search)"
item-width="$ctrl.width" item-width="$ctrl.width"
multiple="$ctrl.multiple"
><vn-item ng-transclude="tplItem">{{$parent.item.name}}</vn-item></vn-drop-down> ><vn-item ng-transclude="tplItem">{{$parent.item.name}}</vn-item></vn-drop-down>
</vn-vertical> </vn-vertical>

View File

@ -20,6 +20,8 @@ class Autocomplete extends Component {
this.showField = this.showField || 'name'; this.showField = this.showField || 'name';
this.valueField = this.valueField || 'id'; this.valueField = this.valueField || 'id';
this.items = this.data || []; this.items = this.data || [];
this.displayValueMultiCheck = [];
this._multiField = [];
} }
get showDropDown() { get showDropDown() {
@ -38,26 +40,50 @@ class Autocomplete extends Component {
} }
set displayValue(value) { set displayValue(value) {
this._value = (value === undefined || value === '') ? null : value; let val = (value === undefined || value === '') ? null : value;
if (this.multiple && val) {
let index = this.displayValueMultiCheck.indexOf(val);
if (index === -1)
this.displayValueMultiCheck.push(val);
else
this.displayValueMultiCheck.splice(index, 1);
this._value = this.displayValueMultiCheck.join(', ');
} else {
this._value = val;
}
if (value === null) { if (value === null) {
this.field = null; this.field = null;
if (this.multiple && this.items.length) {
this.displayValueMultiCheck = [];
this.items.map(item => {
item.checked = false;
return item;
});
}
} }
} }
get field() { get field() {
return this._field; return this.multiple ? this._multiField : this._field;
} }
set field(value) { set field(value) {
this.finding = true; this.finding = true;
if (value && value.hasOwnProperty(this.valueField)) if (value && value.hasOwnProperty(this.valueField)) {
this._field = value[this.valueField]; this._field = value[this.valueField];
else this.setMultiField(value[this.valueField]);
} else {
this.setValue(value); this.setValue(value);
}
if (value && value.hasOwnProperty(this.showField)) if (value && value.hasOwnProperty(this.showField))
this.displayValue = value[this.showField]; this.displayValue = value[this.showField];
this.finding = false; this.finding = false;
if (this.onChange)
this.onChange({item: this._field});
} }
set initialData(value) { set initialData(value) {
@ -66,6 +92,22 @@ class Autocomplete extends Component {
} }
} }
setMultiField(val) {
if (val && typeof val === 'object' && val[this.valueField]) {
val = val[this.valueField];
}
if (val === null) {
this._multiField = [];
} else {
let index = this._multiField.indexOf(val);
if (index === -1) {
this._multiField.push(val);
} else {
this._multiField.splice(index, 1);
}
}
}
setValue(value) { setValue(value) {
if (value) { if (value) {
let data = this.items; let data = this.items;
@ -80,6 +122,7 @@ class Autocomplete extends Component {
this.requestItem(value); this.requestItem(value);
} else { } else {
this._field = null; this._field = null;
this.setMultiField(null);
this.displayValue = ''; this.displayValue = '';
} }
} }
@ -112,6 +155,7 @@ class Autocomplete extends Component {
showItem(item) { showItem(item) {
this.displayValue = item ? item[this.showField] : ''; this.displayValue = item ? item[this.showField] : '';
this.field = item; this.field = item;
this.setMultiField(item);
} }
getRequestFields() { getRequestFields() {
@ -137,7 +181,15 @@ class Autocomplete extends Component {
this.finding = true; this.finding = true;
this.$http.get(`${this.url}?filter=${json}`).then( this.$http.get(`${this.url}?filter=${json}`).then(
json => { json => {
this.items = json.data; this.items = [];
json.data.forEach(
el => {
if (this.multiple) {
el.checked = this.field.indexOf(el[this.valueField]) !== -1;
}
this.items.push(el);
}
);
this.finding = false; this.finding = false;
}, },
() => { () => {
@ -168,6 +220,9 @@ class Autocomplete extends Component {
if (json.data.length) if (json.data.length)
json.data.forEach( json.data.forEach(
el => { el => {
if (this.multiple) {
el.checked = this.field.indexOf(el[this.valueField]) !== -1;
}
this.items.push(el); this.items.push(el);
} }
); );
@ -209,7 +264,6 @@ class Autocomplete extends Component {
let rectangle = this.$element[0].getBoundingClientRect(); let rectangle = this.$element[0].getBoundingClientRect();
this.width = Math.round(rectangle.width) - 10; this.width = Math.round(rectangle.width) - 10;
} }
$onDestroy() { $onDestroy() {
@ -237,7 +291,8 @@ module.component('vnAutocomplete', {
itemAs: '@?', itemAs: '@?',
field: '=', field: '=',
label: '@', label: '@',
itemTemplate: '@?' itemTemplate: '@?',
multiple: '@?'
}, },
transclude: { transclude: {
tplItem: '?tplItem' tplItem: '?tplItem'

View File

@ -37,4 +37,7 @@ vn-autocomplete {
vn-drop-down{ vn-drop-down{
margin-top: 47px; margin-top: 47px;
} }
vn-drop-down .dropdown-body .filter vn-icon {
margin-left: -26px;
}
} }

View File

@ -1,4 +1,4 @@
<vn-vertical class="dropdown-body" ng-show="$ctrl.show && $ctrl.itemsFiltered.length > 1"> <vn-vertical class="dropdown-body" ng-show="$ctrl.show">
<vn-one ng-show="$ctrl.filter" class="filter"> <vn-one ng-show="$ctrl.filter" class="filter">
<vn-horizontal> <vn-horizontal>
<input vn-one placeholder="{{'Search' | translate}}" type="text" ng-model="$ctrl.search"/> <input vn-one placeholder="{{'Search' | translate}}" type="text" ng-model="$ctrl.search"/>
@ -7,13 +7,14 @@
</vn-one> </vn-one>
<vn-one> <vn-one>
<ul class="dropdown"> <ul class="dropdown">
<li <li tabIndex="-1"
ng-repeat="item in $ctrl.itemsFiltered track by $index" ng-repeat="item in $ctrl.itemsFiltered track by $index"
ng-click="$ctrl.selected = item; $ctrl.show = false" ng-click="$ctrl.selectItem(item)"
ng-class="{'active': $index === $ctrl.activeOption}" ng-class="{'active': $index === $ctrl.activeOption, 'checked': item.checked}"
ng-mouseover="$ctrl.activeOption = $index" ng-mouseover="$ctrl.activeOption = $index"
> >
<div ng-transclude="vnItem">{{::item.name}}</div> <input type="checkbox" ng-checked="item.checked" ng-if="$ctrl.multiple">
<div ng-transclude="vnItem">{{item.name}}</div>
</li> </li>
<li ng-if="$ctrl.showLoadMore" class="dropdown__loadMore" tabIndex="-1" ng-class="{'active': $ctrl.itemsFiltered.length === $ctrl.activeOption}" ng-click="$ctrl.loadMore();$ctrl.show = true;" translate="Load More"></li> <li ng-if="$ctrl.showLoadMore" class="dropdown__loadMore" tabIndex="-1" ng-class="{'active': $ctrl.itemsFiltered.length === $ctrl.activeOption}" ng-click="$ctrl.loadMore();$ctrl.show = true;" translate="Load More"></li>
</ul> </ul>

View File

@ -110,6 +110,16 @@ export default class DropDown {
} }
} }
selectItem(item) {
this.selected = item;
if (this.multiple) {
item.checked = !item.checked;
this.show = true;
} else {
this.show = false;
}
}
$onInit() { $onInit() {
if (this.parent) if (this.parent)
this.parent.addEventListener('keydown', e => this.onKeydown(e)); this.parent.addEventListener('keydown', e => this.onKeydown(e));
@ -135,7 +145,8 @@ module.component('vnDropDown', {
showLoadMore: '=?', showLoadMore: '=?',
top: '<?', top: '<?',
itemWidth: '<?', itemWidth: '<?',
parent: '<?' parent: '<?',
multiple: '<?'
}, },
transclude: { transclude: {
vnItem: '?vnItem' vnItem: '?vnItem'

View File

@ -30,6 +30,7 @@ vn-drop-down {
max-height: 400px; max-height: 400px;
overflow-y: auto; overflow-y: auto;
li { li {
outline: none;
list-style-type: none; list-style-type: none;
padding: 5px 10px; padding: 5px 10px;
cursor: pointer; cursor: pointer;
@ -38,6 +39,10 @@ vn-drop-down {
color: rgb(255,171,64); color: rgb(255,171,64);
font-weight: 700; font-weight: 700;
} }
input[type=checkbox]{
float: left;
margin: 5px 5px 0 0;
}
} }
li.active{ li.active{
background-color: #3D3A3B; background-color: #3D3A3B;