Incorporate personalized buttons into the header navigation for each view using VueJS

In my VueJS project, I attempted to include custom buttons in the sub navigation menu which could be customized for each view. Initially, I tried adding a simple property to the main data element, but that didn't yield the desired results. Then, I came across the concept of mixins, however, that approach also failed. Here's what I have so far:

// main.js
new Vue({
    //...
    mixins: [{
        data() {
            return {
                customHeaderButtons: [],
                test: '123'
            };
        }
    }],
})
<!-- TheHeader.vue -->
<template>
    <CHeader>
        <CSubheader class="px-3">
            <CBreadcrumbRouter class="border-0" />
            <CHeaderNav v-if="$root.customHeaderButtons" class="ml-auto" style="min-height: 0">
                <CHeaderNavLink v-for="item in $root.customHeaderButtons">
                    <CIcon :name="item.iconName" />
                </CHeaderNavLink>
                {{$root.customHeaderButtons}}
            </CHeaderNav>
            {{$root.test}} -> 123
        </CSubheader>
    </CHeader>
</template>

<!-- MyView.vue -->
<template>
    {{test}} -> ABC
</template>
<script>
export default {
    data() {
        return {
            customHeaderButtons: [{
                iconName: 'cil-save'
            }],
            test: 'ABC'
        }
    },
    // ...
}
</script>

Can anyone explain why the value change from MyView.vue is not reflected in the header? In theory, when the user navigates to MyView.vue, the text in the header bar should switch to ABC.

PS: Please note that TheHeader is part of the template and not contained within the view itself!

<!-- TheContainer.vue -->
<template>
  <div class="c-app">
    <TheSidebar/>
    <div class="c-wrapper">
      <TheHeader/> <-- Data from any child view should be sent here <---+
      <div class="c-body">                                                  |
        <main class="c-main">                                               |
          <CContainer fluid>                                                |
            <transition name="fade">                                        |   
              <router-view></router-view> <-- This is where MyView goes ----+
            </transition>
          </CContainer>
        </main>
      </div>
      <TheFooter/>
    </div>
  </div>
</template>

Answer №1

After seeking inspiration from a helpful tutorial, I was able to find a solution that works for my current situation. Admittedly, it is a bit complex and may not be the most ideal solution. Here is how it all comes together:

To start, you'll need to make some modifications in the container Vue where your <router-view> tag is located. Add a property binding to your header element or component as described by Boussadjra. Then, include an event listener within the router-view like this:

<template>
    <div class="c-app">
        <TheSidebar />
        <div class="c-wrapper">
            <TheHeader :customHeaderButtons="customHeaderButtons" />
            <div class="c-body">
                <main class="c-main">
                    <CContainer fluid>
                        <transition name="fade">
                            <router-view @setCustomHeaderButtons="setButtons"></router-view>
                        </transition>
                    </CContainer>
                </main>
            </div>
            <TheFooter />
        </div>
    </div>
</template>

In the JavaScript portion of your code, implement the event listener and ensure that you reset the buttons after every page change:

export default {
    name: 'TheContainer',
    components: {
        TheSidebar,
        TheHeader,
        TheFooter
    },
    data() {
        return {
            customHeaderButtons: []
        }
    },
    methods: {
        setButtons(buttons) {
            this.customHeaderButtons = buttons;
        }
    },
    beforeRouteUpdate (to, from, next) {
        this.customHeaderButtons = [];
        next();
    }
}

Next, emit the event in the created event of your view:

export default {
   data() {
       return {
           customHeaderButtons: [{
               iconName: 'cil-save'
           }],
       }
   },
    created() {
        this.$emit('setCustomHeaderButtons', this.customHeaderButtons);
    }
}

Ensure that you have defined this.customHeaderButtons in your view model beforehand.

Additionally, remember to re-emit the event if you nest multiple views within each other. It does not bubble up automatically! Alternatively, you can use this.$parent.$emit() to bypass a nesting level.

If you have any simpler or more effective approaches, please do share them.

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 reason behind HTML5Boilerplate and other frameworks opting for a CDN to host their jQuery files

When it comes to loading jQuery, HTML5Boilerplate and other sources[citation needed] have a standard process that many are familiar with: <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script>window. ...

How can I retrieve the latest state of the Redux store in getServerSideProps in Next.js?

I am attempting to retrieve the most up-to-date redux state in getServerSideProps like so: export const getServerSideProps = async (ctx) => { const state = store.getState(); console.log(state.name); return { props: { login: false } }; }; H ...

Unable to save input from <from> in the React state object

