UNPKG

nly-adminlte-vue

Version:
491 lines (481 loc) 15.6 kB
import Vue from "../../utils/vue"; import { NlySearchSelectItem } from "./plugin/search-select-item"; import { NlySearchSelectMultipleContainer } from "./plugin/search-select-multiple-container"; import { NlySearchSelectSingleContainer } from "./plugin/search-select-single-container"; import { NlySearchSelectDropdownContainer } from "./plugin/search-select-dropdown-container"; import idMixin from "../../mixins/id"; import { from as arrayFrom, isArray } from "../../utils/array"; import optionsMixin from "./plugin/mixin-search-select-options"; import { Portal, Wormhole } from "portal-vue"; import { NlySearchSelectPortal } from "./plugin/search-select-portal"; // import { props } from "./plugin/select-option"; import { warn } from "../../utils/warn"; // const VALUE_NOT_IN_OPTIONS = // "The Value in v-model is not in options, it is not render"; const name = "NlySearchSelect"; export const NlySearchSelect = Vue.extend({ name: name, mixins: [idMixin, optionsMixin], model: { prop: "value", event: "input" }, props: { /** select的prop */ // 隐藏的select 的 id // id: { // type: String, // default: null // }, // 隐藏的select 的 option,即需要渲染到下拉框中的数据 options: { type: [Array, Object], default: () => [] }, // 隐藏的select 的 value, 即 渲染为下拉框中元素的 value valueField: { type: String, default: "value" }, // 隐藏的select 的 text, 即 渲染为下拉框中元素的 文本 textField: { type: String, default: "text" }, // 隐藏的select 的 分组标签 的名称 labelField: { type: String, default: "label" }, // 隐藏的select 的分组下默的 option 字段名称 optionsField: { type: String, default: "options" }, // 颜色 variant: { type: String, default: null }, // 多选 multiple: { type: Boolean, default: false }, /** select-container的 pops */ placeholder: { type: String, default: "Choice a field" }, // inputFunction: { // type: Function // }, // 获取所选择的值 value: { // type: [Array, Object], // default: () => [] }, // disabled: { type: Boolean, default: false } }, data() { return { // 选中的值, 用来传给 item 的 checkedValue: [], inputValue: null, open: false, focus: false, below: null, portalName: `nly-search-select-${this._uid}`, dropdownWidth: null, dropdownLeft: null, dropdownTop: null }; }, beforeDestroy() { this.clearPortalTarget(); }, methods: { clearPortalTarget() { if (Wormhole.hasTarget(this.portalName)) { document.body.removeChild( document.body.querySelector(`#${this.portalName}-id`) ); } }, showDropDown() { this.dropdownWidth = this.$refs[ this.customProps.ref ].getBoundingClientRect().width; this.dropdownLeft = this.$refs[ this.customProps.ref ].getBoundingClientRect().left; this.dropdownTop = this.getOffsetTop(this.$refs[this.customProps.ref]); if (!Wormhole.hasTarget(this.portalName)) { const div = document.createElement("div"); document.body.appendChild(div); const searchSelectPortal = new NlySearchSelectPortal({ parent: this.$root, propsData: { name: this.portalName, id: `${this.portalName}-id` } }); searchSelectPortal.$mount(div); } else { warn( `A "<portal-target>" with name "${this.portalName}" already exists in the document.`, "NlySearchSelectPortal" ); } }, getCheckValueValueFieldValue() {}, inputFunction(evt) { this.inputValue = evt; }, click_other(e) { // console.log(e.target); // this.$nextTick(() => { // console.log(this.$refs[`${this.safeId()}-input`]); // }); if (!this.multiple) if (!this.$el.contains(e.target)) { this.open = false; this.focus = false; } }, addCheckedValue(evt) { if (this.multiple) { const newValue = []; const addCheckedValue = arrayFrom(this.checkedValue).map( o => o[this.valueField] ); if (addCheckedValue.indexOf(evt[this.valueField]) === -1) { this.checkedValue.push(evt); } else { this.checkedValue.splice( addCheckedValue.indexOf(evt[this.valueField]), 1 ); } this.checkedValue.forEach(item => { if (item[this.valueField] !== null) { newValue.push(item[this.valueField]); } }); this.open = false; this.$emit("input", newValue); } else { const newValue = []; const addCheckedValue = arrayFrom(this.checkedValue).map( o => o[this.valueField] ); if (addCheckedValue.indexOf(evt[this.valueField]) === -1) { this.checkedValue = [evt]; } else if (evt[this.valueField] === null) { this.checkedValue = [evt]; } else { this.checkedValue = null; } if (this.checkedValue) { this.checkedValue.forEach(item => { newValue.push(item[this.valueField]); }); } this.open = false; if (this.checkedValue) { this.$emit("input", newValue[0]); } else { this.$emit("input", null); } } }, removeCheckedValue(newValue) { const newVal = []; newValue.forEach(item => { if (item[this.valueField] !== null) { newVal.push(item[this.valueField]); } }); this.$emit("input", newVal); }, getCheckValue() { if (this.multiple) { if (isArray(this.customProps.value)) { const selectedValArray = []; this.customProps.value.forEach(element => { arrayFrom(this.options).forEach(item => { if (Object.keys(item).indexOf(this.valueField) !== -1) { if ( JSON.stringify(item[this.valueField]) === JSON.stringify(element) ) { selectedValArray.push(item); } } else if (Object.keys(item).indexOf(this.optionsField) !== -1) { item[this.optionsField].forEach(children => { if (Object.keys(children).indexOf(this.valueField) !== -1) { if ( JSON.stringify(children[this.valueField]) === JSON.stringify(element) ) { selectedValArray.push(children); } } }); } }); }); return selectedValArray; } else { const selectedValArray = []; arrayFrom(this.options).forEach(item => { if (Object.keys(item).indexOf(this.valueField) !== -1) { if ( JSON.stringify(item[this.valueField]) === JSON.stringify(this.customProps.value) ) { selectedValArray.push(item); } } else if (Object.keys(item).indexOf(this.optionsField) !== -1) { item[this.optionsField].forEach(children => { if (Object.keys(children).indexOf(this.valueField) !== -1) { if ( JSON.stringify(children[this.valueField]) === JSON.stringify(this.customProps.value) ) { selectedValArray.push(children); } } }); } }); return selectedValArray; } } else { if (isArray(this.customProps.value)) { const selectedValArray = []; const element = this.customProps.value[0]; arrayFrom(this.options).forEach(item => { if (Object.keys(item).indexOf(this.valueField) !== -1) { if ( JSON.stringify(item[this.valueField]) === JSON.stringify(element) ) { selectedValArray.push(item); } } else if (Object.keys(item).indexOf(this.optionsField) !== -1) { item[this.optionsField].forEach(children => { if (Object.keys(children).indexOf(this.valueField) !== -1) { if ( JSON.stringify(children[this.valueField]) === JSON.stringify(element) ) { selectedValArray.push(children); } } }); } }); return [selectedValArray[0]]; } else { const selectedValArray = []; arrayFrom(this.options).forEach(item => { if (Object.keys(item).indexOf(this.valueField) !== -1) { if ( JSON.stringify(item[this.valueField]) === JSON.stringify(this.customProps.value) ) { selectedValArray.push(item); } } else if (Object.keys(item).indexOf(this.optionsField) !== -1) { item[this.optionsField].forEach(children => { if (Object.keys(children).indexOf(this.valueField) !== -1) { if ( JSON.stringify(children[this.valueField]) === JSON.stringify(this.customProps.value) ) { selectedValArray.push(children); } } }); } }); return [selectedValArray[0]]; } } }, getOffsetTop: function(obj) { let top = obj.getBoundingClientRect().height; while (obj.offsetParent) { //如果obj的有最近的父级定位元素就继续 top += obj.offsetTop; obj = obj.offsetParent; //更新obj,继续判断新的obj是否还有父级定位,然后继续累加 } return top; //返回json格式 } }, created() {}, mounted() { this.checkedValue = this.getCheckValue(); }, computed: { customProps() { return { focus: this.focus, below: this.below, ower: this.id, placeholder: this.placeholder, inputFunction: this.inputFunction, valueField: this.valueField, textField: this.textField, options: this.options, value: this.value, id: this.safeId(), ref: this.selectRef ? this.selectRef : `${this.portalName}-ref`, variant: this.variant }; } }, watch: { open(newVal) { if (newVal === true) { document.addEventListener("click", this.click_other, true); } else { document.removeEventListener("click", this.click_other, true); } }, value: { //监听的对象 deep: true, //深度监听设置为 true handler: function() { this.checkedValue = this.getCheckValue(); } } }, render(h) { var thatselect = this; const $searchSelectItemVnodes = h(NlySearchSelectItem, { props: { id: thatselect.id, // 隐藏的select 的 option,即需要渲染到下拉框中的数据 options: thatselect.options, // 隐藏的select 的 value, 即 渲染为下拉框中元素的 value valueField: thatselect.valueField, // 隐藏的select 的 text, 即 渲染为下拉框中元素的 文本 textField: thatselect.textField, // 隐藏的select 的 分组标签 的名称 labelField: thatselect.labelField, // 隐藏的select 的分组下默的 option 字段名称 optionsField: thatselect.optionsField } }); const $multipleVnodes = h(NlySearchSelectMultipleContainer, { props: { open: thatselect.open, focus: thatselect.focus, below: thatselect.below, ower: thatselect.safeId(), value: thatselect.checkedValue, placeholder: thatselect.placeholder, inputFunction: thatselect.inputFunction, valueField: thatselect.valueField, textField: thatselect.textField, removeCheckedValue: thatselect.removeCheckedValue }, on: { click: () => { if (thatselect.open) { thatselect.open = false; } else { thatselect.open = true; thatselect.showDropDown(); } thatselect.focus = true; } } }); const $singleVnodes = h(NlySearchSelectSingleContainer, { props: { open: thatselect.open, focus: thatselect.focus, below: thatselect.below, ower: thatselect.safeId(), value: thatselect.checkedValue, placeholder: thatselect.placeholder, disabled: thatselect.disabled }, on: { click: () => { if (thatselect.open) { thatselect.open = false; } else { thatselect.open = true; thatselect.showDropDown(); } thatselect.focus = true; } } }); const $dropdownVnodes = h( Portal, { props: { to: thatselect.portalName, // slim: true, name: thatselect.portalName } }, [ h(NlySearchSelectDropdownContainer, { props: { open: thatselect.open, below: thatselect.below, id: thatselect.safeId(), variant: thatselect.customProps.variant, valueField: thatselect.valueField, textField: thatselect.textField, labelField: thatselect.labelField, optionsField: thatselect.optionsField, options: thatselect.formOptions, multiple: thatselect.multiple, addCheckedValue: thatselect.addCheckedValue, width: `${thatselect.dropdownWidth}px`, left: `${thatselect.dropdownLeft}px`, top: `${thatselect.dropdownTop}px`, inputFunction: thatselect.inputFunction } }) ] ); if (thatselect.multiple) { return h( "div", { staticClass: thatselect.customProps.variant ? `select2-${thatselect.variant}` : null, attrs: { id: thatselect.customProps.id }, ref: thatselect.customProps.ref }, [$searchSelectItemVnodes, $multipleVnodes, $dropdownVnodes] ); } else { return h( "div", { attrs: { id: thatselect.customProps.id }, ref: thatselect.customProps.ref }, [$searchSelectItemVnodes, $singleVnodes, $dropdownVnodes] ); } } });