When utilizing a duplicated VueJS component on a single page, it fails to correctly reference its own instance

I've created a VueJS component and have it displayed multiple times on the same page. Each component functions independently, but there's an issue with a method that calculates its width offset and applies it as a class (such as width-800).

Everything works fine when there is only one instance of the component on a page.

However, when there are multiple instances, only the last one receives the class. The correct class is calculated for all instances based on their width, but only the final one actually gets the class applied.

<template>
    <div id="app-medialib" v-bind:class="[this.breakpoint]">
        <p>{{ this.breakpoint }}</p>

The value this.breakpoint holds the class name as a data property.

mounted: function(){
  var self = this;

  this.calculateBreakpoint();

  window.onresize = function(event) {
      self.calculateBreakpoint();
  };
}

Here's the method for calculating the breakpoint:

calculateBreakpoint: function(){
    var mediaLibraryWidth = null;

    var elems = document.getElementsByClassName('header medialib');
    for( var i=0; i<elems.length; i++ ){
        if( elems[i].offsetParent !== null ){
            console.log('elems[i]', elems[i]);
            mediaLibraryWidth = elems[i].offsetWidth;
            break;
        }
    }

    console.log('calculateBreakpoint', mediaLibraryWidth);

    if( mediaLibraryWidth > 956 ) {
        this.breakpoint = 'md';
    } else if( mediaLibraryWidth < 957 && mediaLibraryWidth > 700 ){
        this.breakpoint = 'sm';
    } else {
        this.breakpoint = 'xs';
    }

    console.log('calculateBreakpoint', this.breakpoint);
},

Any assistance would be greatly appreciated in solving this issue. I've been trying to figure it out for some time now.

Thank you.

Answer №1

When you attach a function to window.onresize, it will override any previous bindings. This can cause issues when you have multiple components in your application, as each mounted function will override the window.onresize event handler. That's why only the class of the last component is being changed.

To see this in action, try running the following code in your console:

window.onresize = function (e) {
  console.log('a')
}

window.onresize = function (e) {
  console.log('b')
}

After resizing, only 'b' will be logged.

For a better way to handle this issue, consider using jQuery to bind functions to the window.onresize event:

$(window).resize(function() {
 console.log('a')
})

$(window).resize(function() {
 console.log('b')
})

With this approach, both 'a' and 'b' will be logged when you resize the window.

To implement this with your specific case, change your window.onresize calls to:

$(window).resize(function() {
  self.calculateBreakpoint();
})

Alternatively, you can follow Daniel Beck's suggestion and use pure JavaScript without jQuery:

 window.addEventListener('resize', self.calculateBreakpoint )

Answer №2

Implement the v-bind:class feature outside of the template as shown below:

Vue.component("foo", {
  template: "<div>{{item}}</div>",
  props: ["item"]
});

var app = new Vue({
  el: "#app",
  data: {
    background: "blue",
    items: ["a", "b", "c", "d"]
  },
  mounted: function() {
    var self = this;
    this.calculateBreakpoint();
    window.onresize = function(event) {
      self.calculateBreakpoint();
    };
  },
  methods: {
    calculateBreakpoint: function() {
      var mediaLibraryWidth = null;
      var elems = document.getElementsByClassName("app");
      for (var i = 0; i < elems.length; i++) {
        if (elems[i].offsetParent !== null) {
          console.log("elems[i]", elems[i]);
          mediaLibraryWidth = elems[i].offsetWidth;
          break;
        }
      }

      console.log("calculateBreakpoint", mediaLibraryWidth);

      if (mediaLibraryWidth > 956) {
        this.background = "red";
      } else if (mediaLibraryWidth < 957 && mediaLibraryWidth > 700) {
        this.background = "blue";
      } else {
        this.background = "green";
      }

      console.log("calculateBreakpoint", this.breakpoint);
    }
  }
});
.red {
  background: red;

}

.blue {
  background: blue;

}

.green {
  background: green;

}

