I want to dynamically update my page based on HTML fragments that are rendered on the server. In a first simple approach I am simply fetching the fragments from the server and update the target via .innerHTML
.
Unfortunately this causes two problems (which are basically the same):
- When a user selects any text within the dynamic content, the selection will be cleared. Even, if the selected text did not change. This can be see in the example below: When selecting
foo
, it will be cleared after an update, but it does not actually change. - Any state that is attached to the elements gets deleted too. In particular the dynamic content of my page has some buttons which will show a loading indicator while the request is processing. It is okay for me, if the indicator is gone when the content changes, but the state being cleared every second makes the indicator useless.
My actual question is, whether there is an easy way to only update the elements that changed. Especially when when elements can be added, removed or reordered.
let counter = 0;
setInterval(() => {
counter++;
// assume this is fetched from the server
content = '<ul><li>foo</li><li>'+counter+'</li><li>bar</li></ul>';
document.getElementById("dynamic-content").innerHTML = content;
}, 1000);
<div>
<h1>my page</h1>
<div id="dynamic-content">
<ul>
<li>foo</li>
<li>0</li>
<li>bar</li>
</ul>
</div>
</div>
2
Answers
I found a simple library called idiomorph, which does pretty much what I want. Generally there are multiple library for this use case and they describe themselves as DOM "morphing" libraries.
So instead of
I just have to do
Additionally I have to put
id
tags on every element, but this is easy in my case.Depends upon what you want to replace, and knowing how to target that. Here I did a totally artificial example of a partial replacement.