There is a possibility of encountering an endless update loop in the watcher when utilizing the expression "tabs" error in vue

My code includes a watcher on tabs to prevent them from changing based on the values of the edit. If edit is false, then go to the next tab; otherwise, prevent the change. However, when I try to click on the tab heading to change the tab, I encounter an error mentioning "You may have an infinite update loop in watcher with expression 'tabs'". This issue is occurring due to the custom events changes_event and changes_cancel being sent to the parent from the child component.

I need assistance in identifying where I am making a mistake.

<template>
  <v-layout row wrap>
    <v-flex xs12 sm12 lg12>
      <div>
        <v-tabs v-model="tabs">
          <v-tab href="#information">INFORMATION</v-tab>
          <v-tab href="#details">DETAILS</v-tab>
          <v-tab href="#services">SERVICES</v-tab>
          <v-tab-item value="#information" v-on:changes_event="alertMessage" v-on:changes_cancel="alertPhone" id="information">
            <Information />
          </v-tab-item>
          <v-tab-item value="#details" v-on:changes_event="alertMessage" v-on:changes_cancel="alertPhone" id="details">
            <Details />
          </v-tab-item>
          <v-tab-item value="#services" v-on:changes_event="alertMessage" v-on:changes_cancel="alertPhone" id="services">
            <Services />
          </v-tab-item>
        </v-tabs>
      </div>
    </v-flex>
  </v-layout>
</template>
import Information from 'views/information/edit.vue';
import Details from 'views/details/edit.vue';
import Services from 'views/services/edit.vue';

export default {
  components: {
    Information,
    Details,
    Services,
  },
  data: function() {
    return {
      tabs: 'information',
      edit: false
    }
  },
  watch: {
    tabs(newVal, oldVal) {
      if (this.edit) {
        this.tabs = oldVal
      } else {
        this.tabs = newVal
      }
    }
  },
  methods: {
    alertMessage() {
      this.edit = true;
    },
    alertPhone() {
      this.edit = false
    }
  }
}

Answer №1

For instance, let's say the initial value for this.tabs='1'. If this.edit is set to true and this.tabs='11', then the newVal of the watch will be '11' and the oldVal will be '1'. In this scenario, this.tabs will revert to this.tabs='1' because of the condition where this.edit is true. Consequently, with newVal='1' and oldVal='11', it will lead to an infinite loop.

