What’s the best way to derive values from props? #639
-
In React it's very common to do something like: function MyComponent() {
const world = "World";
return <span>Hello {world}</span>
} My mental model for writing components is that a component is a function with its own context. But this is not valid with Templ: templ MyComponent() {
world := "World"
<span>Hello {world}</span>
} This makes it more difficult to derive values from props. I can't do this, for example: templ OrdersList(orders []Order) {
totalValue := 0
for _, order := range orders {
totalValue += order.Value
}
<span>Total: ${ strconv.Itoa(totalValue) }</span>
<ul>
for _, order := range orders {
<li>{order.OrderNumber}</li>
}
</ul>
} What is the most ergonomic way to derive values from props? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
After trying a few different things, I think this is a pattern I can work with: Define a templ component that will do the rendering: type OrdersListProps struct {
orders []Order
totalValue int
}
templ RenderOrdersList(props OrdersListProps) {
<span>Total: ${ strconv.Itoa(props.totalValue) }</span>
<ul>
for _, order := range props.orders {
<li>{ order.OrderNumber }</li>
}
</ul>
} The actual component, the one we will import in other components, is a regular function. Because it returns a // This is a regular function
func OrdersList(orders []Order) templ.Component {
totalValue := 0
for _, order := range orders {
totalValue += order.Value
}
return RenderOrdersList(OrdersListProps{orders, totalValue})
}
templ OrdersPage() {
<h1>Orders</h1>
// We can use the import syntax here!
@OrdersList(ctx.Value("orders").([]Order))
} Any thoughts on this approach? |
Beta Was this translation helpful? Give feedback.
-
Another alternative approach is to abuse if statements: func sumTotalValue(orders []Order) int {
totalValue := 0
for _, order := range orders {
totalValue += order.Value
}
return totalValue
}
templ OrdersList(orders []Order) {
if totalValue := sumTotalValue(orders); true {
<span>Total: ${ strconv.Itoa(totalValue) }</span>
<ul>
for _, order := range orders {
<li>{order.OrderNumber}</li>
}
</ul>
<div>And again: ${ strconv.Itoa(totalValue) }</div>
}
} Not the most fun to work with, but it works. I would much appreciate support for defining variables in template functions, but I understand being hesitant to introduce logic into the templates. |
Beta Was this translation helpful? Give feedback.
I like that this separates logic from the template itself, very nice approach.
Depending on your preferences you could also in this example just use a function to transform your model:
There is also this issue which may make things easier for you once resolved: #109