Implementing Custom Single and Multiple Selection for Tables with Vue 3 and Element Plus
Project Context: Developing a examination system using Vue 3 and Element Plus.
Feature Scenario: In the question addition interface, question are categorized into objective and subjective types. Objective questions can be further divided into single-choice and multiple-choice types, which necesssitates that a single-choice question can only have one correct answer selected, while a multiple-choice question can have multiple correct answers selected.
Implementation Preview
Direct Code Implementation
Template (Table Component)
<el-button class="btn" icon="Plus" plain style="width: 100px;height: 29px;margin-bottom: 10px" type="primary" @click="addOption">
Add Option
</el-button>
<el-table ref="questionsTable" :data="tableData" border row-key="id">
<el-table-column :index="indexMethod" align="center" label="Serial" type="index" width="100"/>
<el-table-column align="center" label="Correct Answer" prop="isRight" width="100">
<template #default="scope">
<el-checkbox v-if="form.type==1||form.type==3" v-model="scope.row.isRight" label="Answer" size="large" @change="handleSingleSelection(scope.row.isRight,scope.$index)"/>
<el-checkbox v-else v-model="scope.row.isRight" label="Answer" size="large"/>
</template>
</el-table-column>
<el-table-column align="center" label="Option Image" width="160">
<template #default="scope">
<el-upload
:before-upload="validateImageUpload"
:on-success="handleImageUploadSuccess"
:show-file-list="false"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
class="avatar-uploader"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar"/>
<el-icon v-else class="avatar-uploader-icon">
<Plus/>
</el-icon>
</el-upload>
</template>
</el-table-column>
<el-table-column align="center" label="Option Content" prop="content" width="1150">
<template #default="scope">
<el-input
v-model="scope.row.content"
:rows="2"
placeholder="Enter option content"
type="textarea"
/>
</template>
</el-table-column>
<el-table-column align="center" class-name="small-padding fixed-width" label="Actions">
<template #default="scope">
<el-button circle icon="Delete" type="danger" @click="removeOption(scope.$index)"></el-button>
</template>
</el-table-column>
</el-table>
Script (Vue Composition API)
const initializeOptions = (questionType) => {
tableData.value = []
if (questionType == 1) {
tableData.value.push(
{content: '', image: '', isRight: false},
{content: '', image: '', isRight: false},
{content: '', image: '', isRight: false}
)
} else if (questionType == 2) {
tableData.value.push(
{content: '', image: '', isRight: false},
{content: '', image: '', isRight: false},
{content: '', image: '', isRight: false},
{content: '', image: '', isRight: false}
)
} else if (questionType == 3) {
tableData.value.push(
{content: '', image: '', isRight: false},
{content: '', image: '', isRight: false}
)
}
}
const handleSingleSelection = (selected, index) => {
tableData.value.forEach((item, key) => {
if (key !== index) {
item.isRight = false
}
})
}
const addOption = () => {
tableData.value.push({content: '', image: '', isRight: false})
}
const removeOption = (index) => {
tableData.value.splice(index, 1)
}