@@ -92,6 +92,16 @@ impl Parse for HtmlElement {
9292 //
9393 // For dynamic tags this is done at runtime!
9494 match name. to_ascii_lowercase_string ( ) . as_str ( ) {
95+ "textarea" => {
96+ return Err ( syn:: Error :: new_spanned (
97+ open. to_spanned ( ) ,
98+ "the tag `<textarea>` is a void element and cannot have children (hint: \
99+ to provide value to it, rewrite it as `<textarea value={x} />`. If you \
100+ wish to set the default value, rewrite it as `<textarea defaultvalue={x} \
101+ />`)",
102+ ) )
103+ }
104+
95105 "area" | "base" | "br" | "col" | "embed" | "hr" | "img" | "input" | "link"
96106 | "meta" | "param" | "source" | "track" | "wbr" => {
97107 return Err ( syn:: Error :: new_spanned (
@@ -100,8 +110,9 @@ impl Parse for HtmlElement {
100110 "the tag `<{name}>` is a void element and cannot have children (hint: \
101111 rewrite this as `<{name} />`)",
102112 ) ,
103- ) ) ;
113+ ) )
104114 }
115+
105116 _ => { }
106117 }
107118 }
@@ -156,23 +167,34 @@ impl ToTokens for HtmlElement {
156167 checked,
157168 listeners,
158169 special,
170+ defaultvalue,
159171 } = & props;
160172
161173 // attributes with special treatment
162174
163175 let node_ref = special. wrap_node_ref_attr ( ) ;
164176 let key = special. wrap_key_attr ( ) ;
165- let value = value
166- . as_ref ( )
167- . map ( |prop| wrap_attr_value ( prop. value . optimize_literals ( ) ) )
168- . unwrap_or ( quote ! { :: std:: option:: Option :: None } ) ;
169- let checked = checked
170- . as_ref ( )
171- . map ( |attr| {
172- let value = & attr. value ;
173- quote ! { :: std:: option:: Option :: Some ( #value ) }
174- } )
175- . unwrap_or ( quote ! { :: std:: option:: Option :: None } ) ;
177+ let value = || {
178+ value
179+ . as_ref ( )
180+ . map ( |prop| wrap_attr_value ( prop. value . optimize_literals ( ) ) )
181+ . unwrap_or ( quote ! { :: std:: option:: Option :: None } )
182+ } ;
183+ let checked = || {
184+ checked
185+ . as_ref ( )
186+ . map ( |attr| {
187+ let value = & attr. value ;
188+ quote ! { :: std:: option:: Option :: Some ( #value ) }
189+ } )
190+ . unwrap_or ( quote ! { :: std:: option:: Option :: None } )
191+ } ;
192+ let defaultvalue = || {
193+ defaultvalue
194+ . as_ref ( )
195+ . map ( |prop| wrap_attr_value ( prop. value . optimize_literals ( ) ) )
196+ . unwrap_or ( quote ! { :: std:: option:: Option :: None } )
197+ } ;
176198
177199 // other attributes
178200
@@ -360,6 +382,8 @@ impl ToTokens for HtmlElement {
360382 }
361383 let node = match & * name {
362384 "input" => {
385+ let value = value ( ) ;
386+ let checked = checked ( ) ;
363387 quote ! {
364388 :: std:: convert:: Into :: <:: yew:: virtual_dom:: VNode >:: into(
365389 :: yew:: virtual_dom:: VTag :: __new_input(
@@ -374,10 +398,13 @@ impl ToTokens for HtmlElement {
374398 }
375399 }
376400 "textarea" => {
401+ let value = value ( ) ;
402+ let defaultvalue = defaultvalue ( ) ;
377403 quote ! {
378404 :: std:: convert:: Into :: <:: yew:: virtual_dom:: VNode >:: into(
379405 :: yew:: virtual_dom:: VTag :: __new_textarea(
380406 #value,
407+ #defaultvalue,
381408 #node_ref,
382409 #key,
383410 #attributes,
@@ -439,6 +466,9 @@ impl ToTokens for HtmlElement {
439466 #[ cfg( not( nightly_yew) ) ]
440467 let invalid_void_tag_msg_start = "" ;
441468
469+ let value = value ( ) ;
470+ let checked = checked ( ) ;
471+ let defaultvalue = defaultvalue ( ) ;
442472 // this way we get a nice error message (with the correct span) when the expression
443473 // doesn't return a valid value
444474 quote_spanned ! { expr. span( ) => {
@@ -466,6 +496,7 @@ impl ToTokens for HtmlElement {
466496 _ if "textarea" . eq_ignore_ascii_case( :: std:: convert:: AsRef :: <:: std:: primitive:: str >:: as_ref( & #vtag_name) ) => {
467497 :: yew:: virtual_dom:: VTag :: __new_textarea(
468498 #value,
499+ #defaultvalue,
469500 #node_ref,
470501 #key,
471502 #attributes,
@@ -500,7 +531,7 @@ impl ToTokens for HtmlElement {
500531 :: std:: debug_assert!(
501532 !:: std:: matches!( #vtag. tag( ) . to_ascii_lowercase( ) . as_str( ) ,
502533 "area" | "base" | "br" | "col" | "embed" | "hr" | "img" | "input"
503- | "link" | "meta" | "param" | "source" | "track" | "wbr"
534+ | "link" | "meta" | "param" | "source" | "track" | "wbr" | "textarea"
504535 ) ,
505536 concat!( #invalid_void_tag_msg_start, "a dynamic tag tried to create a `<{0}>` tag with children. `<{0}>` is a void element which can't have any children." ) ,
506537 #vtag. tag( ) ,
0 commit comments