Launching a modal with Nuxt

Currently, I am in the process of developing a Nuxt application that features a list of products. When a user clicks on a product from the list, it opens up a dedicated page for that particular item, which is functioning as intended.

The current structure of the application is as follows:

/pages/featured // This directory contains the products
/pages/product/:id/:slug // Dedicated page for each product

Now, I have a new feature in mind that I would like to implement:

  • I want to maintain the dedicated product page layout if a user accesses it from a page other than the products directory or if they land directly on it;
  • If a user clicks on a product from the products directory, I wish to open an almost full-screen dialog displaying the product over the directory;
  • Ensure that the routing changes are reflected on the dialogs as well.

An example of what I envision is similar to the photo directory feature on Youpic.

The goal is to present a list of "products" entirely within a dialog box with internal navigation capabilities.

I have been researching the documentation on Nuxt routing and Vue Router to work on this development, but I am still quite far from finding a solution.

Although the code snippet presented here seems promising and aligns with my requirements, I am having trouble understanding how to implement it correctly and create custom routing for my Nuxt project:

export default {
  router: {
    extendRoutes (routes, resolve) {
      routes.push({
        path: '/users/:id',
        components: {
          default: resolve(__dirname, 'pages/users'), 
          modal: resolve(__dirname, 'components/modal.vue')
        },
        chunkNames: {
          modal: 'components/modal'
        }
      })
    }
  }
}

Answer №1

Here is a sandbox solution that I created for you: https://codesandbox.io/s/reverent-leftpad-xj81p

Breakdown of the solution:

In this solution, I have utilized the beforeRouteLeave() function from the vue-router, which is a default feature available for nuxt pages:

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

This function blocks any route changes on the main page and triggers a modal dialog when navigating to the product detail page by clicking on a product link.

To manage the URL changes when opening or closing the modal, I have incorporated the use of the window.history object:

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

I encourage you to experiment with this setup as it should mirror the functionality provided in the youpic example you referenced.

Please note that I have kept the example intentionally basic without using actual modals for simplicity.

Answer №2

Having encountered a similar scenario, I recently incorporated this functionality and found that I was overthinking it unnecessarily.

The approach I took was quite simple - I transformed the single resource page (/pages/product/:id/:slug in your case) into a default modal. Leveraging vuetify, where v-dialog serves as the modal component, allowed me to achieve this without altering the structure of my nuxt project hierarchy. In your context, the 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;
    }
}
};

Answer №3

It seems like you are interested in implementing a route for a directory of products at , with a full-screen dialog opening upon clicking on a product leading to the Details page at

https://www.example.com/product/:id/:slug
. Please feel free to correct me if I have misunderstood your requirements!

There are two ways to achieve this:

1) Implement a redirect using nuxt-link from each product listed in the directory to the Details page.

2) Manually update the route using router.push when clicking on a product to open the dialog.

If we take a look at as an example, with its Nuxt code structure located at pages/explore, they use manual route updates with router.push to navigate to specific images like . To handle such URLs efficiently, one must maintain structured pages like pages/image/:id/:slug in the Nuxt setup.

I hope this explanation helps! Feel free to reach out if you need further clarification or discussion.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there only a single particle in Three.js?

I am trying to add a single particle to my scene and have the ability to move it around. However, my attempts to do so without using a Particle System have been unsuccessful. Whenever I try to render the particle as a mesh, nothing appears on the screen. I ...

Guide on Implementing a Function Post-Rendering in Angular 2+

