Dynamic Components in Vue.js Router

In my quest to develop a single-page vue.js application using vue-router, I have set the default route (/) as a list of links to other pages resembling a landing page. Currently, all other pages function as dialogs for various scenarios. To simplify creating new dialogs, I devised a base-dialog page that establishes the generic dialog appearance while allowing specific routes to define the details. The three main sections include basic settings, logging settings, and advanced settings. Basic settings are mandatory for each scenario, logging settings remain constant across scenarios, and advanced settings are optional. I leverage named router-views to load the basic and advanced settings.


Prior Investigation

My approach was inspired by this discussion thread.


Code Excerpts

DialogPage.vue

<template>
  <div>
    <div id="basic-options" class="options">
      <router-view name="basicView" basic="true"/>
    </div>
    <div id="logging-options" class="alt-options">
      <!-- Custom components needed for logging options. This renders properly. -->
    </div>
    <div id="advanced-options" class="alt-options">
      <router-view name="advancedView" basic="false"/>
    </div>
  </div>
</template>

{Scenario}.vue

<template>
  <div>
    <!-- custom components to set up basic dialogs for {Scenario} -->
  </div>
</template>

The file {Scenario}Advanced.vue mirrors {Scenario}.vue but employs different child elements within the div container.

ScenarioSelector.js

/* Import Scenario Here */
import ScenarioA from '@/components/Scenarios/A'
import ScenarioAAdvanced from '@/components/Scenarios/AAdvanced'
import ScenarioB from '@/components/Scenarios/B'
import ScenarioBAdvanced from '@/components/Scenarios/BAdvanced'

/* Add them to the list */
const components =
{
    ScenarioA,
    ScenarioAAdvanced,
    ScenarioB,
    ScenarioBAdvanced
}

/* Do not modify anything here */
export default
{
    functional: true,
    props: [
        {
            name: 'scenario',
            type: String
        },
        {
            name: 'basic',
            type: Boolean,
            default: true
        }
    ],
    render (createElement, context) {
        var scenario = context.props.scenario
        console.log('Log anything, please')
        if (context.props.basic) {
            scenario += 'Advanced'
        }
        return createElement(components[scenario], context.data, context.children)
    }
}

Relevant snippet from router/index.js

