@@ -1,176 +1,191 @@
< script lang = "ts" >
export default {
name : "LaySelect" ,
} ;
< / script >
< script setup lang = "ts" >
import "./index.less" ;
import {
provide ,
computed ,
ref ,
Ref ,
useSlots ,
onMounted ,
VNode ,
Component ,
watch ,
} from "vue" ;
import LayInput from "../input/index.vue" ;
import LayTagInput from "../tagInput/index.vue" ;
import LayDropdown from "../dropdown/index.vue" ;
import LaySelectOption , {
LaySelectOptionProps ,
} from "../selectOption/index.vue" ;
export interface LaySelectProps {
name ? : string ;
create ? : boolean ;
disabled ? : boolean ;
placeholder ? : string ;
modelValue ? : any ;
multipl e? : boolean ;
items ? : LaySelectOptionProps [ ] ;
siz e? : "lg" | "md" | "sm" | "xs" ;
allowClear ? : boolean ;
}
export interface SelectEmits {
( e : "update:modelValue" , value : string ) : void ;
( e : "change" , value : string ) : void ;
}
const props = withDefaults ( defineProps < LaySelectProps > ( ) , {
modelValue : null ,
placeholder : "请选择" ,
disabled : false ,
multiple : false ,
create : false ,
size : "md" ,
allowClear : false ,
} ) ;
const slots = useSlots ( ) ;
const searchValue = ref ( "" ) ;
const singleValue = ref ( "" ) ;
const multipleValue = ref ( [ ] ) ;
const openState : Ref < boolean > = ref ( false ) ;
const selectedItem : Ref < any > = ref ( [ ] ) ;
const options = ref < any > ( [ ] ) ;
const emits = defineEmits < SelectEmits > ( ) ;
onMounted ( ( ) => {
if ( slots . default ) {
getOption ( slots . default ( ) ) ;
export default {
name : "LaySelect" ,
} ;
< / script >
< script setup lang = "ts" >
import "./index.less" ;
import {
provide ,
computed ,
ref ,
Ref ,
useSlots ,
onMounted ,
VNode ,
Component ,
watch ,
} from "vue" ;
import LayInput from "../input/index.vue" ;
import LayTagInput from "../tagInput/index.vue" ;
import LayDropdown from "../dropdown/index.vue" ;
import LaySelectOption , {
LaySelectOptionProps ,
} from "../selectOption/index.vue" ;
export interface LaySelectProps {
name ? : string ;
create ? : boolean ;
disabled ? : boolean ;
placeholder ? : string ;
showEmpty ? : boole an;
emptyMessag e? : string ;
modelValue ? : any ;
multipl e? : boolean ;
items ? : LaySelectOptionProps [ ] ;
size ? : "lg" | "md" | "sm" | "xs" ;
collapseTagsTooltip ? : boolean ;
minCollapsedNum ? : number ;
allowClear ? : boolean ;
}
Object . assign ( options . value , props . items ) ;
watch (
selectedValue ,
( ) => {
if ( multiple . value ) {
multipleValue . value = selectedValue . value . map ( ( value : any ) => {
return options . value . find ( ( item : any ) => item . value === value )
} )
} else {
singleValue . value = options . value . find ( ( item : any ) => {
return item . value === selectedValue . value ;
} ) ? . label ;
}
} ,
{ immediate : true }
) ;
} ) ;
const getOption = function ( nodes : VNode [ ] ) {
nodes ? . map ( ( item : VNode ) => {
let component = item . type as Component ;
if ( component . name === LaySelectOption . name ) {
options . value . push ( item . props ) ;
} else {
getOption ( item . children as VNode [ ] ) ;
}
export interface SelectEmits {
( e : "update:modelValue" , value : string ) : void ;
( e : "change" , value : string ) : void ;
}
const props = withDefaults ( defineProps < LaySelectProps > ( ) , {
modelValue : null ,
placeholder : "请选择" ,
showEmpty : true ,
emptyMessage : "请选择" ,
collapseTagsTooltip : true ,
minCollapsedNum : 3 ,
disabled : false ,
multiple : false ,
create : false ,
size : "md" ,
allowClear : false ,
} ) ;
} ;
const selected Value = computed ( {
get ( ) {
return props . modelValue ;
} ,
set ( val ) {
emits ( "update:modelValue" , val ) ;
emits ( "change" , val ) ;
} ,
} ) ;
const multiple = computed ( ( ) => {
return props . multiple ;
} ) ;
provide ( "openState" , openState ) ;
provide ( "selectedItem" , selectedItem ) ;
provide ( "selectedValue" , selectedValue ) ;
provide ( "searchValue" , searchValue ) ;
provide ( " multiple" , multipl e) ;
< / script >
< templa te>
< div class = "layui-select" >
< lay-dropdown
:disabled = "disabled"
:update-at-scroll = "true"
@show ="openState = true"
@hide ="openState = false"
>
< lay-tag-input
v-if = "multiple"
v-model = "multipleValue"
:allow-clear = "allowClear"
:disabledInput = "true"
const slots = useSlots ( ) ;
const search Value = ref ( "" ) ;
const singleValue = ref ( "" ) ;
const multipleValue = ref ( [ ] ) ;
const openState : Ref < boolean > = ref ( false ) ;
const selectedItem : Ref < any > = ref ( [ ] ) ;
const options = ref < any > ( [ ] ) ;
const emits = defineEmits < SelectEmits > ( ) ;
onMounted ( ( ) => {
if ( slots . default ) {
getOption ( slots . default ( ) ) ;
}
Object . assign ( options . value , props . items ) ;
watch (
selectedValue ,
( ) => {
if ( multiple. valu e) {
multipleValue . value = selectedValue . value . map ( ( value : any ) => {
return options . value . find ( ( item : any ) => {
item . disabled == "" || item . disabled == true ? item . closable = false : i tem . closable = true ;
return item . value === value ;
} ) ;
} ) ;
} else {
singleValue . value = options . value . find ( ( item : any ) => {
return item . value === selectedValue . value ;
} ) ? . label ;
}
} ,
{ immediate : true }
) ;
} ) ;
const getOption = function ( nodes : VNode [ ] ) {
nodes ? . map ( ( item : VNode ) => {
let component = item . type as Component ;
if ( component . name === LaySelectOption . name ) {
options . value . push ( item . props ) ;
} else {
getOption ( item . children as VNode [ ] ) ;
}
} ) ;
} ;
const selectedValue = computed ( {
get ( ) {
return props . modelValue ;
} ,
set ( val ) {
emits ( "update:modelValue" , val ) ;
emits ( "change" , val ) ;
} ,
} ) ;
const multiple = computed ( ( ) => {
return props . multiple ;
} ) ;
provide ( "openState" , openState ) ;
provide ( "selectedItem" , selectedItem ) ;
provide ( "selectedValue" , selectedValue ) ;
provide ( "searchValue" , searchValue ) ;
provide ( "multiple" , multiple ) ;
< / script >
< template >
< div class = "layui-select" >
< lay-dropdown
:disabled = "disabled"
:update-at-scroll = "true"
@show ="openState = true"
@hide ="openState = false"
>
< template # suffix >
< lay-icon
type = "layui-icon-triangle-d "
: class = "{ triangle: openState } "
> < / lay-icon >
< / template >
< / lay-tag-input >
< lay-input
v-else
v-model = "singleValue"
:placeholder = "p laceholder "
:allow-clear = "allowClear "
:readonly = "true"
>
< template # suffix >
< lay-icon
type = "layui-icon-triangle-d"
: class = "{ triangle: openState }"
> < / lay-icon >
< / template >
< / lay-input >
< template # content >
< dl class = "layui-select-options" >
< div class = "layui-select-search" v-if = "multiple" >
< lay -input
v-model = "searchValue"
prefix -icon = " layui -icon -search "
placeholder = "请搜索"
size = "sm"
> < / lay-input >
< / div >
< template v-if = "items" >
< lay -select -option
v-for = "(item, index) in items"
v-bind = "item"
:key = "index"
> < / lay-select-option >
< lay-tag-input
v-if = "multiple"
v-model = "multipleValue "
:allow-clear = "allowClear "
:collapseTagsTooltip = "collapseTagsTooltip"
:minCollapsedNum = "minCollapsedNum"
:disabledInput = "true"
>
< template # suffix >
< lay-icon
type = "layui-icon-triangle-d "
: class = "{ triangle: openState } "
> < / lay-icon >
< / template >
< slot > < / slo t >
< / dl >
< / templat e>
< / lay-dropdown >
< / div >
< / template >
< / lay-tag-inpu t>
< lay-input
v-els e
v-model = "singleValue"
:placeholder = "placeholder"
:allow-clear = "allowClear"
:readonly = "true"
>
< template # suffix >
< lay-icon
type = "layui-icon-triangle-d"
: class = "{ triangle: openState }"
> < / lay-icon >
< / template >
< / lay-input >
< template # content >
< dl class = "layui-select-options" >
< div class = "layui-select-search" v-if = "multiple" >
< lay -input
v-model = "searchValue"
prefix -icon = " layui -icon -search "
placeholder = "请搜索"
size = "sm"
> < / lay-input >
< / div >
< lay-select-option v-if = "showEmpty && !multiple" :label="emptyMessage" value="" > < / lay -select -option >
< template v-if = "items" >
< lay -select -option
v-for = "(item, index) in items"
v-bind = "item"
:key = "index"
> < / lay-select-option >
< / template >
< slot > < / slot >
< / dl >
< / template >
< / lay-dropdown >
< / div >
< / template >