I’m writing a web app in which some contents are saved in a JavaScript object. The properties of the object can change at runtime, and I need to update the content of the element which display that property.
change data name:
<input id="text">
<button id="btn">change</button>
<div id="content"></div>
<script>
const search = document.getElementById('text');
const btn = document.getElementById('btn');
const div = document.getElementById('content');
const data = {
id: '1',
name: 'element name',
inStock: true
}
div.innerHTML = `
<div>id of the data: ${data.id}</div>
<div>name of the data: ${data.name}</div>
<div>is in stock: ${data.inStock}</div>
`
btn.addEventListener('click', () => {
console.log(data.name);
data.name = search.value;
console.log(data.name);
})
</script>
After clicking the button, I change the property of the object data
, and I would like to update the content of the div
, and get something like
id of the data: 1
name of the data: new element name
is in stock: true
By locking at the console I see that indeed the property of the object changes, but not the div
content.
I tried to solve this issue by replacing the child element
btn.addEventListener('click', () => {
const newDiv = document.createElement('div');
newDiv.className = 'name';
newDiv.innerHTML = `<div class="name">name of the data: ${data.name}</div>`;
div.replaceChild(newDiv, document.getElementsByClassName('name')[0]);
})
and it works as expected, but I was wondering if it could be done in a more elegant way.
I hope I made myself clear enough, otherwise please ask more in the comments and I will update the question 🙂
2
Answers
Instead of using a template, you can add the HTML to the page itself. And give each div an id and place an empty span in place of the content.
Then have a single function that takes the data as input and changes the HTML accordingly.
Then call that function on load and on click of the button.
Long story short you cant observe an object directly and have events for changes, react for example does it trough a setter function.
What you can do to be as clean as possible is to put all your html update code in a render function that receives an object, make a needUpdate function that compares the object value with the previous and if needed then call render, and use them to update the object or after doing that.
the render function you alleady have it, the trick might be in the needUpdate function, youu have 2 approach ways as I can see:
can iterate through object properties (using Object.entries) and set
them values to another object (aka lastValues), then you can do the
same but comparing currentValues[prop]===lastValues[prop] to know if
something changed, this is shallow because if the object eventually
have a property that is indeed an object with its own properties and
you change one of these, you wont notice since the object property is
still the same.
objects), you colud use JSON.stringify to generate a string
representation of all the hierarchy and compare it to the
JSON.stringify(lastValues), this way looks a lot simpler and polish
but at a cost os proccess that could outcome in hangs if you have a
lot of changes and a big object
Done this you will have to:
references on both objects.