I'm looking to implement some changes in the Service file without modifying the Component.ts or directive file. Here's what I need: 1) I want to add an event listener after the service renders its content (which is generated by a third-party tool ...

proper way to delete an event listener in vue 3

I have a function that listens for viewport dimensions when the project is first mounted and also after each resize event. However, I am unsure of the correct way to remove this listener. const { createApp, onMounted, ref } = Vue; const app = createA ...

Incorporate an onclick event to the elements within the array

I'm currently working on iterating over an array and adding an onclick event to each element. My goal is to be able to click on each div and have them log their values in the console. However, I am facing a challenge in applying the onclick event to e ...

Customizing Column Background Color with AngularJS

https://i.sstatic.net/OHFFF.png My current webapp highlights the day of the week on a table for the current day and the day two weeks from now. However, I'm facing an issue with adjusting the highlight if either of these days falls on a holiday. Curr ...

What is the method for establishing a callback for call status using the Twilio Voice JavaScript SDK?

Currently, I am in the process of utilizing the Twilio Programmable Voice JavaScript SDK to initiate an outbound call with a statusCallback and statusCallbackEvent in order to update another system once the call is finished. Below is the snippet of my cod ...

Having trouble with Silverlight running JavaScript?

When I try to call a JavaScript function from a SL component using the HtmlPage.Window.Invoke api, it works fine if the function is defined in the page (html). For example: HtmlPage.Window.Invoke("publishValue", topic, jsonObject); However, if I place th ...

Flask does not provide a direct boolean value for checkboxes

After struggling for a week, I am still lost on where to make changes in my code. I need the checkbox to return a boolean value in my Flask application. Below are snippets of the relevant code: mycode.py import os, sqlite3 from flask import Flask, flash ...

What steps are needed to configure ESLint to exclusively analyze .ts files?

I need ESLint to exclusively focus on processing .ts files and not .js files. In order to achieve that, I made a .eslintignore file and included the following lines: *.js **/*.js Nevertheless, it appears that ESLint is disregarding this file. Is there so ...

Having trouble getting the Bootstrap 5 Modal to function properly within an Electron app

Facing an issue with my web app using Bootstrap 5, as the modal is not displaying properly. Below is the HTML code for the modal and the button that triggers it: <div class="modal" tabindex="-1" id=&quo ...

The most basic form of req.body will consistently be devoid of any content

I am currently working on passing basic data from the client to the server using a POST request for testing purposes. However, I am encountering issues with receiving empty or undefined logs on req.body. Server: //jshint esversion:6 const express = requi ...

Encountering a 500 internal server error or receiving an error message stating "invalid value for stripe.confirmCardPayment

I'm currently working on implementing a payment component for my React app using Stripe for the first time. Despite following a tutorial closely, I keep encountering an internal server error or receiving an "invalid value for stripe.confirmCardPayment ...

What is the best way to adjust viewport settings for child components, ensuring the container size is set to 100vw/100vh for all children

Within my project, I have connected the react-static repository with the react repository using yarn link. "react": "^16.13.1" "react-static": "^6.0.18" I am importing various components from the react-static reposi ...

Two interconnected queries with the second query relying on the results of the first

I am currently facing a challenge in my Phonegap (Cordova) application where I need to display a list of items, each requiring an additional query. Let me simplify it with an example scenario. Imagine a student can be enrolled in multiple courses and a co ...

Vue.js shattering the boundaries of SVG animation

Upon initializing new Vue(...), the svg animation stops working. I have not come across anyone else experiencing the same issue, even though most animations are done directly with Vue.js. I attempted using anime.js, but it also fails to work alongside vu ...

Tips for submitting an Ajax Form with identical Name attributes?

One part of my form consists of input fields with the same 'Name' values that will be stored as an Array. I am attempting to send these values via AJAX to PHP for updating my database. The challenge I'm facing is figuring out how to send t ...

Updating parent data in Vue.js does not automatically trigger an update in the child component

I have the following: Vue.component('times-updated', { template: '<span>Times Updated: {{ timesUpdated }}</span>', data: function() { return { timesUpdated: this.$parent.myData.timesUpdated ...

Tips on eliminating overlapping strokes

I'm having trouble with drawing an array of circles that are meant to intersect a series of lines. The issue I face is that if the circles overlap, a stroke appears underneath them which I want to remove. Does anyone have any suggestions on how to el ...

Error: The XPath expression provided is invalid for use with the scrollIntoView function in Selenium

My task involves utilizing Python to extract data from a website that features a filter pane requiring scrolling. I came across a code snippet that aids in navigating through a list of elements by iterating through a loop. recentList = driver.find_element ...

Utilizing Angular RXJS to generate an array consisting of three different observable streams

I am trying to use three different streams to create an array of each one. For example: [homePage, mainNavigation, loan_originators] However, currently only mainNavigation is being returned. const homePage = this.flamelinkService.getData('homePage ...