btwong
btwong

Reputation: 49

VueJS v3, Vuex and Composition API and v-model on input field

Problem

I have some code that is getting a search query from a Vuex store. I am using a computed property to get the search query, and then binding it to the v-model of the input field. I want to be able to edit/change the search term via the input field, and then submit the new search query, which will then perform a new search query.

But the since the computed property is "Read Only", when I change the search query in the input field, it does not update search query, and causes a warning:

vendor.js:16674 Write operation failed: computed value is readonly

Question

How can I get the search query from the Vuex, populate a input field, change/update it, and then submit the changed query? I have tried to find a computed setter for the composition API, but cannot find one.

Any ideas? or should I look at another approach?

Below is the code

<template>

  <form role="search"
      aria-label="Sitewide"
      @submit.prevent="submitSearch"
      autocomplete="off">

    <input type="text" v-model="searchQuery" />
    <button type="button" v-on:click="submitSearch">Search</button>

  </form>
</template>

<script>
import { computed } from 'vue'
import { useStore } from 'vuex'

export default {
   name: "ProductSearchBox",
   setup() {
      const store = useStore();
      const searchQuery = computed(() => store.getters["search/getFiltersSearchTerm"]);

      const submitSearch = () => {
        store.dispatch('search/performSearch', searchQuery);
      }

      return {
          searchQuery,
          submitSearch
      }
   }
}
</script>

Upvotes: 0

Views: 1115

Answers (2)

Skaneris
Skaneris

Reputation: 39

You can use computed property for v-model like this:

<template>
    <form role="search"
        aria-label="Sitewide"
        @submit.prevent="submitSearch"
        autocomplete="off">

        <input type="text" v-model="searchQuery" />

    </form>
</template>

<script>
import { computed } from 'vue'
import { useStore } from 'vuex'

export default {
   name: "ProductSearchBox",
   setup() {
      const store = useStore();
      const searchQuery = computed({
         get: () => store.getters['search/getFiltersSearchTerm'],
         set: (newValue) => store.commit('search/yourMutation', newValue)
      });
      
      const submitSearch = () => {
        store.dispatch('search/performSearch', searchQuery);
      }

      return {
          searchQuery,
          submitSearch
      }
   }
}
</script>

Upvotes: 1

Thomas
Thomas

Reputation: 7118

This sounds more like a use case for a watch.

const searchQuery = ref('');
watch(
  () => store.getters["search/getFiltersSearchTerm"],
  (term) => searchQuery.value = term
);

Upvotes: 1

Related Questions