<script> import ElCheckbox from 'element-ui/packages/checkbox'; import ElRadio from 'element-ui/packages/radio'; import { isEqual } from 'element-ui/src/utils/util'; const stopPropagation = e => e.stopPropagation(); export default { inject: ['panel'], components: { ElCheckbox, ElRadio }, props: { node: { required: true }, nodeId: String }, computed: { config() { return this.panel.config; }, isLeaf() { return this.node.isLeaf; }, isDisabled() { return this.node.isDisabled; }, checkedValue() { return this.panel.checkedValue; }, isChecked() { return this.node.isSameNode(this.checkedValue); }, inActivePath() { return this.isInPath(this.panel.activePath); }, inCheckedPath() { if (!this.config.checkStrictly) return false; return this.panel.checkedNodePaths .some(checkedPath => this.isInPath(checkedPath)); }, value() { return this.node.getValueByOption(); } }, methods: { handleExpand() { const { panel, node, isDisabled, config } = this; const { multiple, checkStrictly } = config; if (!checkStrictly && isDisabled || node.loading) return; if (config.lazy && !node.loaded) { panel.lazyLoad(node, () => { // do not use cached leaf value here, invoke this.isLeaf to get new value. const { isLeaf } = this; if (!isLeaf) this.handleExpand(); if (multiple) { // if leaf sync checked state, else clear checked state const checked = isLeaf ? node.checked : false; this.handleMultiCheckChange(checked); } }); } else { panel.handleExpand(node); } }, handleCheckChange() { const { panel, value, node } = this; panel.handleCheckChange(value); panel.handleExpand(node); }, handleMultiCheckChange(checked) { this.node.doCheck(checked); this.panel.calculateMultiCheckedValue(); }, isInPath(pathNodes) { const { node } = this; const selectedPathNode = pathNodes[node.level - 1] || {}; return selectedPathNode.uid === node.uid; }, renderPrefix(h) { const { isLeaf, isChecked, config } = this; const { checkStrictly, multiple } = config; if (multiple) { return this.renderCheckbox(h); } else if (checkStrictly) { return this.renderRadio(h); } else if (isLeaf && isChecked) { return this.renderCheckIcon(h); } return null; }, renderPostfix(h) { const { node, isLeaf } = this; if (node.loading) { return this.renderLoadingIcon(h); } else if (!isLeaf) { return this.renderExpandIcon(h); } return null; }, renderCheckbox(h) { const { node, config, isDisabled } = this; const events = { on: { change: this.handleMultiCheckChange }, nativeOn: {} }; if (config.checkStrictly) { // when every node is selectable, click event should not trigger expand event. events.nativeOn.click = stopPropagation; } return ( <el-checkbox value={ node.checked } indeterminate={ node.indeterminate } disabled={ isDisabled } { ...events } ></el-checkbox> ); }, renderRadio(h) { let { checkedValue, value, isDisabled } = this; // to keep same reference if value cause radio's checked state is calculated by reference comparision; if (isEqual(value, checkedValue)) { value = checkedValue; } return ( <el-radio value={ checkedValue } label={ value } disabled={ isDisabled } onChange={ this.handleCheckChange } nativeOnClick={ stopPropagation }> {/* add an empty element to avoid render label */} <span></span> </el-radio> ); }, renderCheckIcon(h) { return ( <i class="el-icon-check el-cascader-node__prefix"></i> ); }, renderLoadingIcon(h) { return ( <i class="el-icon-loading el-cascader-node__postfix"></i> ); }, renderExpandIcon(h) { return ( <i class="el-icon-arrow-right el-cascader-node__postfix"></i> ); }, renderContent(h) { const { panel, node } = this; const render = panel.renderLabelFn; const vnode = render ? render({ node, data: node.data }) : null; return ( <span class="el-cascader-node__label">{ vnode || node.label }</span> ); } }, render(h) { const { inActivePath, inCheckedPath, isChecked, isLeaf, isDisabled, config, nodeId } = this; const { expandTrigger, checkStrictly, multiple } = config; const disabled = !checkStrictly && isDisabled; const events = { on: {} }; if (expandTrigger === 'click') { events.on.click = this.handleExpand; } else { events.on.mouseenter = e => { this.handleExpand(); this.$emit('expand', e); }; events.on.focus = e => { this.handleExpand(); this.$emit('expand', e); }; } if (isLeaf && !isDisabled && !checkStrictly && !multiple) { events.on.click = this.handleCheckChange; } return ( <li role="menuitem" id={ nodeId } aria-expanded={ inActivePath } tabindex={ disabled ? null : -1 } class={{ 'el-cascader-node': true, 'is-selectable': checkStrictly, 'in-active-path': inActivePath, 'in-checked-path': inCheckedPath, 'is-active': isChecked, 'is-disabled': disabled }} {...events}> { this.renderPrefix(h) } { this.renderContent(h) } { this.renderPostfix(h) } </li> ); } }; </script>