google / incremental-dom

An in-place DOM diffing library
http://google.github.io/incremental-dom/
Apache License 2.0
3.54k stars 180 forks source link

Create function loses content #429

Closed dy closed 5 years ago

dy commented 5 years ago

Elements, created via constructor in elementOpen or elementVoid, lose their text/content:

import { elementVoid, patch } from "incremental-dom";

function render() {
  elementVoid(foo);
}
function foo() {
  let foo = document.createElement("div");
  foo.innerHTML = "foo";
  return foo;
}

let el = document.createElement("div");
patch(el, render);

console.log(el.textContent) // '' 

Open in Sandbox.

Is that expected behavior?

sparhami commented 5 years ago

Since textContent is really a child Text node, it is cleared by elementClose / elementVoid, since those see that there is a child present that was not declared in the render function. The skip() function can be used to tell Incremental DOM to skip over the children instead of removing them. Adjusting the example above, this would look like:

import { elementOpen, elementClose, skip, patch } from "incremental-dom";

function render() {
  elementOpen(foo);
  skip();
  elementClose(foo);
}
function foo() {
  let foo = document.createElement("div");
  foo.innerHTML = "foo";
  return foo;
}

let el = document.createElement("div");
patch(el, render);

console.log(el.textContent)

Another option, if the browsers you need support have it, is to look into using Shadow DOM.

import { elementVoid, patch } from "incremental-dom";

function render() {
  elementVoid(foo);
}
function foo() {
  const foo = document.createElement("div");
  const sr = foo.attachShadow({mode: 'open'});
  sr.appendChild(document.createTextNode('foo'));
  return foo;
}

let el = document.createElement("div");
patch(el, render);

// Note, since the text is in the Shadow Root, it is not `textContent`
dy commented 5 years ago

Thank you. That's exhaustive answer.