I'm currently working on a project in reactjs where I need to store user input in the react state object. I followed an example from reactjs.com, but it seems like the input is not being stored in the state object as expected. class CreateMovieForm ex ...

Incorporate variable key-value pairs into a JavaScript array or object

Is it possible to add a key value pair to an existing JavaScript associative array using a variable as the key? I need this for JSON encoding and prefer a simple solution over using plugins or frameworks. ary.push({name: val}); In the above code snippet, ...

Configuring a Selenium Firefox profile

While performing our tests, we came across an issue with how FireFox handles events when the browser is not in focus. We discovered that this problem can be resolved by setting up a FireFox profile with the preference "focusmanager.testmode" set to true ( ...

What changes can be made to this function in order for the arches to be positioned directly in front of the camera?

I devised a method that arranges arches in front of a camera, side by side: <!-- HTML --> <a-curvedimage v-for="(value, index) in model" :theta-length="42" :rotation="setThumbsRotation(value, index)"> </a-curvedimage> <a-camera ...

Understanding the behavior of the enter key in Angular and Material forms

When creating forms in my MEAN application, I include the following code: <form novalidate [formGroup]="thesisForm" enctype="multipart/form-data" (keydown.enter)="$event.preventDefault()" (keydown.shift.enter)="$ev ...

Struggling with updating state using splice method within an onClick event in React Hooks

CODE DEMO I'm facing an issue with my code snippet where it appears fine when I console.log it, but fails to set the state. The goal is to delete a box by using splice when clicked, however, something seems to be preventing it from working properly. ...

Click on a plane within a three.js environment to determine the X Y position within it

When using a raycaster, I can successfully obtain the current object (in this case, a plane) under the mouse. However, I am seeking a more precise X and Y value for the mouse position INSIDE the plane. var vector = new THREE.Vector3( ( event.clientX / win ...

Backend data not displaying on HTML page

I am currently working on an Angular 8 application where I have a service dedicated to fetching courses from an API endpoint. The service method that I'm using looks like this: loadCourseById(courseId: number) { return this.http.get<Cours ...

Creating Styles in Material-UI using makeStyles: Tips for Styling by Element Name

I am currently facing a challenge of adding a rule for all <p> tags within the current component. Despite searching through various sources such as material-ui documentation and Stack Overflow, I have been unable to find any information on how to add ...

Steps for displaying search results based on state when a button is clicked

My current challenge involves creating a component that displays a list of results upon clicking the "Find" button. However, I am encountering issues with the results state variable not resetting when I utilize setResults([]). In addition, only the most r ...

Adjust the button's color even after it has been clicked

My goal is to update the button's color when it's clicked. I found some examples that helped me achieve this, but there's an issue - once I click anywhere outside of the button, the CSS class is removed. These buttons are part of a form, and ...

Creating a linear video playback system

Having an issue with my code in Chrome where auto play is enabled, but the video won't play. I have a loop set up to play each video one after the other, but first things first - how do I get this video to start playing? If there's a pre-made so ...

Fixing the Angular2 glitch: 'Uncaught TypeError: Cannot read property 'apply' of undefined'

Seeking solutions: How can I fix the "Uncaught TypeError: Cannot read property 'apply' of undefined" error that keeps showing up in the console of my Angular2 application? Any helpful insights are appreciated! ...

Adding the Edit action in React-Redux is a crucial step towards creating a dynamic

I am looking to add an edit action to my blog page in addition to the existing ADD, DELETE and GET actions. Any suggestions on how I can implement the EDIT action to make my blog editable with just a button click? Your help would be greatly appreciated. ...

Pass information from the child component to the parent component using Vue.js

I am currently working on a modal component named modal_form.vue, which I am using inside another component called index.vue. My goal is to pass a data variable from modal_form.vue to index.vue. Can anyone provide me with an example of how to achieve this ...

Mastering the placement of script tags in your Next.js application with Next Script

I'm in the process of integrating a third-party script into my Next.js website. This particular script adds an iframe right below its corresponding script tag. Therefore, it is crucial for me to have precise control over the placement of the script ta ...

How can you switch between CSS styles using JQuery?

Is there a way to change CSS properties every time I click using jQuery? I couldn't find any information on this specific topic. Can someone guide me on how to achieve this with jQuery? I want the background color to change each time it is clicked. W ...

Leveraging Ajax with PlayFramework Results

As stated in the PlayFramework Document 2.0 and PlayFramework Document 2.1, it is known that Play can return various responses such as: Ok() badRequest() created() status() forbidden() internalServerError() TODO However, when trying to send a response wi ...