This is the second day of my participation in the November Gwen Challenge. Check out the details: the last Gwen Challenge 2021

preface

This is not a three-level linkage of the address component, this is to increase the function of multi-region selection on the basis of this demand; I don’t want it to be that, but the product needs to be that. I went to the gay friends’ community, but there was no such component, so I had to do it myself. Although the process encountered many pits, but finally worked out.

rendering

Get all provincial city information

Address: gist.github.com/afc163/7582… I was able to get information about all the provinces and cities, and I did a simple process for it

import provinces from "china-division/dist/provinces.json"; import cities from "china-division/dist/cities.json"; import areas from "china-division/dist/areas.json"; areas.forEach(area => { const matchCity = cities.filter(city => city.code === area.cityCode)[0]; if (matchCity) { matchCity.children = matchCity.children || []; matchCity.children.push({ label: area.name, value: area.name }); }}); cities.forEach(city => { const matchProvince = provinces.filter( province => province.code === city.provinceCode )[0]; if (matchProvince) { matchProvince.children = matchProvince.children || []; matchProvince.children.push({ label: city.name, value: city.name, children: city.children }); }}); const city = provinces.map(province => ({ label: province.name, value: province.name, children: province.children })); console.log(city) export default cityCopy the code

Get provincial information

pattern

<a-table :data-source="tableData" :pagination="false" style="margin: 0 30px"> <a-table-column key="area" title=" available area" data-index="area"> <template #default="{record}"> <span v-html="record.area" :title="record.areaName"></span> </template> </a-table-column> <a-table-column key="frist" <a-input-number v-model:value="record. Frist "> <a-input-number v-model:value="record. Frist "> Placeholder =" please input "></ a-inline-number ></ template> </a-table-column> <a-table-column key="freight" title=" freight (yuan)" data-index="freight"> <template #default="{ record }"> <a-input-number v-model:value="record.freight" Placeholder =" input "></a-input-number> </template> </a-table-column> <a-table-column key="second" title=" add-on" data-index="second"> <template #default="{ record }"> <a-input-number v-model:value="record.second" Placeholder =" input "></a-input-number> </template> </a-table-column> <a-table-column key="secondPrice" title=" data-index="secondPrice"> <template #default="{ record }"> <a-input-number v-model:value="record.secondPrice" Placeholder =" input "></a-input-number> </template> </a-table-column> <a-table-column key="action" title=" action" data-index="action"> <template #default="{ record,index }"> <! -- {{index}} --> <span style="color: #f36d69" v-if="record.area ! = = 'national' "@ click =" delateArea (index) "> delete < / span > < / template > < / a - table - column > < / a - table > < - modal: a title =" 'choose not to package mail area" :visible="modal_visible" @cancel="handleCancel" width="1000px" @ok="handleAddOk()" > <area-modal ref="areaCheck" @Area="Area"></area-modal> </a-modal>Copy the code

Initial data and click to show hidden events

Let tableData = reactive([{area: 'reactive ', areaName:' reactive ', frist: 1, freight: 1111, second: 1, secondPrice: 111}]) const showArea = () => { modal_visible.value = true; }; const handleCancel = () => { modal_visible.value = false; // areaCheck.value.checkCanelAlls(); };Copy the code

Selecting the Region modal box style, I use Popover to control the display of subset data after mouse over. Add checkbox input to control selection

<a-row> <a-col :span="24"> <div class="allChoose"> <input type="checkbox" @click="checkAll" class="box" :checked="choose.length === treeData.length" :class="0 < choose.length && choose.length < treeData.length ? 'check' : '" /> select <! - {{choose}} {{choose. Length}}, {{treeData. Length}} -- > < / div > < span @ click = "checkCanelAll" > clear < / span > < / a - col > < a - col :span="6" v-for="(item, index) in treeData" :key="index"> <check-box-tree :tree-data="item" :all-check="all" :clear="clear" ref="checkBox" @chooseValue="chooseValue" ></check-box-tree> </a-col> </a-row> <! --check-box-tree--> <div class="treeTip"> <a-popover class="popover" placement="bottom"> <template #content> <div v-for="(item, i) in treeData.children"> <input type="checkbox" class="box" :checked="checkAreaList.indexOf(item.label) >= 0" @click="checkedOne(item.label)" /> {{ item.label }} </div> </template> <div class="treeDate"> <input type="checkbox" @click="checkedChildAll()" class="box" :checked="checkAreaList.length === treeData.children.length" :class="0 < checkAreaList.length && checkAreaList.length < treeData.children.length ? 'check' : ''" /> <span>{{ treeData.label }}</span> <! -- <span class="chooseNum">({{ checkAreaList.length === 0 ? checkAreaList.length: checkAreaList.length-1}}/{{ treeData.children.length }})</span> --> <span class="chooseNum">({{ checkAreaList.length }}/{{ treeData.children.length }})</span> </div> </a-popover> </div>Copy the code

Single check operation

const checkArea = ref({ area: '' as String | '', checkArea: [] as String[] }); const checkAreaList = ref([] as String[]); const isFlag = ref(1); const checek = ref(); const checkedOne = (value: String): Void = > {/ / with, according to judge whether there is at the same time, to get its index (if any) var idIndex = checkAreaList. Value. The indexOf (value); If (idIndex > = 0) {/ / if already contains the id, the remove (radio button is selected into the selected) checkAreaList. Value. The splice (idIndex, 1); } else {// Check the checkbox checkAreaList.value.push(value); }};Copy the code

multi-select

const checkedChildAll = (): void => { if (checkAreaList.value.length === props.treeData? .children? .length) { cancel(); } else { props.treeData? .children? .map(item => { checkAreaList.value.push(item.label); }); // console.log(checkAreaList.value) checkAreaList.value = Array.from(new Set(checkAreaList.value)); isFlag.value = 1; }};Copy the code

By listening to the selected information obtained, the selected information will be passed to the parent component, in the parent component, a data integration, to obtain all the selected data, in the data of a deduplication, and remove the city is empty data

const chooseValue = (val: Any) = > {/ / console log (val, '-- -- -- -- -- -') / / obtain the selected data if (choose) value) length = = = 0) {choose. Value = choose.value.concat([val]); } else { let isflag = true; for (let i = 0; i < choose.value.length; i++) { if (choose.value[i].area === val.area) { isflag = false; choose.value[i].checkArea = val.checkArea; } } if (isflag) { choose.value = choose.value.concat([val]); }}}; watch(()=>choose.value, (newVal)=>{ for(let i=0; i<newVal.length; i++){ if(newVal[i].checkArea.length <= 0){ newVal.splice(i,1) } } },{immediate:true, deep: true})Copy the code

Select all and cancel, respectively, define several states, passed to the child component, the child component on the passed data for a judgment, call select all or store data for a clean.

conclusion

Personal dishes, welcome correction, I feel I wrote a problem, but temporarily did not find a bug. I feel like I’m writing too much, emmmmmmmmmmm