Last active
May 29, 2017 23:26
-
-
Save aaronanderson/f9fb81bad790725c4b3c691921ad1f08 to your computer and use it in GitHub Desktop.
A Polymer 2.0 multiselection list component consisting of two adjacent lists, one with available items (source) and one with selected items (target).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link rel="import" href="../polymer/polymer-element.html"> | |
<link rel="import" href="../iron-flex-layout/iron-flex-layout-classes.html"> | |
<link rel="import" href="../paper-listbox/paper-listbox.html"> | |
<link rel="import" href="../paper-item/paper-item.html"> | |
<link rel="import" href="../paper-button/paper-button.html" /> | |
<link rel="import" href="../paper-input/paper-input.html"> | |
<dom-module id="intworkspace-multi-listbox"> | |
<template> | |
<style include="iron-flex iron-flex-alignment"> | |
.container { | |
background-color: #ccc; | |
margin: 10px; | |
} | |
paper-button { | |
margin: 5px; | |
} | |
paper-input { | |
} | |
paper-listbox { | |
background-color: white; | |
width: var(--multi-listbox-width, 200px); | |
height: var(--multi-listbox-height, 300px); | |
overflow: auto; | |
} | |
</style> | |
<slot id="labelView"><template preserve-content><paper-item value="[[item]]" item-id="[[item.id]]">[[item.name]]</paper-item></template></slot> | |
</template> | |
<template id="listView"> | |
<div class="layout horizontal container fullbleed"> | |
<div class="layout vertical container"> | |
<paper-input value="{{sourceFilter}}" label="Filter" floatingLabel id="sourceFilter"></paper-input> | |
<paper-listbox id="sourceItems" attr-for-selected="item-id" multi selected-items="{{selectedSourceItems}}"> | |
<template is="dom-repeat" items="[[sourceItems]]" as="item" filter="{{filter(sourceFilter)}}" sort="{{sort}}"> | |
</template> | |
</paper-listbox> | |
</div> | |
<div class="layout vertical container"> | |
<div class="flex"></div> | |
<paper-button id="add" raised on-click="add">></paper-button> | |
<paper-button id="addAll" raised on-click="addAll">>></paper-button> | |
<paper-button id="remove" raised on-click="remove"><</paper-button> | |
<paper-button id="removeAll" raised on-click="removeAll"><<</paper-button> | |
<div class="flex"></div> | |
</div> | |
<div class="layout vertical container"> | |
<paper-input value="{{targetFilter}}" label="Filter" floatingLabel id="targetFilter"></paper-input> | |
<paper-listbox id="targetItems" attr-for-selected="item-id" multi selected-items="{{selectedTargetItems}}"> | |
<template is="dom-repeat" items="[[targetItems]]" as="item" filter="{{filter(targetFilter)}}" sort="{{sort}}"> | |
</template> | |
</paper-listbox> | |
</div> | |
</div> | |
</template> | |
<script> | |
class IntMultiListBox extends Polymer.Element { | |
static get is() { | |
return 'intworkspace-multi-listbox'; | |
} | |
static get properties() { | |
return { | |
sourceItems: { | |
notify: true, | |
type: Array, | |
value: [] | |
}, | |
selectedSourceItems: { | |
notify: true, | |
type: Array, | |
value: [] | |
}, | |
targetItems: { | |
notify: true, | |
type: Array, | |
value: [] | |
}, | |
selectedTargetItems: { | |
notify: true, | |
type: Array, | |
value: [] | |
}, | |
sourceFilter: { | |
type: String, | |
}, | |
targetFilter: { | |
type: String, | |
}, | |
filter: { | |
type: Object, | |
value: function(){ | |
return IntMultiListBox.defaultFilter; | |
} | |
}, | |
sort: { | |
type: Object, | |
value: function(){ | |
return IntMultiListBox.defaultSort; | |
} | |
}, | |
} | |
} | |
static get observers() { | |
return [ | |
'sourceItemsChanged(sourceItems.*)', | |
'targetItemsChanged(targetItems.*)', | |
'selectedSourceItemsChanged(selectedSourceItems.*)', | |
'selectedTargetItemsChanged(selectedTargetItems.*)', | |
] | |
} | |
ready(){ | |
super.ready(); | |
let labelTemplate = this.$.labelView.assignedNodes().find((e) => { | |
return e instanceof HTMLTemplateElement; | |
}); | |
labelTemplate = labelTemplate ? labelTemplate : this.$.labelView.children[0]; | |
let listTemplate = document.importNode(Polymer.DomModule.import(IntMultiListBox.is, "#listView"), true); | |
let repeatTemplate = listTemplate.content.querySelector("#sourceItems > template[is='dom-repeat']"); | |
repeatTemplate.content.appendChild(document.importNode(labelTemplate.content, true)); | |
repeatTemplate = listTemplate.content.querySelector("#targetItems > template[is='dom-repeat']"); | |
repeatTemplate.content.appendChild(document.importNode(labelTemplate.content, true)); | |
this.listInstance = this._stampTemplate(listTemplate); | |
this.shadowRoot.appendChild(this.listInstance); | |
} | |
sourceItemsChanged(sourceItems) { | |
//console.log("sourceItems changed", sourceItems); | |
if (this.listInstance) { | |
if (sourceItems.base.length > 0) { | |
this.listInstance.$.addAll.disabled = false; | |
} else { | |
this.listInstance.$.addAll.disabled = true; | |
} | |
} | |
} | |
targetItemsChanged(targetItems) { | |
//console.log("targetItems changed", targetItems); | |
if (this.listInstance) { | |
if (targetItems.base.length > 0) { | |
this.listInstance.$.removeAll.disabled = false; | |
} else { | |
this.listInstance.$.removeAll.disabled = true; | |
} | |
} | |
} | |
selectedSourceItemsChanged(sourceItems) { | |
//console.log("selected sourceItems changed", sourceItems); | |
if (this.listInstance) { | |
if (sourceItems.base.length > 0) { | |
this.listInstance.$.add.disabled = false; | |
} else { | |
this.listInstance.$.add.disabled = true; | |
} | |
} | |
} | |
selectedTargetItemsChanged(targetItems) { | |
//console.log("selected targetItems changed", targetItems); | |
if (this.listInstance) { | |
if (targetItems.base.length > 0) { | |
this.listInstance.$.remove.disabled = false; | |
} else { | |
this.listInstance.$.remove.disabled = true; | |
} | |
} | |
} | |
add() { | |
this.moveItems(Array.from(this.selectedSourceItems), 'sourceItems', 'targetItems'); | |
this.listInstance.$.sourceItems.selectedValues = []; | |
} | |
addAll() { | |
this.moveItems(Array.from(this.sourceItems).filter(this.filter(this.sourceFilter)), 'sourceItems', 'targetItems'); | |
} | |
remove() { | |
this.moveItems(Array.from(this.selectedTargetItems), 'targetItems', 'sourceItems'); | |
this.listInstance.$.targetItems.selectedValues = []; | |
} | |
removeAll() { | |
this.moveItems(Array.from(this.targetItems).filter(this.filter(this.targetFilter)), 'targetItems', 'sourceItems'); | |
} | |
moveItems(selectedItems, source, target) { | |
selectedItems.forEach((item) => { | |
if (item instanceof Polymer.Element) { | |
item = item.value; | |
} | |
var index = this[source].indexOf(item); | |
if (index != -1) { | |
var item = this.splice(source, index, 1); | |
this.push(target, item[0]); | |
} | |
}); | |
} | |
static defaultFilter(key) { | |
return function(item) { | |
if (!item) return false; | |
if (key != null || key != undefined) { | |
return (item.name && ~item.name.toLowerCase().indexOf(key.toLowerCase())); | |
//|| (item.id && ~item.id.toLowerCase().indexOf(key.toLowerCase())); | |
} else | |
return true; | |
}; | |
} | |
static defaultSort(item1,item2){ | |
if (item1 && item2){ | |
if (item1.name && item2.name){ | |
if (item1.name < item2.name){ | |
return -1; | |
} | |
if (item1.name > item2.name){ | |
return 1; | |
} | |
return 0; | |
} | |
} | |
return -1; | |
} | |
} | |
window.customElements.define(IntMultiListBox.is, IntMultiListBox); | |
</script> | |
</dom-module> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link rel="import" href="../polymer/polymer-element.html"> | |
<link rel="import" href="intworkspace-multi-listbox.html"> | |
<dom-module id="multlist-test"> | |
<template> | |
<style> | |
:host { | |
display: block; | |
} | |
</style> | |
<intworkspace-multi-listbox id="listbox" target-items="{{targetItems}}"> | |
<template preserve-content><paper-item value="[[item]]" item-id="[[item.id]]">Override [[item.name]]</paper-item></template> | |
</intworkspace-multi-listbox> | |
</template> | |
<script> | |
/** | |
* `multlist-test` | |
* | |
* | |
* @customElement | |
* @polymer | |
* @demo demo/index.html | |
*/ | |
class MultlistTest extends Polymer.Element { | |
static get is() { return 'multlist-test'; } | |
static get properties() { | |
return { | |
targetItems: { | |
type: Array, | |
value: [], | |
} | |
} | |
} | |
static get observers() { | |
return [ | |
'targetItemsChanged(targetItems.*)', | |
] | |
} | |
ready(){ | |
super.ready(); | |
this.$.listbox.set('sourceItems',[{id: 1, name: "test 1"},{id: 2, name: "test 2"}]); | |
} | |
targetItemsChanged(change){ | |
console.log("targetItemsChanged", change, this.targetItems); | |
} | |
} | |
window.customElements.define(MultlistTest.is, MultlistTest); | |
</script> | |
</dom-module> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment