Compare two objects in Vue js and eliminate any discrepancies in the watcher

Here is the data I am working with:

data() {
  return {
    currentStore: this.store,
    brands: [],
  }
},

Utilizing v-select component:

<v-select
    v-model="currentStore.brands.data"
    :options="allBrands"
    :taggable="true"
    :multiple="true"
/>

There is a watcher set up for an object resembling this (this.newVal):

brands:Object
 data:Array[1]
  0:Object
    name:"3T"
 data:Array[1]
  0:Object
    name:"abc"

The goal is to compare it with another object (this.allBrands)

allBrands:Array[254]
  0:Object
    name:"3T"
  1:Object
    name:"Achielle"

The objective is to remove any entries from the first object that are not present in the second, like removing "abc" and keeping only "3T".

Object.keys(newVal).forEach(function(key) {
    console.log(Object.values(this.allBrands).includes(newVal[key].name));
});


watch: {
  "store.brands.data": function (newVal, oldVal) {
    console.log(this.allBrands);
    console.log(newVal);

    Object.keys(newVal).forEach(function(key) {
      console.log(Object.values(this.allBrands).includes(newVal[key].name));
    });
  }
},

An error is encountered:

"TypeError: Cannot read property 'allBrands' of undefined"

The desired outcome for store.brands.data is:

brands:Object
 data:Array[1]
  0:Object
    name:"3T"

since it matches one of the items in this.allBrands.

EDIT

Object.keys(newVal).forEach((key) => {
    if (!Object.values(this.allBrands).includes(newVal[key].name)) {
        newVal.pop();
    }
});

This results in an error that needs further investigation:

Error in callback for watcher "store.brands.data": "TypeError: Cannot read property 'name' of undefined"

Answer №1

It appears that there is an error related to the undefined value of this, which your method cannot locate within the vue instance.

The issue lies in the binding of this to your function. Using an arrow fn can lexically bind this.

watch: {
  "store.brands.data": function (newVal, oldVal) {
    console.log(this.allBrands);
    console.log(newVal);

When updating or deleting a property from a vue object, it is recommended to use delete. Reference: https://v2.vuejs.org/v2/api/#Vue-delete

    Object.keys(newVal).forEach((key) => {
      console.log(Object.values(this.allBrands).includes(newVal[key].name));
    });
  }
},

Answer №2

As mentioned by @Satyam Pathak, the initial error was due to a binding issue that can be resolved in various ways. However, the most modern approach is to utilize arrow functions.

// Implementing an arrow function

watch: {
  "store.brands.data": (newVal, oldVal) => { // using arrow functions consistently
    console.log(this.allBrands);
    console.log(newVal);

    Object.keys(newVal).forEach((key) => { // using an arrow function to maintain context
      console.log(Object.values(this.allBrands).includes(newVal[key].name));
    });
  }
},


// Utilizing a constant to retain parent context

watch: {
  "store.brands.data": function (newVal, oldVal) {
    const self = this;

    Object.keys(newVal).forEach(function(key) {
      console.log(Object.values(self.allBrands).includes(newVal[key].name));
    });
  }
},

// Binding the function to ensure it's connected to the parent context
watch: {
  "store.brands.data": function (newVal, oldVal) {
    Object.keys(newVal).forEach(function(key) {
      console.log(Object.values(this.allBrands).includes(newVal[key].name));
    }.bind(this));
  }
},

Regarding the second issue, if newVal appears as shown below

brands:Object
 data:Array[1]
  0:Object
    name:"3T"
 data:Array[1]
  0:Object
    name:"abc"

The cause of the error

"TypeError: Cannot read property 'name' of undefined"
lies in the fact that

Object.keys(newVal) returns "data", and newValue.data returns an array with object a.

Hence, newVal.data.name will trigger an error. One solution would be to iterate through each array, although it's not the most optimal method.

I've brainstormed numerous solutions for this issue, but they all involve multiple for-loops which are inefficient and not recommended. It goes against good coding practices.

Consider simplifying the data structure of newVal. For example, instead of an object of arrays, could it be transformed into an array of objects?

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 it expected to conceal children who are 2 years old?

I came across the following HTML code snippet: <ul id="product_create-header" class="stepy-header"> <li id="product_create-head-0" class="stepy-active"> <div>Categoría</div><span>Categoría</span> </ ...

If the item with the specified name is not found in the list, display an image using Vue's v-if directive

<ul class="ulItems" v-for="item in listingItems" :key="item.channels"> <li class="liItems"> {{ item.itemName }} </li> </ul> I am looking to incorporate an image in situations where th ...