.widget {
  margin: 10px;
  padding: 20px;
  width: 200px;
  font-weight: bold;
  font-size: 16px;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<div id="app" class="app"> 
  <foo v-for="item in items" :class="[background]" class="widget" :item="item"> 
</div> 

https://codepen.io/anon/pen/RVLrmG

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 activate a click event in Vue.js?

Hey there! I'm facing a situation where I have a button within the child component that emits an event when clicked. Is there a way to trigger this event when the parent component is mounted? Alternatively, is there another method to achieve this goal ...

Having trouble interpreting json with angularjs

Looking at the following code snippet, <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Dashboard</title> <!-- Libs --> <script src="angular.js"></script> ...

Exploring the Power of Asynchronous Operations with Await and Async in

I have a basic understanding of how to use await/async in Angular 2 with the following example: async getValueWithAsync() { const value = <number>await this.resolveAfter2Seconds(20); console.log(`async result: ${value}`); } In my Angular ...

When utilizing a Slick carousel with three slides and setting autoPlay to true, the slider-nav behaves as if there are five slides

I am currently using the Slick carousel plugin and I want to feature a display of 3 photos. The issue is that when I set slidesToShow=2, everything works perfectly fine, but when I try to set slidesToShow=3, which equals the total number of slides, the bot ...

Mesh object circling in the opposite direction of the displayed image

Working on replicating a Flash website using Three.JS and facing difficulty in achieving desired functionality. The goal is to create button images that orbit around the center of the screen, stop when hovered over by the mouse, and open a different locat ...

What is the best way to display the contents of a javascript file on the screen by using its URL?

I need help with displaying the contents of a JavaScript file from our CDN in the browser window. I have the technical details sorted out, but I'm struggling with how to actually show the file when its URL is entered. Any guidance or assistance would ...

Please be advised that the message is currently in the process of being typed

In my current setup, I am utilizing Laravel 5.6.7, Socket.IO, and vue.js while excluding Pusher and Redis. The following is the code snippet I am using to send messages directly to a user engaged in one-on-one chatting with me. var url = "http://localhost ...

Leveraging periods within a MySQL database: Node.js for seamless updates

I am currently facing a challenge in updating a column name that contains a period in node using node-mysql. I appreciate the convenience of being able to update multiple columns by providing an object with keys, but the string escaping process with node-m ...

ParsleyJS always seems to miss the mark when it comes to

I had previously sought advice on a different JavaScript/jQuery form validation library but was told it was outdated, so I switched to Parsley. While Parsley allowed me to make some progress, I still encountered issues with its functionality. Specifically, ...

Confirm the 'background-image' CSS URL with Cypress

Is it possible to verify the status code '200' of a CSS background-image URL using Cypress for image loading validation? Any suggestions on how to accomplish this? it('Validate displayed images',() => { cy.get('.logo'). ...

Invoking a class method in Javascriptcore on iOS

I'm currently trying to comprehend the inner workings of JavascriptCore. Initially, I attempted calling a single function. Now, my focus has shifted to invoking a function within a class. This is what my javascript code looks like: var sayHelloAlf ...

Tips for highlighting a button within a details list using React and Office Fabric

Does anyone have any tips on how to focus a button in React DetailsList? I've been considering using refs and attempting something like this: findDOMNode<HTMLButtonElement>(this.refs.mybutton).focus() However, I've encountered dif ...

Having trouble with your Angular routes tutorial?

I'm currently working on Google's Angular tutorial log (with different names for the necessary items), and I can't seem to get the routing to function correctly. If I remove the "#" from the hrefs, I end up with a "Cannot GET" error. But eve ...

"From time to time, reimport React when saving to ensure all necessary imports are

When working with TypeScript in *.tsx files, particularly when copying code around, I frequently encounter the issue of an additional import line being added. This can be seen below: import React from "react"; // ? On Save "editor ...

Vue.js Error: Attempting to access property 'product' on an undefined variable

I am struggling to integrate this product information: data() { return { sitename: 'Vue.js Pet Store', product: { id: 1001, title: 'Dog Treats, 5lb bag', description: 'A 5 pou ...

Receiving an unexpected error message related to Vuex in the watcher function, even though I am not utilizing Vuex in my N

My goal is to update an object property in an array [{ text: 'some text' value: 'some value, active: false }, etc..] from false to true when I click on a checkbox that is connected to a v-model: <v-col v-for="(item, i) in searchModul ...

Uploading CSV file in Angular to populate the scope rather than sending it to the server

I need assistance with allowing users to upload a CSV file, which will then be displayed and validated. Rather than uploading the file directly to the server, I would prefer to keep it within scope until validation is complete. Unfortunately, Angular 1.5. ...

Tips for verifying the functionality of your AngularJS controller and troubleshooting any potential issues

Testing my controller functionality has been a challenge. I attempted to use an alert function to check if the controller is working properly, but unfortunately, nothing seemed to happen. JS routerApp.controller('myCtrl', ["$scope", "$http", " ...

Leveraging Shared Workers within a React application

I am currently working on a backend app that continuously sends events to my React app through Web Sockets. One of the requirements is for a new browser tab to be opened when a specific event is received. However, since the application will be used by a si ...

Using document.getElementById will only target a single item

Essentially, I am facing an issue where the document.getElementById() function only works for the first product when I click on the addToBasket button. It always changes the details of the first product, even if I click on a different one. Is there a way ...