Skip to content

Conditional statements ​

This example uses conditional actions in @dynamicforms/vue-forms to set a field's value, visibility and access from the values of other fields.

Demo ​

Conditional Actions Demo
apple
Color preview
Form Output

Form is unchanged

{
  "fruit": "apple",
  "favoriteColor": "red",
  "detailsToggle": false,
  "additionalInfo": ""
}

What the demo shows ​

  • ConditionalValueAction: one action per fruit sets the colour field's value when its statement becomes true. It applies on the transition from false to true only, so a colour typed by hand stays until another fruit is selected.
  • ConditionalVisibilityAction: the additional information field is 'full' while the details switch is on and 'suppress' otherwise, and the template does not render a suppressed field. Visibility affects only rendering: the suppressed field is still sent.
  • ConditionalAccessAction: Submit is an Action whose access is 'editable' while both the fruit and the colour hold a value and 'disabled' otherwise. The statement combines two NOT_EQUALS statements with AND. The button is disabled while the action is not executable, and a submit shows what the form sends.
  • Construction order: the conditional actions are passed to the constructors, and the group is built from the finished elements, so the actions have applied before the group records its baseline. The form starts with the colour red for apple, and isChanged is false.
  • Reset: rebind(originalValue) puts every value back to the baseline, including the colour.

TIP

To also leave a suppressed field out of what the form sends, register a ConditionalAccessAction on it as well; see What a container serializes.

Source Code ​

vue
<template>
  <div class="conditional-actions-demo">
    <v-card class="mb-4">
      <v-card-title>Conditional Actions Demo</v-card-title>
      <v-card-text>
        <v-form @submit.prevent>
          <!-- Fruit selection -->
          <v-select
            v-model="conditionsForm.fields.fruit.value"
            :items="Object.keys(fruitColorMap)"
            label="Select a fruit"
            outlined
            hide-details="auto"
            class="mb-4"
          ></v-select>

          <!-- Color field that updates based on fruit -->
          <v-text-field
            v-model="conditionsForm.fields.favoriteColor.value"
            label="Fruit color"
            outlined
            hide-details="auto"
            class="mb-4"
          ></v-text-field>

          <div class="color-preview mb-4" :style="{ backgroundColor: conditionsForm.fields.favoriteColor.value }">
            Color preview
          </div>

          <!-- Details toggle -->
          <v-switch
            v-model="conditionsForm.fields.detailsToggle.value"
            label="Show additional details"
            color="primary"
            hide-details="auto"
            class="mb-4"
          ></v-switch>

          <!-- Additional info field (conditionally visible) -->
          <v-text-field
            v-if="conditionsForm.fields.additionalInfo.visibility === 'full'"
            v-model="conditionsForm.fields.additionalInfo.value"
            label="Additional Information"
            outlined
            hide-details="auto"
            class="mb-4"
          ></v-text-field>
        </v-form>
      </v-card-text>

      <v-card-actions>
        <v-btn color="primary" :disabled="!submit.executable" @click="submitForm">
          {{ submit.label }}
        </v-btn>
        <v-btn color="secondary" @click="resetForm" class="ml-2">Reset</v-btn>
      </v-card-actions>
    </v-card>

    <v-card>
      <v-card-title>Form Output</v-card-title>
      <v-card-text>
        <p>Form is {{ conditionsForm.isChanged ? 'changed' : 'unchanged' }}</p>
        <pre class="output">{{ conditionsForm.value }}</pre>
        <template v-if="submitted">
          <p class="mt-4">Submitted</p>
          <pre class="output">{{ submitted }}</pre>
        </template>
      </v-card-text>
    </v-card>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import {
  Action,
  ConditionalAccessAction,
  ConditionalValueAction,
  ConditionalVisibilityAction,
  ExecuteAction,
  Field,
  Group,
  Operator,
  Statement,
} from '../../src'; // from '@dynamicforms/vue-forms'

const fruitColorMap: Record<string, string> = {
  apple: 'red',
  orange: 'orange',
  banana: 'yellow',
  grape: 'purple',
  blueberry: 'blue',
};

// The field the conditions read. It is declared before the group so that the other elements' actions can be
// passed to their constructors, and the form's baseline is recorded after the actions have applied.
const fruit = new Field({ value: 'apple' });

// 1. Conditional Value Action - Set color based on fruit selection, one action per fruit
const favoriteColor = new Field({
  value: '',
  actions: Object.entries(fruitColorMap).map(
    ([name, color]) => new ConditionalValueAction(new Statement(fruit, Operator.EQUALS, name), color),
  ),
});

// 2. Conditional Visibility Action - Show additional info field only when details toggle is on
const detailsToggle = new Field({ value: false });
const additionalInfo = new Field({
  value: '',
  actions: [new ConditionalVisibilityAction(new Statement(detailsToggle, Operator.EQUALS, true))],
});

// What the last submit sent
const submitted = ref('');

// 3. Conditional Access Action - Enable the submit action only when both fields hold a value
const submit = new Action({
  value: { label: 'Submit' },
  actions: [
    new ConditionalAccessAction(
      new Statement(
        new Statement(fruit, Operator.NOT_EQUALS, ''),
        Operator.AND,
        new Statement(favoriteColor, Operator.NOT_EQUALS, ''),
      ),
    ),
    new ExecuteAction((action, supr, params) => {
      submitted.value = JSON.stringify(conditionsForm.value);
      return supr(action, params);
    }),
  ],
});

const conditionsForm = new Group({ fruit, favoriteColor, detailsToggle, additionalInfo, submit });

async function submitForm() {
  await submit.execute();
}

// Back to the baseline: the values the form was built with, after its actions applied
function resetForm() {
  conditionsForm.rebind(conditionsForm.originalValue);
}
</script>

<style scoped>
.conditional-actions-demo {
  margin: 2rem 0;
}

.output {
  background-color: #f5f5f5;
  padding: 1rem;
  border-radius: 4px;
  white-space: pre-wrap;
}

.color-preview {
  height: 40px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
  transition: background-color 0.3s ease;
}
</style>

API Reference ​

Try It Yourself ​

  1. Select different fruits to see the colour change
  2. Type a colour by hand, then select another fruit
  3. Toggle the details switch to show and hide the additional information field
  4. Clear the colour: Submit is disabled
  5. Change a few fields, then Reset

Released under the MIT License.