export default new Router({
  routes: [
    /* Other routes */,
    {
      path: "/dialog/:scenario",
      component: DialogPage,
      props: true,
      children:[
        {
          path: "*",
          components: { basicView: ScenarioSelector, advancedView: ScenarioSelector },
          props: { basicView: true, advancedView: true }
        }
      ]
    }
  ]
}


The Issue

The render function in ScenarioSelector does not seem to be triggered. No logging occurs. There have been instances where it entered the function, but I cannot pinpoint the exact conditions leading to this behavior. Even when executed, no properties are being set.


Alternative Approaches Different route attempts:

export default new Router({
  routes: [
    /* Other routes */,
    {
      path: "/dialog/",
      component: DialogPage,
      props: true,
      children:[
        {
          path: "/:scenario",
          components: { basicView: ScenarioSelector, advancedView: ScenarioSelector },
          props: { basicView: true, advancedView: true }
        }
      ]
    }
  ]
}

With this setup, the links from the landing page (/dialog/{Scenario}) do not initiate any actions.

export default new Router({
  routes: [
    /* Other routes */,
    {
      path: "/dialog/",
      component: DialogPage,
      props: true,
      children:[
        {
          path: "ScenarioA",
          components: { basicView: ScenarioA, advancedView: ScenarioAAdvanced }
        },
        {
          path: "ScenarioB",
          components: { basicView: ScenarioB, advancedView: ScenarioBAdvanced }
        }
      ]
    }
  ]
}

Similarly, in this case, the links do not trigger any actions.


Edit

Previously, I mentioned uncertainty about what caused the code execution variations. A simple change from * to / in the child path resolved the issue. Example below:

export default new Router({
  routes: [
    /* Other routes */,
    {
      path: "/dialog/:scenario",
      component: DialogPage,
      props: true,
      children:[
        {
          path: "/",
          components: { basicView: ScenarioSelector, advancedView: ScenarioSelector },
          props: { basicView: true, advancedView: true }
        }
      ]
    }
  ]
}

Answer №1

I finally managed to resolve the issues with my code and get it functioning as expected after encountering two obstacles.

  1. As mentioned in my edit, I realized that using "/" instead of "*" for the path of the children was necessary. Initially, I thought "*" would work just fine regardless of the last part of the path, but that turned out not to be the case. If someone could provide further insight on this matter, I would greatly appreciate it. Please refer to the relevant code section in the question's Edit.
  2. The second issue arose from how I defined props in ScenarioSelector.js. The solution to this problem is detailed in response to this query. It clarified my mistake of not structuring my props as an object when implementing prop validation. Below is a snippet of the pertinent code:

/* ... */
export default
{
    functional: true,
    props: {
        scenario: String,
        basic: {
            type: Boolean,
            default: true
        }
    },
    render (createElement, context) {
        var scenario = context.props.scenario
        console.log('Log anything, please')
        if (context.props.basic) {
            scenario += 'Advanced'
        }
        return createElement(components[scenario], context.data, context.children)
    }
}

Now that I have addressed both these issues, the props values are correctly bound, and the desired output is successfully logged in the browser's console.

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

I continue to encounter an error every time I attempt to place an HTML nested div on a separate line

When I structure the HTML like this, I don't encounter any errors: <div class="game-card"><div class="flipped"></div></div> However, if I format it differently, I receive an error message saying - Cannot set property 'vi ...

Transmit form information using jQuery's ajax JSON functionality

Hello, I am new to PHP/jquery and I have a question. I would like to know how to send JSON data from a form field (such as name, age, etc.) using AJAX in a JSON format. I have searched for relevant information on this but couldn't find anything concre ...

Changing the color of a div element dynamically with JavaScript

Is there a way to improve the code below so that the background color of this div box changes instantly when clicked, without needing to click twice? function updateBackgroundColor(platz_id) { if(document.getElementById(platz_id).style.backgroundCol ...

Is there a way to confirm that a file has been chosen for uploading prior to form submission, by utilizing the jquery validator?

I have a section on my website where users can upload files. I am trying to implement validation to ensure that a file has been selected before the form is submitted. Currently, I am using the jQuery form validator plugin for handling form validations. Th ...

Sending a batch of files through an axios request by passing them as an object

I need to send multiple images in a specific format through an API call { "date":"currentDate", "files":[Files uploaded via input box] } Here is my approach: Method 1 const event = document.querySelector("#files"); const f ...

Error Message: jQuery script imported successfully, however, functions are not defined

Here is my HTML code: <script type="text/javascript" src="js/myjs.js"></script> <script> ... $("#enviornment").hide().delay(1200).css({'display':'block', 'opacity':'0'}).animate({'opacity&apos ...

I seem to be having trouble encoding a character in Internet Explorer 8, do you have any suggestions on how to fix

After making an XHR get request to my server side, I encountered a problem with Chinese characters in the request URL. While non-IE browsers worked fine, IE8 did not automatically encode the characters, leading to data handling issues on the server side. H ...

What are some strategies for pinpointing the cause of a regular expression validation failure?

Can the specific type of error (e.g. text too short, invalid characters) that caused a regular expression match failure, like the ones listed below, be identified? regexes = { name: /^[a-zA-Z0-9_ -]{3,32}$/, title: /^[a-zA-Z0-9_ -]{3,128}$/, ...

Make sure to include both the :value and v-model attributes when using a radio input field

<input type="radio" :value="myValue" v-model="value" /> I am attempting to create a radio button within a component, where value is a variable. However, I am encountering an error that states: :value="myValue" conflicts with v-model on the same ele ...

Firefox returns empty computed value in getComputedStyle function

When I use getComputedStyle on an element that has defined properties for left, right, and bottom, I noticed that Chrome returns 'auto' as the value for top, whereas Firefox returns the pixel value. However, interestingly, the top value does not ...

Choose the ngModel option from the dropdown menu

I have a project where I need the first question from a list to be displayed automatically. I found an example of how to do this using the index, like so: <select> <option *ngFor="let answer of answers; let i = index" [value]="answer.id" [selec ...

The fixed left div and scrollable right div are experiencing issues with their alignment

I am having an issue with a section where the left div is fixed and the right div is scrollable. However, the content of the right div scrolls even before the scroll top reaches the section. My goal is for the right div to scroll only when it reaches the t ...

The Arrival of Link: A Countdown Timer

I'm attempting to create a countdown timer that reveals a link after 20 minutes. Currently, this is my progress... <script type="text/javascript"> window.onload = function() { countDown('my_div1', '<a href="cdtl.html" ...

What is the process for importing the required dependencies for the maps module in react-svg-map?

Exploring interactive maps led me to discover the project react-svg-map. As I followed the example provided, a certain issue caught my attention: import Taiwan from "@svg-maps/taiwan"; The developers mentioned that they have separated the map&ap ...

Link the Sass variable to Vue props

When working on creating reusable components in Vue.js, I often utilize Sass variables for maintaining consistency in colors, sizes, and other styles. However, I recently encountered an issue with passing Sass variables using props in Vue.js. If I directly ...

Mongoose faces difficulty in locating records that were not initially generated using mongoose

After successfully creating a collection and a document in a local running database using mongosh, I encountered an issue while trying to access it via mongoose. Despite querying all documents using a model that matches the collection I created, the docume ...

Determining the spatial location of an object in Three.js in relation to the camera for the purpose of creating a trail

In my scene, I have an object (a pen) that rotates around its axis in the render loop using the following code: groupPen.rotation.y += speed; groupPen.rotation.x += speed; Additionally, I have a TrackballControls that allows the user to rotate the entire ...

Tips on including a trash can symbol to rows in a bootstrap table using React

I am working on a table that contains various fields, and I want to add a trash icon to each row so that when it is clicked, the specific row is deleted. However, I am encountering an issue where the trash icon is not showing up on the row and I am unable ...

Ways to transfer a variable from a component's function in Vue?

Can anyone help me figure out how to pass a variable from a function within a Vue component? Here's the code I've been working with: export default { name: 'app', data: function () { return{ city1: '&a ...

Ways to retrieve a single variable periodically and refresh it at intervals

One common issue faced by maintenance employees at my company is losing their log entry if they receive a call or text while filling out the daily form on their phones. To solve this problem, I came up with a solution to store the form values in PHP SESSIO ...