-
-
Notifications
You must be signed in to change notification settings - Fork 408
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
Sugar for multi-assignment with let
block helper
#602
Comments
I'm not sure this is a good idea because it ultimately beaks the consistency of template syntax, it perhaps makes new users getting confused about But let's assume this is an acceptable change, then I'm thinking a more intuitive solution as: {{!
1. not to introduce a new scoping semantic
2. declare variables like JS version `let`
3. use them as local variables
}}
{{#let
foo=(if cond valueA valueB)
bar=(some-helper arg1 arg2)
qux=(hash a=1 b=2)
}}
{{foo}}
{{bar}}
{{qux.a}} {{qux.b}}
{{/let}}
{{!
1. namespace is optional by using extra `as ||`
2. namespace will collect all local variables automatically, the user only need to name it
}}
{{#let
foo=(if cond valueA valueB)
bar=(some-helper arg1 arg2)
qux=(hash a=1 b=2)
as |context|}}
{{context.foo}}
{{context.bar}}
{{context.qux.a}} {{context.qux.b}}
{{/let}} This is enough for like 95% usage, and I have some more ideas around it: {{!
this.fetchedParams is an async task like what Promise.all or RSVP.hash did
and I'm always dreaming about the possibility of basic deconstruction
the as |...| part is optional
}}
{{#let |paramsA paramsB|=(await this.fetchedParams)}} as |promise|
{{#let
foo=(component (concat "custom-ui/" paramsA.name))
bar=(component (concat "custom-ui/" paramsB.name)) as |UI|
}}
<UI.foo /> and <UI.bar />
{{/let}}
{{else}}
{{!
render else block if this.fetchedParams rejected
I'm not sure this is possible or not for let helper
but since if/unless/each can have it, maybe let can have it.
I wish the let helper can automatically detect if there are any async operations
and use else block to handle the rejected promise
}}
<Common::ErrorMessage @message={{promise.message}} />
{{/let}} Okay, I know the second part is a bit impractical, it's just a rough idea came up suddenly when I saw this topic. Rational rejection is welcomed. 😝 |
I like the |
I agree with @nightire that this will be confusing to new users. Specifically they will not understand why they can't do similar things elsewhere, like:
even though it clearly doesn't make sense. |
@Gaurav0 I was actually thinking about that example in particular. I don't think it "clearly doesn't make sense". In fact, it intuitively looks like you're traversing two lists in parallel, which may or may not be useful, but it makes sense to me... I do agree that a better mental model for what this syntax means and where it can and cannot be used would be necessary. Still thinking about that. |
Just to throw another example in the ring, I think we could probably make something like this work: {{#let foo=(whatever) bar="something else" as |@bar @foo|}}
{{/let}} Basically allowing named arguments to be yielded and have them match the hash args not be positional at all. |
@rwjblue Liking your variation of this. Definitely an improvement over the current state. Do you envision this being syntactic sugar for destructuring block params in general? I.e. something like this would work: template.hbs {{#full-name firstName="Rob" lastName="Jackson" as |@fullName|}}
{{!-- ... --}}
{{/full-name}} full-name.hbs {{yield (hash fullName=(concat @firstName " " @lastName))}} Edit: |
What yielded argument would be destructed? The first argument? The first argument, which is an object? It's easier for helpers cause they can not return multiple arguments. |
@jelhan Yeah, I had this thought immediately after my reply haha. |
Leaving this open for now since it's part of the meta issue. |
Is there a path forward here? |
1 similar comment
This comment was marked as duplicate.
This comment was marked as duplicate.
Personally, I don't see this as a big issue, but I think that's because I hardly |
I suspect that at least some of the felt need for multi-item |
Using block
let
to assign multiple template variables quickly becomes a pain to read the more variables you want to assign, especially when you're assigning values derived from more complex expressions:This is already pretty painful to read and it's a simple toy example.
IMO the reason why this is painful to read is because there's cognitive overhead required to positionally map the values with the variable they're being assigned to. To fix this, I've seen the following pattern used:
This fixes the mental overhead of positional mapping, but it introduces the overhead of naming the hash of the variables as well as the overhead of having to grab those variables off the hash everywhere.
I propose the following syntactic sugar for multi-assignment with block
let
:This solves both of the issues with the current methods of multi-assignment: no mental positional mapping required and no hash overhead.
Another alternative proposal that solves the current issues with block
let
multi-assignment is the inlinelet
proposal (as implemented in ember-let). As discussed here, adding inlinelet
isn't as straight forward because it introduces new scoping semantics into the templating language, which may or may not be desirable. The advantage of the above syntactic sugar solution is that the semantics of the language remain the same.The text was updated successfully, but these errors were encountered: