Changing component properties using router-view in Vue.js is the recommended approach

Looking to pass a boolean value from a view within a router-view up to the root App.vue and then on to a component in the App.vue. Successfully achieved this, but encountering an error:

Received a warning about mutating a prop directly, as it will be overwritten whenever the parent component re-renders. Suggested to use a data or computed property based on the prop's value. Prop causing mutation: "drawer"

Here is a snippet of the code:

In Home.vue:

<template>
  <div class="home" v-on:click="updateDrawer">
    <img src="...">
  </div>
</template>
<script>
export default {
name: "Home",
methods:{
updateDrawer:function(){
  this.$emit('updateDrawer', true)
}
};
</script>

The above view is located within a router-view and the value is passed to App.vue below:

<template>
<v-app class="">
<Navbar v-bind:drawer="drawer" />
<v-main class=" main-bg">
  <main class="">
    <router-view v-on:updateDrawer="changeDrawer($event)"></router-view>
  </main>
</v-main>
</v-app>
</template>

<script>
import Navbar from '@/components/Navbar'

export default {
name: 'App',
components: {Navbar},

data() {
return {
  drawer: false
}
},
methods:{
changeDrawer:function(drawz){
  this.drawer = drawz;
}
},
};
</script>

The value of drawer is sent by binding it in the navbar component.

In Navbar.vue:

<template>
<nav>
<v-app-bar app fixed class="white">
  <v-app-bar-nav-icon
    class="black--text"
    @click="drawer = !drawer"
  ></v-app-bar-nav-icon>
  </v-app-bar>
  <v-navigation-drawer
  temporary
  v-model="drawer"
  >
   ...
 </v-navigation-drawer>
</nav>
</template>
<script>
export default {
props:{
drawer:{
  type: Boolean
}
},
};
</script>

This method works only once before displaying the aforementioned error. Seeking advice on how to address and resolve this issue.

Answer №1

Within Navbar.vue, the property "drawer" is being manipulated whenever a user clicks on "v-app-bar-nav-icon," resulting in a change where drawer becomes the opposite of its current value.

The issue lies in the fact that this mutation (value change) is occurring from the child component's side (Navbar.vue as the child). This contradicts Vue's principles, as props should only transmit data from parent to child components (with App.vue acting as the parent and Navbar.vue as the child), not the other way around.

A more suitable approach would involve emitting an event each time you wish to alter the value of "drawer" within Navbar.vue, similar to what is done in Home.vue.

Subsequently, you can listen for this event in App.vue and adjust the drawer variable accordingly.

For instance:

Navbar.vue

<v-app-bar-nav-icon
    class="black--text"
    @click="$emit('changedrawer', !drawer)"
></v-app-bar-nav-icon>

App.vue

<Navbar v-bind:drawer="drawer" @changedrawer="changeDrawer"/>

I initially overlooked the fact that v-model="drawer" was also used in Navbar.vue. v-model likewise modifies the value of drawer, which goes against our intended behavior. This can be rectified by splitting up the v-model into v-on:input and :value as shown below:

<v-navigation-drawer
    temporary
    :value="drawer"
    @input="val => $emit('changedrawer', val)"
>

Implementing a centralized state management system such as Vuex could prove beneficial in this particular case ;)

Answer №2

To monitor changes on the drawer prop in Navbar.vue, consider the following approach:

<template>
  <nav>
    <v-app-bar app fixed class="white">
      <v-app-bar-nav-icon
        class="black--text"
        @click="switchDrawer"
      />
    </v-app-bar>
    <v-navigation-drawer
      temporary
      v-model="navbarDrawer"
    >
      ...
    </v-navigation-drawer>
  </nav>
</template>

<script>
export default {
  data () {
    return {
      navbarDrawer: false
    }
  },
  props: {
    drawer: {
      type: Boolean
    }
  },
  watch: {
    drawer (val) {
      this.navbarDrawer = val
    }
  },
  methods: {
    switchDrawer () {
      this.navbarDrawer = !this.navbarDrawer
    }
  }
}
</script>

Home.vue

<template>
  <div class="home">
    <v-btn @click="updateDrawer">Update drawer</v-btn>
  </div>
</template>

<script>
export default {
  name: 'Home',
  data () {
    return {
      homeDrawer: false
    }
  },
  methods: {
    updateDrawer: function () {
      this.homeDrawer = !this.homeDrawer
      this.$emit('updateDrawer', this.homeDrawer)
    }
  }
}
</script>

App.vue

<template>
  <v-app class="">
    <Navbar :drawer="drawer" />
    <v-main class="main-bg">
      <main class="">
        <router-view @updateDrawer="changeDrawer"></router-view>
      </main>
    </v-main>
  </v-app>
</template>

<script>
import Navbar from '@/components/Navbar'

export default {
name: 'App',
components: { Navbar },

data () {
return {
drawer: false
}
},
methods: {
changeDrawer (newDrawer) {
this.drawer = newDrawer
}
}
}
</script>

This method does not alter the drawer prop directly but is responsive to any modifications.

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

What is the best way to conceal elements that do not have any subsequent elements with a specific class?

Here is the HTML code I have, and I am looking to use jQuery to hide all lsHeader elements that do not have any subsequent elements with the class 'contact'. <div id="B" class="lsHeader">B</div> <div id="contact_1" class="contac ...

The font size varies depending on the language being used

On a single web page, there are 3 different language words displayed: Language / 한국어 / ภาษาไทย I am interested in enlarging the Thai word (ภาษาไทย) to make it stand out. <span class="thai">ภาษาไท ...

Unable to pass several parameters to a Component

I'm attempting to send three URL parameters to a React Component. This is my approach: App.js: <Route path="/details/:id(/:query)(/:type)" handler={DishDetails}/> DishDetails.js: class DishDetails extends Component { constructor(props) { ...

Choose a specific 24-hour range with the Date Interval Selector

I am currently utilizing the Date Range Picker plugin for bootstrap from the website http://www.daterangepicker.com/#examples, and I have a requirement to set the maximum date time range to be within 24 hours. Below is an example demonstrating how I can s ...

Sharing data between VueJS2 components

I am working on a project where the parent component retrieves a large JSON object from the server. My goal is to parse this data and then pass it down to the child components. The structure of the child components is as follows: <child-comp /> I ...

Include the image source in the array

Currently, I am utilizing this loop to showcase images using Smarty {foreach from=$gallery item=image key=KEY} <div class="col-lg-2 col-md-2 col-sm-4 col-xs-6 smallImage"> <img ng-click="bigImage('/files/galleries/{$image.gallery ...

Enter the UL element and modify the LI class if it contains the .has_children class

Seeking assistance in navigating through a UL element to modify the LI and nested UL classes when .has_children is detected. Take a look at this example: <ul class="nav navbar-nav"> <li class="first current parent">Link1</li> < ...

What is the best way to showcase a QR code on a mesh using three.js?

I utilized the QRcode library available at to try and showcase it on a mesh object as a texture using the following code: var qrcode = new QRCode( "test", { text: "http://jindo.dev.naver.com/collie", width: 128, height: 128, colorDark : " ...

Use Javascript to conceal a div element if there are no links present

I am working on a website using ModX CMS and I am attempting to hide or remove a div element when it does not contain any anchor tags. How can I achieve this? I have already attempted the following code without success: jQuery(function($) { if ($(".pages ...

Is there a way to export a specific portion of a destructuring assignment?

const { a, ...rest } = { a: 1, b: 2, c: 3 }; If I want to export only the rest object in TypeScript, how can I achieve that? ...

What are the steps to utilizing the $document service in AngularJS?

I am a complete beginner when it comes to AngularJS and JavaScript in general, and I find myself a bit confused about the usage of $document. From what I understand, $document provides access to some JQuery functions. So, if I want to remove an element tha ...

Inquiring about the Model component within the MVC architecture in a web application created with NodeJs and integrated with

As a beginner in NodeJs, I am venturing into creating web applications using the express framework and MySQL. Understanding that in MVC architecture, views are represented by *.ejs files, controllers handle logic, and models interact with the database. Ho ...

Steps for importing a jQuery script into a Vue component

Looking to include a basic jQuery script in my Vue file. Attempted to import it using the following method: In the Vue file import {myScript} from "@/components/scripts/myScript.js" Then in the myScript.js file : export const myScript = { $('.cl ...

Tips for converting file byte code to file form data

From one folder I am retrieving a file and uploading it to another server. However, when I extract the file from the first folder, I receive a byte code representation of that file. The API for uploading the file to the second folder requires FormData as a ...

Tips for displaying dynamic content based on conditions in React

I am currently working on adjusting the boilerplate repository in order to render different pages based on whether a user is logged in or not. The current setup always displays the same page but includes additional content if there is an authenticated user ...

Scrolling in iOS 8 causing flickering problem with background image

Utilizing the Supersized jQuery slider plugin to create a full-page background slider with a fade-in effect and added height for scrolling. The slider functions correctly on desktop, but upon testing on an iOS 8 iPad device, there is noticeable flickering ...

When working with Vuex, remember to only alter the store state within mutations. Avoid mutating the Vuex

Consider the following situation: Textfield Component: <v-text-field v-model="form.profile.mobile_business" label="Mobile" prepend-inner-icon="mdi-cellphone" ></v-text-field> To retrieve the current value, I use: data() { retu ...

Retrieve the name of the path for the specified * stack within Express.js

When working with Express.js, I am utilizing '*' to catch the error 404. Is there a way for me to find out the path name of the error URL? app.get('*', (req, res) => { console.log("route: " + JSON.stringify(req.route) ...

Error message: Encountered JavaScript heap out-of-memory error during Azure DevOps React Container Production Build

I am facing challenges in building a React production Docker container with Azure DevOps pipelines. Despite upgrading my build environment and code, the pipeline failed to run successfully. After conducting some research, I attempted to add the "--node-fla ...

simulated xhr server along with the locales in polymer appLocalizeBehavior

Currently, I am in the process of developing a web frontend utilizing Polymer. Within my web component, I incorporate various other components such as paper-input or custom web components. To facilitate testing for demonstration purposes, I have integrated ...