Reusing Single-Record Components for Bulk Operations

📖 2 minutes read




Reusing Single-Record Components for Bulk Operations

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:

  1. Optional default values (or null)
  2. 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.

Category: Laravel | Keywords: Vue.js, component reuse, optional props, DRY, Laravel, architecture


Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *