isu-element
Version:
Polymer components for building web apps.
274 lines (248 loc) • 6.82 kB
JavaScript
import {html, PolymerElement} from "@polymer/polymer";
import {mixinBehaviors} from "@polymer/polymer/lib/legacy/class";
import {BaseBehavior} from "./behaviors/base-behavior";
import './behaviors/isu-elements-shared-styles.js';
import '@polymer/paper-checkbox';
/**
*
* `isu-checkbox-group`
*
* Example:
* ```html
* <isu-checkbox-group label="材料" value="0" items="{{items}}"></isu-checkbox-group>
*
* <script>
* items = [
* {label: '薄膜', value: 0},
* {label: '纤维', value: 1},
* {label: '塑料', value: 2},
* {label: '其它', value: 3}
* ];
* </script>
* ```
*
* ## Styling
*
* The following custom properties and mixins are available for styling:
*
* |Custom property | Description | Default|
* |----------------|-------------|----------|
* |`--isu-checkbox-group-label` | Mixin applied to the label of checkbox | {}
* |`--isu-checkbox-group-checked-color` | Mixin applied to color of the checkbox when it is checked | #0099FF
*
* @customElement
* @polymer
* @demo demo/isu-checkbox-group/index.html
*/
class IsuCheckboxGroup extends mixinBehaviors(BaseBehavior, PolymerElement) {
static get template() {
return html`
<style include="isu-elements-shared-styles">
:host {
display: flex;
flex-wrap: nowrap;
position: relative;
line-height: 34px;
font-family: var(--isu-ui-font-family), sans-serif;
font-size: var(--isu-ui-font-size);
}
#checkbox-container {
position: relative;
display: flex;
align-items: center;
flex-direction: row;
@apply --isu-checkbox-group-container;
}
:host([direction=column]) #checkbox-container {
flex-direction: column;
align-items: start;
}
:host([direction=column]) .checkbox-item {
margin-bottom: 6px;
}
.checkbox-item {
margin-left: 6px;
--paper-checkbox-checked-color: var(--isu-ui-color_skyblue);
}
:host([border]) .checkbox-item {
border: 1px solid lightgray;
padding: 7px 13px;
border-radius: 4px;
}
:host([border]) .checkbox-item[checked] {
border: 1px solid var(--isu-ui-color_skyblue);
}
</style>
<div class="isu-label">[[label]]</div>
<div id="checkbox-container">
<template is="dom-repeat" items="[[ _items ]]">
<paper-checkbox noink class="checkbox-item" checked="{{ item.checked }}" disabled="{{ item.disabled }}" on-change="__checkedChangeHandler" value="[[ getValueByKey(item, attrForValue) ]]">
[[ getValueByKey(item, attrForLabel) ]]
</paper-checkbox>
</template>
<div class="prompt-tip__container" data-prompt$="[[prompt]]">
<div class="prompt-tip">
<iron-icon class="prompt-tip-icon" icon="social:sentiment-very-dissatisfied"></iron-icon>
[[prompt]]
</div>
<div class="mask"></div>
</div>
`;
}
static get properties() {
return {
/**
* The label of the Checkbox
*
* @attribute label
* @type {string}
*/
label: {
type: String
},
/**
* Candidates of the checkbox group.
* @attribute items
* @type {array}
*/
items: {
type: Array
},
_items: {
type: Array,
computed: '__computedInnerItems(items, value)'
},
/**
* The selected value of checkbox group.
* @attribute value
* @type {string}
*/
value: {
type: String,
notify: true
},
/**
* The selected value items of checkbox group.
* @attribute value
* @type {array}
*/
selectedValues: {
type: Array,
notify: true
},
/**
* Attribute name for value.
* @type {string}
* @default 'value'
*/
attrForValue: {
type: String,
value: "value"
},
/**
* Attribute name for label.
* @type {string}
* @default 'label'
*/
attrForLabel: {
type: String,
value: "label"
},
/**
* Set to true if the selection is required.
* @type {boolean}
* @default false
*/
required: {
type: Boolean,
value: false
},
/**
* 可选项目数量的限制,最少可选
* */
min: {
type: Number
},
/**
* 可选项目数量的限制,最多可选
* */
max: {
type: Number
},
/**
* The prompt tip to show when input is invalid.
* @type {String}
*/
prompt: {
type: String
}
};
}
static get is() {
return "isu-checkbox-group";
}
static get observers() {
return [
'__valueChanged(value, items)',
'getInvalidAttribute(required, min, max, value)'
];
}
__computedInnerItems(items = [], value = "") {
const values = this.__parseValues(value);
const selectValues = value.split(',')
const _items = items.map(item =>
Object.assign({}, item, {checked: values.some(val => val === item[this.attrForValue] + '')}))
if (this.min) {
if (selectValues.length <= this.min && selectValues.length > 0) {
_items.forEach(item => {
if (!!item.checked) item.disabled = true
})
}
}
if (this.max) {
if (selectValues.length >= this.max) {
_items.forEach(item => {
if (!item.checked) item.disabled = true
})
}
}
this.set('_items', _items)
return _items;
}
__checkedChangeHandler() {
const selectValues = this._items.filter(item => !!item.checked).map(item => item[this.attrForValue]);
this.value = selectValues.length > 0 ? selectValues.join(',') : undefined;
}
/**
* @private
*/
__valueChanged(value = "", items = []) {
const values = this.__parseValues(value);
this.selectedValues = items.filter(item => values.some(val => val === item[this.attrForValue] + ''));
}
/**
* @private
*/
__parseValues(value = "") {
return value.split(',').map(val => val.trim());
}
/**
* Validate, true if the select is set to be required and this.selectedValues.length > 0, or else false.
* @returns {boolean}
*/
validate() {
super.validate()
let valid = true
if (this.required) {
valid = this.selectedValues && this.selectedValues.length > 0
}
if(this.min) {
valid = this.selectedValues && this.selectedValues.length >= this.min
}
if(this.max) {
valid = this.selectedValues && this.selectedValues.length <= this.max
}
return valid
}
}
window.customElements.define(IsuCheckboxGroup.is, IsuCheckboxGroup);