How can Vue.js update the displayed information when the selection option changes?

Ensuring the total weight of the products remains accurate when changing the unit of measurement is essential. Currently, although the data in the array is being updated, these changes are only reflected on the screen after clicking on other input fields.

The table displays data from the array including Product name, net weight, and quantity. A select option allows users to choose the unit of measure - kg or grams, determining the units for "net weight" based on a conversion coefficient from another array.

Despite updating the data upon changing the unit of measure using the unitChange function, the screen fails to display these adjustments. Even attempting to implement a computed function did not solve the issue.

If you're experiencing this problem too, check your HTML code:

<tr v-for="(comp, i) in st">
 <td>{{comp.name}}</td>
  <td>
   <input v-model.number="comp.weight_netto">
  </td>
  <td>
   <select @change="unitChange($event.target.value, i)" v-model="comp.unit_id">
    <option v-for="val in ul" :value="val.unit_id" v-text="val.name" ></option>
   </select>
  </td>
  <td>
   <input v-model.number="comp.quantity">
  </td>
  <td>{{itemqty(i)}}</td>
 </tr>

To resolve this issue in your JavaScript code, make sure your methods are correctly defined:

methods: {
unitChange(value, i){
 for (var j=0; j<this.ul.length; j++){
  if (this.ul[j].unit_id==value){
  this.st[i].conversion_num=this.ul[j].conversion_num;
  break;
  }
 }
},
itemqty(i){
  return (this.st[i].weight_netto*this.st[i].quantity)/this.st[i].conversion_num;
 }
}

Answer №1

Avoid altering your product data!

Changing the units of your products can lead to inaccuracies due to rounding errors. Converting back and forth between different units will result in a value that is not the same as the original, as a result of the multiple roundings involved.
Furthermore, it adds complexity for you as you would need to consider the current unit every time you use the product.

A better approach would be to keep the weight and unit unchanged (in the unit preferred by you) and implement a method to interpret the displayed value based on the currently selected unit.

Your product data remains constant (with no changes to weight values or units).

Example:

Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
  el: '#app',
  data: () => ({
    products: [
      { id: 1, name: 'one', weight: 20},
      { id: 2, name: 'two', weight: 17}
    ],
    units: [
      {label: 'kgs'},
      {label: 'lbs', factor: 2.20462},
      {label: 'oz', factor: 35.274}
    ],
    currentUnit: {label: 'kgs'}
  }),
  methods: {
    convertToUnit(weight) {
      return (Math.round(weight * (this.currentUnit.factor || 1) * 100) / 100) +
        this.currentUnit.label
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  Current unit:
  <select v-model="currentUnit">
    <option v-for="(unit, key) in units" :value="unit" :key="key">{{ unit.label }}</option>
  </select>
  <div v-for="(product, k) in products" :key="k">
    name: <span v-text="product.name"></span>, 
    weight: <span v-text="convertToUnit(product.weight)"></span>
  </div>
</div>

Answer №2

Consider implementing Vue.set for optimal performance

It's also a good idea to refactor certain aspects of the code

For instance:

const table = Vue.component('product-table', {
  data() {
    return {
      products: [{
        name: 'one',
        weight_netto: 1.23,
        quantity: 4,
        conversion_num: .420,
        unit_id: 1
      },{
        name: 'two',
        weight_netto: 3.21,
        quantity: 5,
        conversion_num: .69,
        unit_id: 2
      }],
      units: [{
          unit_id: 1,
          conversion_num: .420,
          name: 'kg'
        },
        {
          unit_id: 2,
          conversion_num: .69,
          name: 'lb'
        }
      ]
    }
  },
  template: `
   <table>
    <tbody>
      <tr :key="product.name" v-for="product in products">
     <td>{{product.name}}</td>
      <td>
       <input v-model.number="product.weight_netto">
      </td>
      <td>
       <select @change="unitChange($event.target.value, product)" v-model="product.unit_id">
        <option :key="unit.unit_id" v-for="unit in units" :value="unit.unit_id" v-text="unit.name" ></option>
       </select>
      </td>
      <td>
       <input v-model.number="product.quantity">
      </td>
      <td>{{itemqty(product)}}</td>
     </tr>
    </tbody>
  </table>`,
  methods: {
    unitChange(unit_id, product) {
      unit_id = Number(unit_id);
      const { conversion_num } = this.units.find(pr => pr.unit_id === unit_id);
      Vue.set(product, 'conversion_num', conversion_num);
    },
    itemqty({ weight_netto, quantity, conversion_num}) {
      return ((weight_netto * quantity) / conversion_num).toFixed(2);
    }
  }
})

new Vue({
  el: '#container'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="container">
  <product-table>
  </product-table>
</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

Display the data returned from a computed property PromiseResult using VueJS

After calculating the property shown below, it will output res, which is a Promise object. The reason I cannot place this script inside the created() or mounted() hook is due to the fact that this.selectedObject is null at that time. I am satisfied with t ...

The presence of v-if does not depend on the model value to toggle the element

I have a scenario where I want to hide the dropdown menu for US states if a different country other than the US is selected. The code snippet I am using to achieve this functionality is shown below: <b-row v-for="demo in demographics" :key=&qu ...

What are your thoughts on utilizing for loops within the same function in Vue to organize fetched data?

Currently, I am implementing a fetch request to retrieve data from an API. The data is then converted to JSON format and I would like to organize it into separate categories. For instance, tickets with the status "active" should be placed in one array whil ...

Using Vue.js to make AJAX requests

I am facing an issue while trying to fetch data from an API endpoint api/data which returns an object. However, when I run my application, nothing shows up in the console and there are no XHR requests visible in the network tab. There are no warnings or er ...

Incorporate style elements dynamically using an array in Vue

My progress bar's width and color are determined by data from an array. The color of the bar changes based on the value of the data - grey if the progress is 0, blue if it's more than 0, and green if it's 100. <div class="card-item" v-fo ...

Media publications do not conform to the current trends

I'm currently utilizing the HTML-to-paper plugin to print my content on a printer. However, I've encountered an issue where it doesn't seem to apply any of the styles I've defined within @media print. The challenges I'm encounteri ...

Creating a Vue Canvas with Endless Grid Dots and a Dynamic Panning Feature

I'm currently focused on integrating a panning system into the canvas of my Vue application. Although I have successfully implemented the panning system, I am encountering difficulties in efficiently rendering an infinite grid of dots. Below is the c ...

Vue - Ways to securely integrate Firebase config data into main.js

Currently, I am utilizing firebase within a Vue application with the following configuration: var firebaseConfig = { apiKey: "", authDomain: "", databaseURL: "", projectId: "", storageBucket: "", appId: "", measurementId: " }; ...

Is there something lacking in my project.json while building with nuxtjs?

Issue detected in ./services/emailService.js Unable to locate module: Error: Unable to find '@/apis/adl/instance/EmailsApi' in I encountered this error while executing the nuxt build within a docker container or on certain CI/CD servers such a ...

Tips for retrieving the most recent number dynamically in a separate component without needing to refresh the page

Utilizing both the Helloworld and New components, we aim to store a value in localStorage using the former and display it using the latter. Despite attempts to retrieve this data via computed properties, the need for manual refreshing persists. To explore ...

error message about missing relative modules in vuejs webpack

I am working on a full-stack application using express and the default vue-webpack-boilerplate. The structure of my project is as follows: ├── client │   ├── build │   │   └── ... │   ├── config │   │   └ ...

Creating a file structure for JavaScript files in a Vue CLI project

When structuring my Vue CLI project, I'm struggling to find clear documentation on best practices. Currently, I have 10 modules each with an associated JS file. My approach so far involves organizing all the pages in my router.js within a views direc ...

The parameters in VueJS are malfunctioning on this webpage

I created my vue in an external file and included it at the bottom of my webpage, but I am encountering issues with its functionality. One specific problem arises when using v-model, resulting in a template error displayed on the page: Error compiling t ...

Issue arises when annotation is utilized in ChartJs, as the tooltip fails to appear

Upon hovering over a dot, only a blue line is displayed without showing a tooltip as expected below: Library Version: "chart.js": "^2.9.3", "chartjs-plugin-annotation": "^0.5.7" Actual : enter image descriptio ...

How can I test for equality with an array item using v-if in Vue.js?

Currently, I am facing a challenge in my Vue.js project where I need to determine if a number is equal to an element within an array. Here is the code snippet that I am working with: <div v-if="someValue != arrayElement"> // </div> I am st ...

The process of ensuring a component is able to watch for the router even when it is not within the router

I am facing an issue with setting v-if for an element to get a boolean value from a function when the router changes the URL. Here is the code snippet for my Header component: <template> <header class="wfm-header"> <div class=" ...

The Card Component from Core UI fails to appear in the Print Preview feature

I'm currently experimenting with the Card Component from the Core UI framework. However, I'm facing an issue where the color of the Card component and its associated icon do not appear in the Preview when trying to print the page. I attempted to ...

Tips for eliminating the ripple effect when clicking on a q-list item

I have managed to create a sleek sidebar with a curved edge that seamlessly integrates into the body of the page. However, I am struggling to remove the semi-transparent ripple effect that appears when clicking on a list item. The current effect clashes ...

[Vue warning]: The property "text" was accessed during rendering, however it is not defined on the current instance using Pug

Looking for some guidance from the Vue experts out there. I've recently started working with Vue and I'm attempting to create a view that verifies an email with a unique code after a user signs up. Right now, my view is set up but it's not c ...

Getting started with Vue.js Components

Being a newbie in the world of Vue.js, my question may seem quite basic. Bear with me, please. I've set up the components App.vue and Character.vue. My goal is to dynamically create characters and add them to an array in App.vue, then use Character.v ...