Search code examples
javascripthtmlvue.jsaxiosvuex

Search input using a query using Vuex and Axios


I'm trying to make a search input where I input a query and that query gets added to the API call and returns me the data that I want, here's a sample of my code

      <input
    class="rounded-l-full w-full py-6 px-6 text-gray-700 leading-tight focus:outline-none"
    id="search"
    type="text"
    placeholder="Search"
    v-bind="query"
  />

    <button
      class="bg-blue-900 text-white rounded-full p-2 hover:bg-blue-700 focus:outline-none w-12 h-12 flex items-center justify-center"
      @click="getSearchResults()"
    >
      <font-awesome-icon :icon="['fas', 'search']" />
    </button>

My JS:

    <script>
import { mapActions, mapGetters, mapState } from "vuex";

export default {
  name: "Main",
  data() {
    return {};
  },
  computed: {
    ...mapGetters(["searchResult"]),
    ...mapState({
      query: (state) => state.query,
    }),
  },
  methods: {
    ...mapActions(["getSearchResults"]),
  },
};
</script>

My vuex module:

    import axios from "axios";

const state = {
  results: [],
  query: "",
};

const getters = {
  searchResult: (state) => state.results,
};

const actions = {
  async getSearchResults() {
    let query = state.query;
    const res = await axios.get(
      `https://www.theaudiodb.com/api/v1/json/1/search.php?s=${query}`
    );

    res.data.artists.forEach((artist) => state.results.push(artist));
  },
};

const mutations = {
  returnResults: (state, results) => (state.results = results),
};

export default {
  state,
  getters,
  actions,
  mutations,
};

The search query is not getting passed on the input, if I put something on the query from the Vuex module I get the correct results but if I input something and click the search button I get the default results of the api JSON which means my input is not working, I'd appreciate some help and thanks in advance!


Solution

  • First thing is that your using v-bind incorrectly, better use v-model:

    <input
        class="rounded-l-full w-full py-6 px-6 text-gray-700 leading-tight focus:outline-none"
        id="search"
        type="text"
        placeholder="Search"
        v-model="query"
      />
    

    second thing organize better your code when you are using vuex, I would do it of this way:

    Template:

    // pass the variable query to the funcion getSearchResults
    <button
          class="bg-blue-900 text-white rounded-full p-2 hover:bg-blue-700 focus:outline-none w-12 h-12 flex items-center justify-center"
          @click="getSearchResults(query)"
        >
          <font-awesome-icon :icon="['fas', 'search']" />
        </button>
    

    JS:

    // Only import mapActions and mapGetters
    // create the variable query inside of data() for v-model
    <script>
    import { mapActions, mapGetters} from "vuex";
    
    export default {
      name: "Main",
      data() {
        return {
             query:"",
          };
      },
      computed: {
        ...mapGetters(["searchResult"]),
       
        }),
      },
      methods: {
        ...mapActions(["getSearchResults"]),
      },
    };
    </script>
    

    VUEX:

    import axios from "axios";
    
    const state = {
      results: [],
    };
    
    const getters = {
      searchResult: (state) => state.results,
    };
    
    const actions = {
      async getSearchResults({commit}, query) {
        const res = await axios.get(
          `https://www.theaudiodb.com/api/v1/json/1/search.php?s=${query}`
        );
        // Execute the mutation which receive the data and pass to the state
        commit('returnResults', res.data.artists)
      },
    };
    
    const mutations = {
      returnResults: (state, results) => (state.results = results),
    };
    
    export default {
      state,
      getters,
      actions,
      mutations,
    };