VUE实现级联选择框与选项互斥

需求

        功能布局如下图,实现根据一级选项的code去查询二级选项,并且其他二级选择框无法再次选中已经被选的二级选项。

代码实现

HTML

        一级选择框:
<div style="margin-top: 20px;" v-for="(item, index) in questions" :key="index">
                    <span><span style="color: red;">*</span>问题类别:</span>
                    <a-select style="width: 240px;"            :value="item.primaryIndicators.itemCode"
                        @change="handleChangetypes(index,$event)">
                        <a-select-option v-for="itemone,ccindex in problemTypeoptions" :key="itemone.itemCode+ccindex"
                            :value="itemone.itemCode">{{ itemone.itemName }}
                        </a-select-option>
                    </a-select>
         二级选择框:
<a-select :showSearch="false" style="width: 240px;margin-left: 40px;" mode="multiple"
                        @change="handlechildtypes(index, item.secondaryIndicatorkeys)"
                        v-model:value="item.secondaryIndicatorkeys">
                        <a-select-option v-for="citem, cindex in item.CategoryDetails" :key="cindex"
                            :value="citem.itemCode">{{ citem.itemName }}
                        </a-select-option>
                    </a-select>
 </div>

数据结构

questions:({
            primaryIndicators: {
                itemCode: "",
                itemName: "",
                parentItemCode: "",
                changed: true
            },
            CategoryDetails: [

            ],
            secondaryIndicatorkeys: [],
            secondaryIndicators: [{
                itemCode: "",
                itemName: "",
                parentItemCode: "",
                changed: true
            }]
        })

        我们看到二级选择框的选择项并没有像一级一样直接双向绑定选项的code,因为一级选项虽然能多选,但是数据结构是对象,而二级是数组,如果直接item.secondaryIndicators[index].itemCode就有问题,故用一个secondaryIndicatorkeys来单独存储二级选项的code。

JS

        改变一级选项:

        将primaryIndicators的值更改为现在对应选项的code,使用getProblemTypeInfo接口用一级选项的code查询二级选项,将查询回来的二级选项存于questions中的CategoryDetails数组:

const handleChangetypes = async (index, code) => {
    questions.value[index].primaryIndicators = problemTypeoptions.value.find(item => {
        return item.itemCode == code
    })
    questions.value[index].CategoryDetails = []
    questions.value[index].secondaryIndicatorkeys = [],
        questions.value[index].secondaryIndicators = [],
        spinning.value = true
    let cdatas = await useStore.getproblemTypeinfo(1, code)
    questions.value[index].CategoryDetails = cdatas
    spinning.value = false
}

        因为二级绑定的不是secondaryIndicators,故选择二级后需要把数据传递给真正要穿回后端的questions的secondaryIndicators:

const handlechildtypes = (index, slects) => {
    questions.value[index].secondaryIndicators = []
    slects?.map(item => {
        let cdataobjs = questions.value[index].CategoryDetails.find(citem => {
            return citem.itemCode == item
        })
        questions.value[index].secondaryIndicators.push(cdataobjs)
    })
}

        上面就实现了基本的级联功能,但是没用实现二级选项的互斥,下面我们来实现二级选项互斥。

        使用了a-select组件API中的select和deselect来监听选中的二级选项增减:

 <div v-for="fitem, findex in Questionitems" :key="findex" v-if="allquestions"
                            style="margin-bottom: 10px;">
                            <a-select placeholder="请选择" @select="selectmytype($event, findex)"
                                v-model:value="fitem.primaryIndicators" style="width: 150px">
                                <template v-for="item, index in allquestions">
                                    <a-select-option :value="item?.primaryIndicators?.itemCode">
                                        {{ item?.primaryIndicators?.itemName }}
                                    </a-select-option>
                                </template>
                            </a-select>

                            <a-select @select="selecttype($event, fitem.primaryIndicators, true)"
                                @deselect="selecttype($event, fitem.primaryIndicators, false)" mode="multiple"
                                :disabled="!fitem.primaryIndicators.length" placeholder="请选择"
                                v-model:value="fitem.secondaryIndicators" style="width: 150px;margin-left: 10px;">
                                <template v-for="citem, cindex in getChileds(fitem.primaryIndicators)" :key="cindex">
                                    <a-select-option
                                        :disabled="getchildrendis(citem.disabled, fitem.secondaryIndicators.includes(citem?.itemCode))"
                                        :value="citem?.itemCode"> 
                                        <span :title="citem?.itemName">
                                            {{ citem?.itemName }}
                                        </span>
                                    </a-select-option>
                                </template>
                            </a-select>
</div>

        选项映射到返回表单中:

const selectmytype = (itemcode, index) => {
    Questionitems.value[index].myprimaryIndicators = allquestions.value.find(item => {
        return item.primaryIndicators.itemCode == itemcode
    })?.primaryIndicators
}

       将后端查询到的数据回显到页面,并将选中的二级选项选项标识符置为真,这样修改表单只能从后端返回的二级中选(而非全部二级选项),如果不需要限制则不需加这个标识符:

const selecttype = (event, fitemcode, newtype) => {
    allquestions.value = allquestions.value.map(item => {
        if (item.primaryIndicators.itemCode == fitemcode) {
            item.secondaryIndicators = item.secondaryIndicators.map(citem => {
                if (citem.itemCode == event) {
                    citem.disabled = newtype
                }
                return citem;
            })
        }
        return item;
    })
}

        获得二级选项:

const getChileds = (code) => {
    let chiledtypes = allquestions.value.find(item => {
        return item.primaryIndicators.itemCode == code
    })
    return chiledtypes ? chiledtypes.secondaryIndicators : []
}

        判断二级选项被选中没有:

const getchildrendis = (boll1, bool2) => {
    return boll1 && !bool2;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leviash

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值