Home > Software engineering >  Vue-Router Page reload with form submit
Vue-Router Page reload with form submit

Time:06-13

I'm trying to make a simple movie searcher to get familiarised with Vue but this thing is a pain in the ***.

The problem I have is that I'm using the same component for the majority of my routes because they all do the same work but with different info. So I thought it was a good idea to use path params to tell what kind of information it needs to fetch, all the other routes work fine but when I try to submit a form with the query that I need the API search for, the page does not reload so for the component the info is the same as in the previous route.

I have already tried with router.go() and it does not work. Also tried with beforeRouteUpdate and all its useless cousins but none of them work either.

Here is my code:

Router.js

import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
import Detail from "./views/Detail.vue";

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: "/",
      name: "home",
      component: Home
    },
    {
      path: "/favorites",
      name: "favorites",
      component: Home
    },
    {
      path: "/results/:search",
      name: "results",
      component: Home
    },
    {
      path: "/detail/:id",
      name: "detail",
      component: Detail
    }
  ]
});

Cards.vue This thing is called by Home

<template>
  <div >
    <Filters />
    <div
      v-if="$store.state.movieList.length > 0"
      
    >
      <Card
        v-for="(item, index) in $store.state.movieList"
        :key="index"
        :id="item._id"
        :title="item.title"
        :img="item.image"
        :year="item.year"
        :description="item.description"
      />
    </div>
    <div v-else >
      Not fun
    </div>
  </div>
</template>

<script>
import Card from "./Card.vue";
import Filters from "./Filters.vue";

export default {
  name: "cardContainer",
  components: {
    Card,
    Filters,
  },
  data() {
    return {
      path: this.$route.name,
      params: this.$route.params.search,
    };
  },
  beforeMount(){
    console.log("path", this.path);//this work when I change with the navBars Links, but not when using the search button

  },
  beforeRouteUpdate(to, from, next){
    console.log("I hope this works", to); //This thing does not work.
    next();
  }
};
</script>

SearchBar.vue

<template>
  <form  v-on:submit="onSubmit">
    <input type="text" v-model="search" />
    <button type="submit">
      Search
    </button>
  </form>
</template>

<script>
export default {
  name: "searchBar",
  data() {
    return {
      search: ""
    };
  },
  methods: {
    onSubmit() {
       // this.$router.go(`/results/${this.search}`) //does not work
      this.$router.push(`/results/${this.search}`);
      this.search = "";
    }
  }
};
</script>

UPDATE:

I resolve it by adding a weird watch in the cards component and using @submit.prevent="submit" when submitting the search form.

cards.vue

<script>
import Card from "./Card.vue";
import Filters from "./Filters.vue";

export default {
  name: "cardContainer",
  components: {
    Card,
    Filters,
  },
  data() {
    return {
      path: this.$route.name,
      params: this.$route.params.search,
    };
  },
  beforeMount() {
    console.log("path", this.path); //dispatch
  },
  created() {
    this.$watch(
      () => this.$route.params.search,
      () => {
         this.params = this.$route.params.search;
        //dispatch 
      }
    );
  },
};
</script>

I still want a cleaner way of doing it. If anyone finds it, please let me know it. Thank you.

CodePudding user response:

When u submit a form, the native behavior is refreshing the page, so I think you should do this:

v-on:submit.prevent="onSubmit"

or

@submit.prevent="onSubmit"

CodePudding user response:

I didnt read your question that closely but you might need to make router-view key based off the URL (which includes URL params) so that it's not caching when URL changes (by default it doesn't include url params)

<router-view :key="$route.fullPath"></router-view>

You should also never have the app refresh, ever, even on form submits. You should also use the .prevent method listed in the other answer.

If you need to share data across multiple pages you can use a store instead of query params, or you can just use the composition api to build an extremely simple store without complexity of vuex.

  • Related