Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nuxt open link into modal

I'm building a Nuxt application that has a list of products and clicking on one of them open a dedicated page of the product. It is working fine.

Structure is:

/pages/featured // directory of products
/pages/product/:id/:slug // Dedicated product page

Now I wish to add a new feature:

  • I wish to keep the dedicated page of the product if clicked from a page that is not the directory of the products or if people land directly on it;
  • I wish to open an almost full-screen dialog of the product on top of the directory if, obviously, clicked from the directory;
  • Keep the routing change on dialogs.

A nice example of what I wish to achieve is the photo directory of Youpic.

A list of "products", visible entirely in a dialog with its internal navigation.

I'm looking at the various nuxt-routing and vue-router documentations to try developing it but I'm still far away from the solution.

This small portion of the code I see here looks pretty similar at what I need but I don't understand how should I correctly implement it and how to create my nuxt custom routing:

export default {
  router: {
    extendRoutes (routes, resolve) {
      routes.push({
        path: '/users/:id',
        components: {
          default: resolve(__dirname, 'pages/users'), // or routes[index].component
          modal: resolve(__dirname, 'components/modal.vue')
        },
        chunkNames: {
          modal: 'components/modal'
        }
      })
    }
  }
}
like image 513
Ayeye Brazo Avatar asked Mar 15 '20 11:03

Ayeye Brazo


People also ask

How to handle links in nuxt application?

Read more in Guide > Features > Routing . Nuxt provides <NuxtLink> component to handle any kind of links within your application. <NuxtLink> is a drop-in replacement for both Vue Router's <RouterLink> component and HTML's <a> tag.

What is <nuxtlink> component?

Nuxt provides <NuxtLink> component to handle any kind of links within your application. <NuxtLink> is a drop-in replacement for both Vue Router's <RouterLink> component and HTML's <a> tag.

How to navigate between pages in a nuxt app?

The NuxtLink Component To navigate between pages of your app, you should use the <NuxtLink> component. This component is included with Nuxt.js and therefore you don't have to import it like you do with other components. It is similar to the HTML <a> tag except that instead of using a href="/about" you use to="/about".

Why do I need to add the nuxt component to layouts?

Basically, this component gets replaced by what is inside your page components depending on the page that is being shown. Therefore it is important that you add the <Nuxt> component to your layouts. The <Nuxt> component can only be used inside layouts .


Video Answer


3 Answers

I have built a sandbox solution for you here: https://codesandbox.io/s/reverent-leftpad-xj81p

Explaining the solution:

The solution uses beforeRouteLeave() function from the vue-router which is available to your nuxt pages by default:

beforeRouteLeave(to, from, next) {
  if (to.name === "product-id") {
    this.displayProductModal(to);
  } else {
    next();
  }
},

This function interrupts any route changes on the featured page before they happen, and if the target route is the route of the product detail (which means someone clicked on product link), it opens the modal dialog instead.

To handle the url change on opening and closing of the modal, the window.history object is used:

displayProductModal(route) {
  this.activeModal = route.params.id
  window.history.pushState({}, null, route.path)
},
hideProductModal() {
  this.activeModal = null
  window.history.pushState({}, null, this.$route.path)
}

Try to play around a bit, it should work exactly like the youpic example you provided.

Note: There are no real "modals" used in the example, the whole example is as basic as possible for the sake of simplicity.

like image 146
ajobi Avatar answered Oct 19 '22 22:10

ajobi


I recently implemented this feature after facing nearly the same situation you are in. At least in my case, I was really overthinking it.

All that I did was take the single resource page (/pages/product/:id/:slug in your case) and have it be a modal by default. I am using vuetify and v-dialog is a modal. The nuxt project hierarchy didn't change. Your equivalent would be the slug.vue page.

<template>
<v-dialog v-model="drawer" fullscreen hide-overlay transition="dialog-bottom-transition">
    <v-card height="100vh">
        <div class="flex">
            <v-toolbar dark color="primary darken-2">
                <v-btn icon dark @click="close">
                    <v-icon>close</v-icon>
                </v-btn>
                <v-toolbar-title>{{member.alias}}</v-toolbar-title>
                <v-spacer></v-spacer>
                <v-toolbar-items>
                    <v-btn text nuxt :to="`/members/${member.id}/notes`">Notes</v-btn>
                    <v-btn text nuxt :to="`/members/${member.id}/edit`">Edit</v-btn>
                    <v-btn text nuxt :to="`/members/${member.id}/payments`">Payments</v-btn>

                </v-toolbar-items>
            </v-toolbar>
            <v-row no-gutters>
            </v-row>
        </div>
    </v-card>
</v-dialog>
</template>

<script>
import { mapGetters } from "vuex";
export default {
watchQuery: ["id"],
transition(to, from) {
    if (!from) {
        return "slide-left";
    }
    return +to.query.id < +from.query.id ? "slide-right" : "slide-left";
},
data() {
    return {
        id: this.$route.params.id,
        drawer: true
    };
},
fetch({ store, params }) {
    store.commit("members/active", params.id);
},
computed: {
    member: {
        get() {
            return this.$store.getters["members/active"];
        },
        set(member) {
            this.$store.commit("members/update", {
                id: member.id,
                member: member
            });
        }
    }
},
methods: {
    async close() {
        await this.$nuxt.$router.go(-1);
        this.drawer = false;
    }
}
};
like image 33
retrograde Avatar answered Oct 19 '22 21:10

retrograde


What I have an understanding of your requirement is looking at https://youpic.com/explore is that you want https://www.example.com/featured (directory of products) route and there on click of product you want open dialog which will be full screen with the route as https://www.example.com/product/:id/:slug (Details page).

please correct me if I am wrong!!

Now you can achieve this with 2 way

1) On click of the each product(i.e.https://www.example.com/featured (directory of products) route) use nuxt-link with redirect to https://www.example.com/product/:id/:slug (Details page) route

2) On click of the each product(i.e.https://www.example.com/featured (directory of products) route) manually update the route with router.push and open dialog

Now, if we see https://youpic.com/explore and let's take this as Nuxt code structure will be pages/explore where they manually update route with router.push to https://youpic.com/image/16660875/steffi-by-fs22photography but when you share/take this URL(https://youpic.com/image/16660875/steffi-by-fs22photography) and try to open that so in Nuxt code structure you have to maintain pages/image/:id/:slug which will actually a page if you directly see go to https://youpic.com/image/16660875/steffi-by-fs22photography Page you can see.

Hope this will help you!!

If you have any doubts we can discuss more!!

like image 23
Hardik Shah Avatar answered Oct 19 '22 23:10

Hardik Shah