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:
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'
}
})
}
}
}
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.
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.
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".
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 .
I have built a sandbox solution for you here: https://codesandbox.io/s/reverent-leftpad-xj81p
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.
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;
}
}
};
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!!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With