Eike
Eike
SSolidJS
Created by Eike on 12/1/2024 in #support
"Hydrate" custom HTML
I would like to make previously-static HTML interactive. As an example for what I want, suppose the server sends HTML like
<ul class="todo-list">
<li>Learn SolidJS</li>
<li>Create TODO-App</li>
<li>Get rich and famous</li>
</ul>
<ul class="todo-list">
<li>Learn SolidJS</li>
<li>Create TODO-App</li>
<li>Get rich and famous</li>
</ul>
I would like to make this interactive by: - Adding a "Done" button to each list item - Adding a list item with an empty textbox at the end to add additional todos to the list. Ideally, I don’t need to adapt the HTML. (The real case is more complicated, of course, but I’m relatively confident that I could take it from there.) I assume that I need to read in the existing list in some way to fill an internal data structure, then render it again using SolidJS, adding in the buttons and extra list item at the end. So far, I pass in the <ul> element into my component function, parse the list items and then call replaceChildren on the <ul> to get rid of the existing HTML. Then, I can return new <li> elements in a fragment that have the buttons and so on. Like so:
const App: Component<{root: Element}> = ({ root }) => {
let initialTodos: Array<string> = [];
Array.from(root.children).forEach(child => {
initialTodos.push(child.textContent || "")
})
const [todos, setTodos] = createSignal(initialTodos);
root.replaceChildren();
return <>
<For each={todos()}>
{(todo) => <li>{todo} <button>Done!</button></li>}
</For>
<li><input placeholder='Add a todo' /></li>
</>
};
const App: Component<{root: Element}> = ({ root }) => {
let initialTodos: Array<string> = [];
Array.from(root.children).forEach(child => {
initialTodos.push(child.textContent || "")
})
const [todos, setTodos] = createSignal(initialTodos);
root.replaceChildren();
return <>
<For each={todos()}>
{(todo) => <li>{todo} <button>Done!</button></li>}
</For>
<li><input placeholder='Add a todo' /></li>
</>
};
In then render this into the existing <ul class="todo-list">. Ideally this would work with the development server. However, when I change script and it live-reloads, it is easy to confuse Solid or your own code as it now runs on the previous iterations output instead of the list from the HTML. For example, here, every iteration will insert another "Done!" at the end of todo list items. Is there a better way?
8 replies