Fundamentals

Data Operations (Mutations)

Creating, updating, and deleting data in Nuxt Crouton

Nuxt Crouton provides two ways to mutate data:

Quick Way: useCroutonMutate()

Use when: One-off actions, utilities, prototyping

<script setup lang="ts">
const { mutate } = useCroutonMutate()

// Create
await mutate('create', 'shopProducts', {
  name: 'New Product',
  price: 29.99
})

// Update
await mutate('update', 'shopProducts', {
  id: 'product-123',
  name: 'Updated Name'
})

// Delete
await mutate('delete', 'shopProducts', ['id1', 'id2'])
</script>

Optimized Way: useCollectionMutation()

Use when: Forms, repeated operations

Complete Examples: For full useCollectionMutation usage patterns and API details, see Mutation Composables.

When to Use Which?

For a detailed comparison and decision matrix, see the Mutation Composables API Reference.

Create Operations

Basic Create

<script setup lang="ts">
const { create } = useCollectionMutation('shopProducts')

const handleCreate = async () => {
  const newProduct = await create({
    name: 'Widget',
    price: 19.99,
    inStock: true
  })

  console.log('Created:', newProduct.id)
}
</script>

Create with Relations

<script setup lang="ts">
const { create } = useCollectionMutation('shopProducts')

// Create product with category relation
await create({
  name: 'Widget',
  price: 19.99,
  categoryId: 'cat-123'  // Foreign key
})

Update Operations

Basic Update

<script setup lang="ts">
const { update } = useCollectionMutation('shopProducts')

const handleUpdate = async (productId: string) => {
  await update(productId, {
    name: 'Updated Widget',
    price: 24.99
  })
  // updatedBy and updatedAt are automatically set
}
</script>
Automatic Audit Tracking: When you update a record, the system automatically sets:
  • updatedBy to the current user's ID
  • updatedAt to the current timestamp
You don't need to manually include these fields in your update data. The userId field (creator) remains unchanged.

Partial Update

<script setup lang="ts">
// Only update specific fields
await update('product-123', {
  price: 29.99  // Only price changes
})

Delete Operations

Single Delete

<script setup lang="ts">
const { deleteItems } = useCollectionMutation('shopProducts')

const handleDelete = async (productId: string) => {
  await deleteItems([productId])
}
</script>

Bulk Delete

<script setup lang="ts">
const { deleteItems } = useCollectionMutation('shopProducts')

const handleBulkDelete = async (productIds: string[]) => {
  await deleteItems(productIds)
}
</script>

Bulk Operations

For bulk update, delete, and other batch operations on multiple records, see the dedicated Bulk Operations guide.

Quick tip: Use a loop with useCroutonMutate for simple bulk operations, or implement optimistic updates for better UX.

Error Handling

<script setup lang="ts">
const { create } = useCollectionMutation('shopProducts')

const handleCreate = async () => {
  try {
    await create({
      name: 'Widget',
      price: 19.99
    })
    // Success - cache automatically refreshes
  } catch (error) {
    console.error('Failed to create product:', error)
    // Show error toast
  }
}
</script>

Optimistic Updates

For implementing optimistic updates with rollback on error, see the dedicated Optimistic Updates guide.

Quick tip: Optimistic updates improve perceived performance by updating the UI before the server responds.

Cache Invalidation

Mutations automatically invalidate and refresh all related queries:

// After mutation, all matching caches refresh automatically
await create({ name: 'New Product' })
// → Triggers refetch for all shopProducts queries

// These all get refreshed:
// collection:shopProducts:{}
// collection:shopProducts:{"page":1}
// collection:shopProducts:{"page":2}
// collection:shopProducts:{"locale":"en"}

See Also

Related Documentation: