Implementing Vue data binding with JavaScript objects

I have been tinkering with a JavaScript object that I want to connect with a Vue view.

When I trigger a function to update this JavaScript object using AJAX, I expected Vue to automatically sync up and refresh the view. However, it seems like the binding isn't happening as anticipated.

Some research advises making the AJAX call within the Vue declaration itself, but due to certain limitations, I am reluctant to take that route.

To showcase the problem more visually, I've put together a fiddle demonstrating the issue without the AJAX component. You can also find the relevant code posted below.

https://jsfiddle.net/g6u2tph7/5/

Thank you in advance for your assistance and insights.

Best regards,

vmitchell85

JavaScript

window.changeTheData = function (){
    externalJSSystems =  [{description: 'Baz'}, {description: 'Car'}];
    document.getElementById("log").innerHTML = 'function has ran...';
    // This doesn't update the Vue data

}

var externalJSSystems = [{description: 'Foo'}, {description: 'Bar'}];

Vue.component('systable', {
    template: '#sysTable-template',
    data() {
        return {
            systems: externalJSSystems
        };
    }
});
new Vue({
   el: 'body'
});

HTML

<systable :systems="systems"></systable>

<button type="button" onclick="changeTheData()">Change</button>
<br><br>
<div id="log"></div>
<template id="sysTable-template">
    <table>
        <thead>
            <tr>
                <th>Description</th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="sys in systems">
                <td>{{ sys.description }}</td>
            </tr>
        </tbody>
    </table>
</template>

Answer №1

Give this a try:

externalJSSystems.push({name: 'Foo'}, {name: 'Bar'});

This code snippet adds new objects to the externalJSSystems array and updates the view. Why might your previous attempt not be successful? It could be due to assigning a new reference of an Array to externalJSSystems, while Vue is still tracking the old one.

To accomplish what you intend, avoid creating a new instance of Array but instead clear it. Here's an example:

window.updateData = function (){
    externalJSSystems.length = 0
    externalJSSystems.push({name: 'Foo'}, {name: 'Bar'});
}

Answer №2

When the systable Component is created, Vue attaches an "Observer" class to the original externalJSSystems Array. This extends the prototype of the Array, adds getter/setters for each property, and maintains a two-way binding between the Component's data and the initial Array. However, the changeTheData() method overrides this Vue-modified Array with a new Array that lacks the Observer, thus breaking the two-way binding.

The reason why externalJSSystems.push( … ) still works is because the standard Array methods ('push', 'pop', 'shift', 'unshift', 'splice', 'sort', and 'reverse') have been modified to be handled by the Observer.

To achieve the desired behavior, focus on the Vue Component "props" — as seen in the component markup:

<systable :systems="systems"></systable>
. Currently, :systems="systems" does not do anything. By defining systems in the Parent Vue scope and setting it as a prop within the Component registration, dynamic data can be passed to Components within the Parent's scope.

Component

Vue.component('systable', {
  template: '#sysTable-template',
  props: {
    systems: Array
  }
});

Vue Instance

var vm = new Vue({
  el: 'body',
  data: {
    systems: externalJSSystems
  }
});

Check out the implementation in action through this fiddle: https://jsfiddle.net/itopizarro/ycr12dgw/

I stored the Vue instance — var vm = new Vue({ … }) — so that the changeTheData method could access its systems data. This allows the external changeTheData() method to reference the Vue instance where systems was defined, enabling modifications to the Array without replacing or iteratively altering items.

Answer №3

Instead of defining systems as a simple data property, consider making it a computed property for better efficiency. As mentioned in another response, the original object is being referenced. By transforming systems into a computed property, Vue will automatically monitor any variables used in its calculation (such as externalJSSystems) and update the computed property accordingly.

Vue.component('systable', {
template: '#sysTable-template',
computed: {
    systems() {
        return externalJSSystems;
    }
}
});

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

Switch out a character with its corresponding position in the alphabet

Starting out, this task seemed simple to me. However, every time I attempt to run the code on codewars, I keep getting an empty array. I'm reaching out in hopes that you can help me pinpoint the issue. function alphabetPosition(text) { text.split ...

The new mui v5 Dialog is having trouble accepting custom styled widths

I am facing an issue with my MUI v5 dialog where I cannot seem to set its width using the style() component. import { Dialog, DialogContent, DialogTitle, Paper, Typography, } from "@mui/material"; import { Close } from "@mui/icons- ...

[ElectronJS][VueJs] ERROR_OSSL_EVP_UNSUPPORTED

I am in the process of developing an Electron app with VueJs. Currently, I am following a tutorial available at : https://www.youtube.com/watch?v=LnRCX074VfA However, I have encountered a bug and I am unsure about its meaning... Here is the error message ...

Manipulating Arrays in JavaScript: Techniques for Extracting Values Buried in Nested Objects

I am working with an array of objects that contain multiple "Book" objects with dynamic keys. My goal is to filter the objects in the array to only include those that have at least one new "Book" object. For example: const arr = [ { id: '123&ap ...

modify an element using jquery

Hey there! I'm facing an issue where I have an ID of #item_quantity in a span, and I want it to refresh its contents once a button with the ID of #update_cart is clicked. It seems that everything else updates fine on click, but for some reason, the sp ...

Errors in Chartist.js Data Types

I am currently using the Chartist library to monitor various metrics for a website, but I have encountered some challenges with the plotting process. The main errors that are appearing include: TypeError: a.series.map is not a function TypeError: d.normal ...

What is the method for exporting data directly from an EC2 instance to a file, such as a .txt or .json file?

I tried exporting the security group rules from EC2 into a file, like .txt or .json, using javascript/node.js. However, my attempts were unsuccessful. I wrote a code to retrieve information about security groups (rules, ingress, egress, etc.) and save it ...

Utilizing ng-model to control the visibility of a label or anchor tag

Here is the code snippet I am working with: <div class="tabs DeliveryRightDiv"> <label class="selected"><a>One</a></label> <label> <a>Two</a> </label> <label> ...

Discover the method of connecting to a unique JavaScript trigger while utilizing IJavaScriptExecutor

In our web application, we have an event called timelineEventClicked that is created by a custom trigger. canvas.addEventListener('click', function (evt) { evt.stopImmediatePropagation(); var mousePos = ge ...

What is the best way to display a nested JSON object structure?

{ "Title": "Jurassic Park", "Year": "1993", "Rated": "PG-13", "Released": "11 Jun 1993", "Runtime": "127 min", "Genre": "Action, Adventure, Sci-Fi", "Director": "Steven Spielberg", "Writer": "Michael Crichton, David Koepp", "Actors": "Sam ...

end the node.js automated testing process

I'm currently using Jasmine and Zombie JS to create automated tests. I have integrated Drone.io for Continuous Integration, and the tests are executing successfully. However, there seems to be an issue where after passing the tests, the process does n ...

Tips for validation of Vuetify text field with asynchronous function?

Text fields in Vuetify come with a feature called rules, which can be used to add functions that return either true or an error message. Is it possible to make these rules asynchronous, allowing for server-side validation using XHR? For example: <v-te ...

What is the best method for distributing this array object?

I am faced with the task of spreading the following object: const info = [{ name: 'John', address: 'america', gender: 'Male', job: 'SE' }]; I want to spread this array object and achieve the following format: form:{ ...

Is there a way to incorporate an external JavaScript file into a .ts file without the need for conversion?

I have an external JavaScript file that I need to utilize in a .ts file without performing any conversion. Does anyone know how to use it within TypeScript without the need for conversion? ...

Learn the process of connecting checkboxes to a database in MeanStack using Angular

Hey everyone, I'm currently working with AngularJS ng-repeat and I am trying to dynamically bind a checkbox based on a true or false value from the database. However, even when the database value is set to true, the checkbox does not automatically che ...

Utilizing props to transfer data between components in ReactJS

I have a React application where I am binding text values when a specific div is clicked. However, I am now faced with the challenge of passing these text values to another component using props. This is what my code looks like: class PostOptionBar exten ...

The various sections of my website are neatly tucked away under one tab, only revealing themselves to users as they click on each individual tab

My recently published website is experiencing a strange issue. When the site loads, all contents including paragraphs and videos from other pages are displayed under one tab (the HOME tab). However, once any other tab is clicked, the issue fixes itself. Yo ...

Generate live references to interact with elements

I am facing a challenge in my vue app where I need to access a specific element, but there are multiple duplicate elements generated through a component. The issue is that the ref attribute only seems to work on the first component. How can I target a part ...

JavaScript: The function is encountering issues with properly formatting the numbers

I am currently facing an issue with a function I have created to format numbers for currency by inserting commas every 4 digits. The problem lies in the fact that the first 4 numbers do not have a comma added where it should be, and the formatting only wor ...

Unable to reset iframe style height in IE8 using JavaScript

I am encountering an issue with resetting the height of an iframe using JavaScript. Here is the code snippet I am working with: var urlpxExt = document.getElementById('urlPx'); urlpxExt.style.height = "200px"; While this approach works well in m ...