Allow returning <template> from view

This commit is contained in:
Greg Johnston 2022-11-13 15:58:49 -05:00
parent 876aa0f0f4
commit d4da7e0c25
5 changed files with 72 additions and 2 deletions

View file

@ -26,6 +26,7 @@ members = [
"examples/parent-child",
"examples/router",
"examples/todomvc",
"examples/view-tests",
# book
"docs/book/project/ch02_getting_started",

View file

@ -0,0 +1,14 @@
[package]
name = "view-tests"
version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos" }
console_log = "0.2"
log = "0.4"
console_error_panic_hook = "0.1.7"
[dev-dependencies]
wasm-bindgen-test = "0.3.0"

View file

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<link data-trunk rel="rust" data-wasm-opt="z"/>
</head>
<body></body>
</html>

View file

@ -0,0 +1,35 @@
use leptos::*;
pub fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to_body(|cx| view! { cx, <TemplateConsumer/> })
}
#[component]
fn TemplateConsumer(cx: Scope) -> Element {
let tpl = view! { cx, <TemplateExample/> };
let cloned_tpl = tpl
.unchecked_ref::<web_sys::HtmlTemplateElement>()
.content()
.clone_node_with_deep(true)
.expect("couldn't clone template node");
view! {
cx,
<div id="template">
<h1>"Template Consumer"</h1>
{cloned_tpl}
</div>
}
}
#[component]
fn TemplateExample(cx: Scope) -> Element {
view! {
cx,
<template>
<div>"Template contents"</div>
</template>
}
}

View file

@ -88,6 +88,7 @@ fn root_element_to_tokens(
&mut expressions,
true,
mode,
false
);
match mode {
@ -179,6 +180,7 @@ fn element_to_tokens(
expressions: &mut Vec<TokenStream>,
is_root_el: bool,
mode: Mode,
parent_is_template: bool,
) -> Ident {
// create this element
*next_el_id += 1;
@ -186,6 +188,7 @@ fn element_to_tokens(
// Open tag
let name_str = node.name.to_string();
let is_template = name_str.to_lowercase() == "template";
let span = node.name.span();
if mode == Mode::Ssr {
@ -288,6 +291,13 @@ fn element_to_tokens(
let #this_el_ident = #prev_sib.next_sibling().unwrap_throw();
//log::debug!("=> got {}", #this_el_ident.node_name());
}
} else if parent_is_template {
quote_spanned! {
span => let #this_el_ident = #debug_name;
//log::debug!("first_child ({})", #debug_name);
let #this_el_ident = #parent.unchecked_ref::<web_sys::HtmlTemplateElement>().content().first_child().unwrap_throw();
//log::debug!("=> got {}", #this_el_ident.node_name());
}
} else {
quote_spanned! {
span => let #this_el_ident = #debug_name;
@ -354,7 +364,8 @@ fn element_to_tokens(
expressions,
multi,
mode,
idx == 0
idx == 0,
is_template
);
prev_sib = match curr_id {
@ -606,7 +617,8 @@ fn child_to_tokens(
expressions: &mut Vec<TokenStream>,
multi: bool,
mode: Mode,
is_first_child: bool
is_first_child: bool,
parent_is_template: bool,
) -> PrevSibChange {
match node {
Node::Element(node) => {
@ -639,6 +651,7 @@ fn child_to_tokens(
expressions,
false,
mode,
parent_is_template
))
}
}