Conversation
|
One challenge with using fragments in that they behave a little strangely when being added to the DOM. f = document.createDocumentFragment()
f.appendChild(document.createElement('p'))
f.childElementCount // => 1
document.body.appendChild(f)
f.childElementCount // => 0This means we no longer have a reference to the containing element so dynamic content won't work inside document fragments. A related feature that I've been thinking about adding is a way to register specific tags to arbitrary handlers. That way someone could register document fragments or other element constructors to take more control over customized behavior. Something like: ul
Item(@click @text)
span Neat!Jadelet.register
Item: ({click, text, children}) ->
el = document.createElement 'li'
el.onclick = click;
el.append(text, children...)
return elIt needs a bit more thought, especially around observable properties and content but I think there might be something to it. |
Can you show me an example of this? <!-- html -->
<div id="app"></div>
<ul id="list"></ul>o = Jadelet.Observable
t = Jadelet.exec
app = document.getElementById("app")
lst = document.getElementById("list")
tpl1 = t(`ul
li @a
li @b
li @c`)
tpl2 = t(`Fragment
li @a
li @b
li @c`)
x = o(1)
obj = {
a: o(() => x() + 1),
b: o(() => x() + 2),
c: o(() => x() + 3)
}
app.appendChild(tpl1(obj))
lst.appendChild(tpl2(obj))
/*
html result:
<div id="app">
<ul>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
<ul id="list">
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
*/
x(5)
/*
html result:
<div id="app">
<ul>
<li>6</li>
<li>7</li>
<li>8</li>
</ul>
</div>
<ul id="list">
<li>6</li>
<li>7</li>
<li>8</li>
</ul>
*/ |
|
Try this one: tpl = t(`Fragment
@a
li @b
li @c`) |
|
I've got the following result with the same HTML. tpl1 = t(`li @d`)
tpl2 = t(`Fragment
@a
li @b`)
x = o(1)
objA = {
d: o(() => x() + 1)
}
obj = {
a: o(() => tpl1(objA)),
b: o(() => x() + 2)
}
lst.appendChild(tpl2(obj))
/*
html result:
<div id="app"></div>
<ul id="list">
<li>2</li>
<li>3</li>
</ul>
*/
x(5)
/*
html result:
<div id="app"></div>
<ul id="list">
<li>6</li>
<li>7</li>
</ul>
*/So far, it looks like it's working. tpl3 = t(`ul
@a
li @b`)
app.appendChild(tpl3(obj))
/*
html result:
<div id="app">
<ul>
<li>6</li>
<li>7</li>
</ul>
</div>
<ul id="list">
<li>7</li>
</ul>
*/So, the I changed the HTML a bit to check if this is the issue with the <div id="app"></div>
<div id="app2"></div>app.appendChild(tpl3(obj))
/*
html result
<div id="app">
<ul>
<li>2</li>
<li>3</li>
</ul>
</div>
<div id="app2"></div>
*/
app2.appendChild(tpl3(obj))
/*
html result
<div id="app">
<ul>
<li>3</li>
</ul>
</div>
<div id="app2">
<ul>
<li>2</li>
<li>3</li>
</ul>
</div>
*/I thought this might be connected to the observable functions, so I tried the code without them, and the result is the same as above. objA = { d: x() + 1 }
obj = { a: tpl1(objA), b: x() + 2 }Even without the observables, the behavior stays the same. objA = { d: 1 }
obj = { a: tpl1(objA), b: 2 }Did I miss something in my code? |
|
I'm still not sure about the disappearing subtemplate, but here is the working example. o = Jadelet.Observable
t = Jadelet.exec
app = document.getElementById("app")
lst = document.getElementById("list")
x = o(1)
function objA() {
var tpl = t(`li @d`),
obj = {d: o(() => x() + 1)}
return tpl(obj)
}
function obj() {
return {
a: objA(),
b: o(() => x() + 2)
}
}
function elm1() {
var tpl = t(`ul
@a
li @b`)
return tpl(obj())
}
function elm2() {
var tpl = t(`Fragment
@a
li @b`)
return tpl(obj())
}
function test() {
app.appendChild(elm1())
lst.appendChild(elm2())
}
test()
/*
<div id="app">
<ul>
<li>2</li>
<li>3</li>
</ul>
</div>
<ul id="list">
<li>2</li>
<li>3</li>
</ul>
*/
x(5)
/*
<div id="app">
<ul>
<li>6</li>
<li>7</li>
</ul>
</div>
<ul id="list">
<li>6</li>
<li>7</li>
</ul>
*/ |
|
I've been thinking... There may be a way to do this by instead of tracking the parent node, to track the first child in a fragment and the number of sibling nodes added. This assumes that other nodes aren't inserted in between nodes controlled by Jadelet. In this case wrapping the entire template in a document fragment by default would allow for root level siblings and should still be able to handle reactively inserting/removing. One additional edge case would be to track the parent/previous sibling where the template is appended to the DOM to handle the case where zero nodes are added, or to insert a comment node as a placeholder. |
This PR adds support for a fragments.
Currently Jadelet requires a single root element (e.g., HTML element) in the template.
However, there are cases where HTML root element can be redundant, or might produce invalid HTML.
For example, there might be a case where we would like to output the content in the existing
<ul>element.With this PR, we would be able to use a (reserved) word "Fragment" or a symbol
<>in the template string.