/ Gists / 12 multiple watchers
On gists

12 multiple watchers

cdruc vue

Page.vue Raw #

<script setup>
import {reactive, watch} from "vue";
import BaseLabel from "./BaseLabel.vue";
import BaseInput from "./BaseInput.vue";
import BaseTextarea from "./BaseTextarea.vue";
import SecondaryButton from "./SecondaryButton.vue";
import BaseButton from "./BaseButton.vue";
import BaseCheckbox from "./BaseCheckbox.vue";
import BaseSwitch from "./BaseSwitch.vue";

const form = reactive({
  name: null,
  is_sellable: false,
  is_available_online: false,
  is_available_in_stores: false,
  price: null,
  description: null,
});

/**
 * Separate watchers
 */
watch(
  () => form.is_available_online,
  isAvailableOnline => {
    if (!isAvailableOnline && !form.is_available_in_stores) {
      form.is_sellable = false;
    }
  }
);

watch(
  () => form.is_available_in_stores,
  isAvailableInStores => {
    if (!isAvailableInStores && !form.is_available_online) {
      form.is_sellable = false;
    }
  }
);

/**
 * Watch multiple values in the same watch function
 */
watch(
  () => [form.is_available_online, form.is_available_in_stores],
  ([isAvailableOnline, isAvailableInStores]) => {
    if (!isAvailableOnline && !isAvailableInStores) {
      form.is_sellable = false;
    }
  }
);

/**
 * Combine watched values
 */
watch(
  () => form.is_available_online || form.is_available_in_stores,
  isSellable => (form.is_sellable = isSellable)
);
</script>

<template>
  <form class="bg-white p-6 rounded-xl shadow">
    <div class="space-y-6 sm:space-y-5">
      <div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
        <BaseLabel required>Name</BaseLabel>
        <div class="mt-1 sm:mt-0 sm:col-span-2">
          <BaseInput
            v-model="form.name"
            placeholder="Enter product name"
            type="text"
          ></BaseInput>
        </div>
      </div>

      <div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
        <BaseLabel>Can be sold?</BaseLabel>
        <div class="mt-1 sm:mt-0 sm:col-span-2">
          <BaseSwitch v-model="form.is_sellable"></BaseSwitch>
        </div>
      </div>

      <template v-if="form.is_sellable">
        <div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
          <BaseLabel>Available in online stores</BaseLabel>
          <div class="mt-1 sm:mt-0 sm:col-span-2">
            <BaseCheckbox v-model:checked="form.is_available_online" />
          </div>
        </div>

        <div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
          <BaseLabel>Available in physical stores</BaseLabel>
          <div class="mt-1 sm:mt-0 sm:col-span-2">
            <BaseCheckbox v-model:checked="form.is_available_in_stores" />
          </div>
        </div>

        <div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
          <BaseLabel>Price</BaseLabel>
          <div class="mt-1 sm:mt-0 sm:col-span-2">
            <BaseInput
              v-model="form.price"
              placeholder="Enter price"
              type="number"
            ></BaseInput>
          </div>
        </div>
      </template>

      <div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
        <BaseLabel>Description</BaseLabel>
        <div class="mt-1 sm:mt-0 sm:col-span-2">
          <BaseTextarea
            v-model="form.description"
            placeholder="Enter product description"
            rows="3"
          ></BaseTextarea>
        </div>
      </div>
    </div>

    <div class="pt-5">
      <div class="flex justify-end">
        <SecondaryButton type="button">Cancel</SecondaryButton>
        <BaseButton type="submit">Save</BaseButton>
      </div>
    </div>
  </form>
</template>