Unable to display scrollbar when generating dynamic content with jquery ajax

I have a jQuery report where I am generating dynamic HTML content (nested divs, span, label) using JSON. The report utilizes jQuery, mCustomScrollbar, commons, and jQueryUI. When I have a <div>...//some static code </div>, everything works per ...

Sharing node_modules via Npm and ensuring the package.json is correctly mapped

I have a dilemma with two projects, one serving as a server and the other as a client. They share very similar dependencies, making it tedious to set up shared dependencies without manual file editing or installing everything twice. The issue is exacerbate ...

Unveiling Insights from a JSON File: Data Extraction

I have a JSON file named pio2.json that contains the following data: { "controles":[{ "chart":[{ "type":"columns", "title":"Pollitos" }], "datos":[{"key":"Math","value":98}, {"key":"Physics" ...

Encountered a problem when injecting the angularjs $location service

I'm having some trouble getting the $location service to work in this code snippet: <script type="text/javascript> var $injector = angular.injector(['ng', 'kinvey', 'app.constants']); $in ...

Line breaks in Vue v-tooltip functionality

Currently, I am implementing v-tooltip to add tooltip text to a button. My aim is to include a line break within the tooltip text, but I have been unable to determine if this is feasible using this method. After reviewing the documentation, I did not find ...

Guide on uploading a file to Pinata directly from a React application

I keep encountering the 'MODULE_NOT_FOUND' console error code. Displayed below is the complete console error: > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3f4b4d564b5a4d4d5e4c1251505b5a7f0e110f110f">[email& ...

Inconsistent Animation Issue with jQuery Toggle for Expanding Div and Text

My expanding div functionality is almost perfect, but I've noticed that the transition when opening abruptly on divs with text. However, the closing transition is smooth. Can anyone help me make the opening transition as smooth as the closing one? Bel ...

Automatically generate a tree view using Lodash

Is there a way to automatically generate a tree view for my React component based on the paths of multiple files? For example: com/company/model/Main.java com/company/controller/Move.java com/company/controller/Rotate.java com/company/view/Watch.java Th ...

Javascript keycode used to target the element when a key is pressed

In my current project, I am utilizing a code snippet to attach a KeyDown event handler to any element within the HTML form. for(var i=0;i<ele.length;i++) { ele[i].onkeydown = function() { alert('onkeydown'); } } I am ...

Mapping prop passed to client component in NEXT 13: A step-by-step guide

Hello, I'm currently navigating through the Next 13 APP directory and have encountered a scenario where everything functions smoothly when I integrate the server component as shown below: const Tasks = async () => { const { tasks } = await getAll ...

Looking for giphy link within a v-for loop (Vue.js)

I am fetching a list of movie characters from my backend using axios and rendering them in Bootstrap cards. My objective is to search for the character's name on Giphy and use the obtained URL as the image source for each card. However, when I attemp ...

The ref.on() method fails to trigger a response from a function, despite producing the intended outcome

I've been working on developing an app called workspace. I previously asked a question, but I've made more additions to the features now. One of the new features is a remarks system. After experimenting with different versions of my code, the ver ...

Adjust the styling of the anchor tag within the selected div by utilizing jQuery

I am struggling with changing the color of a specific anchor tag when clicked inside a div with class .product_wishlist. Currently, all anchor tags within .pw div are changing colors. Is there a way to apply selected css only to the clicked element? Any he ...

Guide on executing a function exclusively when the state of a service variable changes within an Angular4 component

In my InfoFormService, I have a variable called isInValidating that is initially set to false. This variable becomes true when the component calls the validateEmail(email) function as shown below. @Injectable() export class InfoFormService { private ...

Using Vue.js to make an AJAX request to an API that returns a list in JSON format

I am attempting to utilize an AJAX call with the free API located at that returns a list in JSON format. My goal is to display the result on my HTML using Vue.js, but unfortunately, it doesn't seem to work as expected. This is my JavaScript code: va ...

Identify the location of the mouse and activate a specific function based

Tracking the x-coordinate of the mouse is crucial in this scenario. When the mouse approaches a specific threshold (250px) towards the left edge of the window, it should trigger the function "openNav." The function should close when the mouse moves away fr ...

retrieve a static method that returns an asynchronous value

Is there a way to have a static ES6 method in my code that simply returns a value instead of a promise? I'm looking for a solution to this problem: export default class Member { static existingMember() { var _existingMember; // DB.findExist ...

Scroll to the previous view with React

My task involves handling 10 lists of questions within a single multi-step form. I intend to address each question gradually, starting from the first one. Moreover, I aim to incorporate a feature where users can navigate back to the initial question by cl ...