I’m trying to update a stringify HTML element with element from the DOM. This stringify HTML element is in an array in the localStorage.
First, here is how I convert it into manipulable HTML :
let toBeUpdated = document.createElement('div'); toBeUpdated.innerHTML = `${var_stringify_html_from_localstorage}`; toBeUpdated = toBeUpdated.firstElementChild;
This toBeUpdated
element is a div that contains, among other thing, an element with id updateMe
.
I want to update this “virtual” (not visible) #updateMe
element with the one from the DOM.
I tried first :
let updateme = toBeUpdated.querySelector("#updateMe"); let updateme_DOM = document.querySelector("#updateMe"); toBeUpdated.replaceChild(updateme, updateme_DOM);
Which returns Uncaught DOMException: Node.replaceChild: Child to be replaced is not a child of this node
And secondly I tried :
let updateme = toBeUpdated.querySelector("#updateMe"); let updateme_DOM = document.querySelector("#updateMe"); updateme.replaceWith(updateme_DOM);
Which removes the originale #updateMe
from the DOM and dosn’t update the toBeUpdated
element.
I’m obviously missing something, but I can’t see what…
I tried to reproduce as much as possible my situation :
//initial state of local storage let motd = ["<div id='toBeUpdated'><h1>Hello World</h1><p id='updateMe'>Message of tomorrow</p></div>"]; window.localStorage.setItem('motds', JSON.stringify(motd)); // My situation, later in the code let motds = JSON.parse(window.localStorage.getItem('motds')); let toBeUpdated = document.createElement('div'); toBeUpdated.innerHTML = `${motds[0]}`; toBeUpdated = toBeUpdated.firstElementChild; // this is the div#toBeUpdated let DOMUpdateMe = document.getElementById('updateMe'); let storageUpdateMe = toBeUpdated.querySelector("#updateMe"); // getElementById doesn't work here // Replace storageUpdateMe.replaceWith(DOMUpdateMe); // Back in local storage motds[0] = toBeUpdated.outerHTML; window.localStorage.setItem('motds', JSON.stringify(motds));
<body> <div id="toBeUpdated"> <h1>Hello World</h1> <p id="updateMe">Message of tomorrow</p> </div> </body>
Advertisement
Answer
It seems the only thing you’re missing is cloning the DOM node before inserting it into the non-DOM.
Here’s a step-by-step reproduction of your code changing only this, that works. I also set the initial state of localStorage
to “Message of today” for clarity.
localStorage
is emulated with variables, as it triggers a security error inside snippet due to CORS
//initial state of local storage let motd = ["<div id='toBeUpdated'><h1>Hello World</h1><p id='updateMe'>Message of today</p></div>"]; //window.localStorage.setItem('motds', JSON.stringify(motd)); //Read from local storage //let motds = JSON.parse(window.localStorage.getItem('motds')); const motds = JSON.parse(JSON.stringify(motd)); //Simulate local storage console.log("In storage:", motds); //Create element outside of DOM const toBeUpdated = document.createElement('div'); toBeUpdated.innerHTML = motds[0]; console.log("To be updated:", toBeUpdated.outerHTML); //Get part to update const DOMUpdateMe = document.getElementById('updateMe'); const storageUpdateMe = toBeUpdated.querySelector("#updateMe"); console.log(DOMUpdateMe, storageUpdateMe); //Replace part outside of DOM with clone of part from DOM storageUpdateMe.replaceWith(DOMUpdateMe.cloneNode(true)); console.log(toBeUpdated.outerHTML); //Store back motds[0] = toBeUpdated.outerHTML; motd = JSON.stringify(motds); //Simulate local storage console.log(motd); //window.localStorage.setItem('motds', JSON.stringify(motds));
<body> <div id="toBeUpdated"> <h1>Hello World</h1> <p id="updateMe">Message of tomorrow</p> </div> </body>