Vue.config.productionTip = false
new Vue ({
  el:'#app',
  data () {
      return {
        tabs: '1',
        edit: true
      }
  },
  watch: {
    tabs: function (newVal, oldVal) {
      console.log(newVal, oldVal)
      if (this.edit) this.tabs = oldVal
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
    <div>
        <div>
            <input type="text" value="A" v-model="tabs">
        </div>
        <pre>{{tabs}}</pre>
    </div>
</div>

A possible solution would be to utilize the setter of a computed property.

Vue.config.productionTip = false
new Vue ({
  el:'#app',
  data () {
      return {
        tabs: '1',
        edit: true,
        tabsCopy: this.tabs
      }
  },
  computed: {
    myTabs: {
      get: function () {
        return this.tabs
      },
      set: function (newVal) {
        if (this.edit) {
          this.$forceUpdate()
          return
        }
        this.tabs= newVal
      }
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
    <div>
        <div>
            <input type="checkbox" v-model="edit">
            <input type="text" v-model="myTabs">
        </div>
    </div>
</div>

Another approach is to perform the validation in @input.

Vue.config.productionTip = false
new Vue ({
  el:'#app',
  data () {
      return {
        tabs: '1',
        edit: true,
        tabsCopy: this.tabs
      }
  },
  methods: {
    changeValue: function (newVal) {
      if(this.edit) { this.$forceUpdate(); return}
      this.tabs = newVal.target.value
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
    <div>
        <div>
            <input type="checkbox" v-model="edit">
            <input type="text" :value="tabs" @input="changeValue($event)">
        </div>
    </div>
</div>

An inferior workaround involves using a data property to check if newVal matches it, and if so, return immediately.

In any case, using a watch to determine whether its object needs to be changed or not is not advisable.

Therefore, utilizing the setter of a computed property solution would be a more suitable option.

Vue.config.productionTip = false
new Vue ({
  el:'#app',
  data () {
      return {
        tabs: '1',
        edit: true,
        tabsCopy: this.tabs
      }
  },
  watch: {
    tabs: function (newVal, oldVal) {
      if (newVal == this.tabsCopy) return
      if (this.edit) {
        this.tabs = oldVal
        this.tabsCopy = this.tabs
      }
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
    <div>
        <div>
            <input type="checkbox" v-model="edit">
            <input type="text" v-model="tabs">
        </div>
    </div>
</div>

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 am unable to retrieve images using the querySelector method

Trying to target all images using JavaScript, here is the code: HTML : <div class="container"> <img src="Coca.jpg" class="imgg"> <img src="Water.jpg" class="imgg"> <img src="Tree.jpg" class="imgg"> <img src="Alien.jpg" class=" ...

Can you explain how to create a function in Angular that accepts a number as an argument and then returns the square of that number?

I am working with an array of numbers and I want to show each number in the list along with its square value. To do this, I need to create a function that takes a number as input and returns its square as output. Here is what I have attempted so far: co ...

Navigating the process of passing data in a VueJS 2 application

As a newcomer to VueJS 2, I'm seeking feedback on my current approach. My system involves uploading files containing data that is used to generate charts. As such, I display the uploaded files for users. <tr v-for="file in files.data" :key="file.i ...

Can anyone guide me on troubleshooting the firebase import error in order to resolve it? The error message I am encountering is "Module not found: Error:

When attempting to import the 'auth' module from my 'firebase.js' file, I encountered an error. I used the code import {auth} from "./firebase", which resulted in the following error message: Error: Unable to locate module &a ...

Interactive image sliders in a Netflix-inspired style with live previews on hover, fully compatible with Bootstrap framework

I'm looking for suggestions on Twitter Bootstrap compatible jquery plugins that can create a Netflix-style continuously scrolling image carousel with mouse-over functionality. I've tried the carousel included in the Bootstrap JS library, but it r ...

Preventing Excessive Event Triggering in a PhoneGap - Jquerymobile Application

I've created an application using a combination of Phonegap and JqueryMobile. So far, this app has accumulated approximately 15,000 downloads across iOS, Android, and iPhone platforms. Surprisingly, the code remains consistent across all versions. P ...

Guide on comparing an object against an array and retrieving a specific output

If I were to create a data structure like this: const carObj = {"1234":"Corvette","4321":"Subaru","8891":"Volvo"}; And also have an array that contains the IDs: const myArray = [1234, 4321, 8891, ...

What could be causing the HelloWorld program in AngularJS to malfunction?

To access the codes, you can visit http://jsfiddle.net/hh1mye5b/1/ Alternatively, you can refer to: <!doctype html> <html ng-app="dcApp"> <head> </head> <body> <div> <div ng-controller="SpeciesController"> ...

If the socket cannot be found, an error callback will be activated

Below is the method I am using to send a message to a targeted socket connection. socket.broadcast.to(socketid).emit('message', JSON.stringify(data)); If the specified "socketid" does not exist, is there a mechanism in place to capture the erro ...

Unable to retrieve the text enclosed between the:: before and after the:: marker

I attempted this using the XPATH finder in Chrome, and it highlighted the element. However, when running my Selenium script, I received the following error: Caused by: org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: ...

How to activate PurgeCSS for external CSS sources

I have integrated the @mdi/font into my project built with Nuxt for server-side rendering (SSR). Is there a way to enable purgeCSS specifically for the CSS coming from @mdi/font? nuxt.config.js module.exports = { css: [ '@/assets/scss/a ...

Import objects into THREE.js using OBJLoader, convert to Geometry, apply transformations, and finally convert to BufferGeometry

Trying to figure out why the geometry loaded with OBJLoader cannot be smoothly shaded. var loader = new THREE.OBJLoader(manager); loader.load('/manmodel/js/man.obj', function (object, materials) { console.log(object); console.log(materia ...

Adding elements to a multi-dimensional array that match elements from another array

I am working with two arrays: a = [ [a, b], [c, d], [e, f], [g, h] ] b = [ [a, 4], [1, 2], [e, 3] ] My challenge lies in updating the elements of array a when they match corresponding elements in array b. Specifically, I need to add a new ...

What methods are available for implementing hover effects within attributes using a JavaScript object?

const customPanelStyle = { 'background-color': 'red', 'border': '1px solid green', ':hover'{ 'background': 'blue' } } class some extends React.Component{ rende ...

Changing a property of an object in Angular using a dynamic variable

It seems like I may be overlooking a crucial aspect of Angular rendering and assignment. I was under the impression that when a variable is updated within a controller's scope, any related areas would automatically be re-evaluated. However, this doesn ...

Encase all jQuery functionalities within a custom class

I am looking to create a JavaScript class that encapsulates jQuery's DOM functions, but I want these functions to only interact with a single property of that class. class Foo { constructor() { this.$wrapper = $('<div>wrapper</div ...

What steps do I need to take to extract the date and month from a single datepicker using the code below?

<div class="col-md-3 pull-left" style="padding:9px"> <input type="text" id="datepicker" class="form-control"> </div> The HTML and C ...

What is the best way to locate this particular element on the webpage?

After using the right-click and selecting inspect element, I located the code of the desired element on the webpage: <input type="text" ng-if="!editing" ng-model="item.Price" ng-click="inputFocus()" ts="" required="" placeholder="قیمت :" class="ng- ...

How can I create a JSON string that exactly matches the data source needed for a pie chart? Any tips

received JSON string: "{Date:'15/05/2015',y:'6'}, {Date:'01/08/2015',y:'6'}, {Date:'02/08/2015',y:'6'}, {Date:'08/08/2015',y:'72'}, {Date:'09/08/2015',y:&apo ...

What is the best way to insert a two-worded value into the value attribute of an input tag using Express-Handlebars?

Currently, I am using the code below to render the handlebars page: router.get("/update", function(req, res) { mysql.pool.query("SELECT * FROM workouts WHERE id = ?",[req.query.id], function(err, rows, fields) { if (err) { c ...