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