-
Notifications
You must be signed in to change notification settings - Fork 79
Support $component directive #300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Very cool!
|
|
Ah, @parsonsmatt I've updated the PR description. |
|
OK, that makes a lot of sense, thanks for clarifying! |
| it "supports $component with binding (modal example)" $ | ||
| let | ||
| modalWidget :: (ExampleModal (HtmlUrl url) -> HtmlUrl url) -> HtmlUrl url | ||
| modalWidget body = | ||
| let | ||
| exampleModal = | ||
| ExampleModal | ||
| { modalHeader = \content -> | ||
| [hamlet| | ||
| $newline never | ||
| <div class="modal-header"> | ||
| ^{content} | ||
| |], | ||
| modalContent = \content -> | ||
| [hamlet| | ||
| $newline never | ||
| <div class="modal-content"> | ||
| ^{content} | ||
| |] | ||
| } | ||
| in | ||
| [hamlet| | ||
| $newline never | ||
| <div class="modal"> | ||
| ^{body exampleModal} | ||
| |] | ||
| in | ||
| helper "<div class=\"modal\"><div class=\"modal-header\"><h1>This is the title</h1></div><div class=\"modal-content\"><p>This is the content</p></div></div><p>outside</p>" | ||
| [hamlet| | ||
| $newline never | ||
| $component modal <- modalWidget | ||
| $component modalHeader modal | ||
| <h1>This is the title | ||
|
|
||
| $component modalContent modal | ||
| <p>This is the content | ||
| <p>outside | ||
| |] | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another use-case that greatly simplifies and localises the development of Hamlet templates in our application is this pattern. Note how we pass down into the component how to render individual parts of the Modal.
Allowing us to abstract over components in ways that let's you assemble widgets and individual content while still being guided by a skeleton.
b048262 to
876efc6
Compare
|
Any chance I can pitch the idea to anybody for inclusion in shakespeare? Happy to hop on a calls or anything to spark the discussion. |
|
I think this is great and I'm in favor of inclusion. Could you update the changelog, write some documentation, and bump the version? Adding new constructors to the sum type is a breaking change, so it'll need to be a major version bump. |
|
Cool, thanks! For the documentation, where would I put it? Are we talking https://github.com/yesodweb/yesodweb.com-content? |
|
Hmmm, it is occurring to me that that is the only location with documentation on shakespeare! Yeah, let's get this merged and worry about docs later or in that repository. |
|
Sounds good! Before I do that, do you think $component is the name we should go with? I could imagine $widget or $view or $block as more or less fitting alternatives. |
|
I have no objection to component - it's a pretty common term for a reusable bit of template. Widget is a bit overloaded already in Yesod. |
|
Alright then! I will add the changelog and version and we should be good to go then. |
|
Alright, check out the changelog. |
|
Cool, I think we are good to go at this point. Anything that you would like to see from this PR? |
|
@parsonsmatt any last doubts getting this in? |
|
Sorry, nope - I'll merge and release. Thanks so much for getting this in! |
Hamlet already has ^{..} for embedding an existing Widget/Html value.
But it lacks a way to call a function with a captured block of template code. That’s where $component comes in.
^{..} — embed a value
Use when you already have a widget in scope:
This only works if header has already been constructed in Haskell.
$component — call a function with a block
Use when you want to invoke a function that takes a Widget argument, directly inside Hamlet:
Conceptually this desugars to:
Which can not be expressed today.