rs-tml/rstml

Allow struct initialzation syntax inside attribute

tachibanayui opened this issue · 2 comments

Currently, key-value attributes only allow valid Expr.

<div style=Style {height: "16vh"}>Hello</div>

Because a Style struct is expected here so it could be simplified to:

<div style={height: "16vh"}>Hello</div>
<!-- conform to jsx rules -->
<div style={{height: "16vh"}}>Hello</div>

Maybe we could extend KeyedAttributeValue to accept Block(NodeBlock) as another variant? This way #14 can be implemented (with a brace):

<Routes>
  <Route path="/" view={<Home/>}/>
  <Route path="/other" view={<Other>"children"</Other>} />
  <Route path="/*any" view={<>"just text"</>} />
</Routes>
vldm commented

@tachibanayui Hi.
I have answered to #49 .

But i want to touch on the use of nodes in position of arguments separately:
For my opinion it is making element less readable. With big amount of attributes you usually cant even tell where tag ends.

I understand the motivation behind - some users want to implement components with different view branches for different situations.

What do you think to instead of providing a way to put node-tree into attribute, give a way to move-out some of attributes into separate pseudo-elements ?

So instead of writing

<Routes>
  <Route path="/" view={<Home/>}/>
  <Route path="/other" view={<Other>"children"</Other>} />
  <Route path="/*any" view={<>"just text"</>} />
</Routes>

One could write:

<Routes>
  // find first child with "Component.*" syntax
  <Route path="/" >
    <Route.view>
        <Home/> 
    </Route.view> 
  </Route>
  // or on same node-tree level to make it shorter
  // find first sibling with "Component.*" syntax
  <Route path="/other" />
  <Route.view> <Other>"children"</Other> </Route.view>
  // keeping original  to compare
  <Route path="/*any" view={<>"just text"</>} />
</Routes>

My original intention is to implement support for transforming values in attribute value positions like the style attribute in the first example. After reading the doc.rs page, transform_block seems to solve my problem well, solve the technical problem using parse_tokens_with_ending.

About the readability issue, I used react and react-router-dom extensively so I might be biased but I think the syntax is somewhat readable especially if you format it.

<Route path="/users" view={
	<MyCustomComponent my_attr="my_value">
		<UserPage/>
	</MyCustomComponent>
} />

<Route path="/products" 
	extra_attrs="extra value here" 
	view={ 
		<ProductPage  
			my_attr_1="my_value" 
			my_attr_2="my_value" 
			my_attr_3="my_value" 
			my_attr_4="my_value" 
			my_attr_5="my_value" />
	}
	more_extra_args="" 
 />

What do you think to instead of providing a way to put node-tree into attribute, give a way to move-out some of attributes into separate pseudo-elements ?

.NET XAML format also uses this syntax to support element nodes inside attributes (properties in xaml) and IMO I also like this syntax. But parsing this syntax is harder for the end user because they have to look ahead inside its children's to find additional attributes and validate them. Also, it is a bit hard to understand the relationship between parent and child when both move-out attributes node and children node are used together, something like React Suspense:

<Suspense>
	<Suspense.fallback>
		<LoadingIndicator />
	</Suspense.fallback>
	<div>
		// Large lines of UI code
	</div>
</Suspense>

Original:

```rs
<Suspense fallback={<LoadingIndicator />} > 
	<div>
		// Large lines of UI code
	</div>
</Suspense>

But for your example specifically, breaking out attributes into sub-children nodes is better. However, the ability to transform code inside attribute value allows for more flexibility and parity between rsx and jsx