Table of Contents
Reusing Single-Record Components for Bulk Operations
You have a TaskEditor component that works perfectly for editing one task. Now you need bulk editing. Should you build a separate BulkTaskEditor component from scratch?
No. Make your single-record component bulk-capable by designing for optional prepopulation.
The Pattern
Your single-record editor passes all the defaults explicitly:
<!-- SingleTaskEdit.vue -->
<StatusUpdateForm
:defaultStatus="task.status"
:defaultDueDate="task.due_date"
:defaultAssignee="task.assignee_id"
:tasks="[task]"
/>
For bulk editing, just pass the common values (or nothing if they differ):
<!-- BulkTaskEdit.vue -->
<StatusUpdateForm
:defaultStatus="commonStatus"
:defaultDueDate="commonDueDate"
:defaultAssignee="commonAssignee"
:tasks="selectedTasks"
/>
The StatusUpdateForm component doesn’t know (or care) if it’s handling one task or fifty. It just uses whatever defaults you pass.
How to Make This Work
Design your child component with optional props that have sensible defaults:
// StatusUpdateForm.vue
export default {
props: {
tasks: {
type: Array,
required: true
},
defaultStatus: {
type: String,
default: null // Null = user must choose
},
defaultDueDate: {
type: String,
default: null
},
defaultAssignee: {
type: Number,
default: null
}
}
}
When a default is null, the form field starts empty. When it has a value, the field is prepopulated.
The Parent’s Job
The parent component (single or bulk) decides what to pass:
// BulkTaskEdit.vue
computed: {
commonStatus() {
const statuses = this.selectedTasks.map(t => t.status);
const unique = [...new Set(statuses)];
return unique.length === 1 ? unique[0] : null;
}
}
If all selected tasks have status: "pending", pass "pending". Otherwise, pass null.
Why This Beats Separate Components
- One source of truth: Bug fixes apply to both single and bulk editing
- Consistent validation: Same rules, same error messages
- Less code: No duplicated form logic
- Easier testing: Test the component once with different prop combinations
Key Insight
The child component should be data-agnostic. It doesn’t care where the defaults come from or how many records it’s editing. It just needs:
- Optional default values (or null)
- An array of records to update
The parent decides what defaults to pass based on whether it’s single or bulk editing.
Rule of thumb: If your component takes a single record as input, refactor it to accept an array of records plus optional defaults. You’ve just made it bulk-capable with zero extra UI code.
Leave a Reply