Advanced

Conditional Fields & Dependent Dropdowns

Create dynamic forms with conditional logic

Build dynamic forms that show/hide fields based on conditions and create cascading dropdown menus.

Conditional Fields

Show or hide form fields based on the value of other fields:

<template>
  <UForm>
    <UFormField label="Product Type" name="type">
      <USelectMenu
        v-model="state.type"
        :options="['physical', 'digital']"
      />
    </UFormField>

    <!-- Show only for physical products -->
    <UFormField v-if="state.type === 'physical'" label="Weight" name="weight">
      <UInput v-model.number="state.weight" type="number" />
    </UFormField>

    <!-- Show only for digital products -->
    <UFormField v-if="state.type === 'digital'" label="Download URL" name="downloadUrl">
      <UInput v-model="state.downloadUrl" />
    </UFormField>
  </UForm>
</template>

Dependent Dropdowns

Create cascading dropdowns where options in one field depend on the selection in another:

Query Examples: For complete useCollectionQuery patterns, see Querying Data.
<script setup lang="ts">
const { items: categories } = await useCollectionQuery('shopCategories')
const selectedCategory = ref<string | null>(null)

// Fetch subcategories when category changes
const { items: subcategories } = await useCollectionQuery('shopSubcategories', {
  query: computed(() => ({
    categoryId: selectedCategory.value
  }))
})
</script>

<template>
  <UFormField label="Category" name="categoryId">
    <USelectMenu
      v-model="selectedCategory"
      :options="categories"
      option-attribute="name"
    />
  </UFormField>

  <UFormField v-if="selectedCategory" label="Subcategory" name="subcategoryId">
    <USelectMenu
      v-model="state.subcategoryId"
      :options="subcategories"
      option-attribute="name"
    />
  </UFormField>
</template>

How It Works

Conditional Fields

  1. Use Vue's v-if directive to conditionally render form fields
  2. Reference reactive state values to determine visibility
  3. Fields are automatically added/removed from the form state

Dependent Dropdowns

  1. The parent dropdown value is stored in a reactive ref
  2. A computed query watches the parent value
  3. When the parent changes, the child query automatically refetches
  4. The child dropdown only appears when the parent has a value

Best Practices

  • Always provide default values for conditional fields
  • Clear dependent field values when parent selection changes
  • Use loading states while fetching dependent options
  • Validate that required conditional fields are filled before submission

Auto-Generated Dependent Fields

For common patterns like loading data from related collections, Nuxt Crouton can generate dependent field logic automatically through schema configuration.

When to Use Auto-Generated vs Manual

Use Auto-Generated Dependent Fields when:

  • Loading data from a referenced collection (e.g., slots from a location)
  • The pattern is standard (fetch on change, reset on dependency change)
  • You want regeneration-safe code
  • Using supported display modes like slotButtonGroup

Use Manual Conditional Fields when:

  • Custom business logic beyond simple data loading
  • Complex validation or computed values
  • Unsupported UI patterns
  • One-off scenarios

Example: Auto-Generated Slot Selection

Instead of manually writing:

<script setup>
const { data: locationData } = await useFetch(() =>
  state.value.location
    ? `/api/teams/${teamId}/bookingsLocations/${state.value.location}`
    : null
, {
  watch: [() => state.value.location],
  immediate: false
})

watch(() => state.value.location, () => {
  state.value.slot = 0
})
</script>

Simply configure your schema:

{
  "slot": {
    "type": "number",
    "meta": {
      "dependsOn": "location",
      "dependsOnField": "slots",
      "dependsOnCollection": "locations",
      "displayAs": "slotButtonGroup"
    }
  }
}

The generator creates all the fetch logic, watchers, and conditional UI automatically.

Benefits of Auto-Generated Approach

  • Regeneration-Safe - Persists through schema changes and regeneration
  • Consistent - Same pattern across all collections
  • Maintainable - Configuration in schema, not scattered in code
  • Type-Safe - Automatically generates TypeScript types
  • DRY - No code duplication for common patterns

See Schema Format - Dependent Fields for complete configuration details.