Skip to content
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

Let block for "the rest of the template" #520

Closed
mehulkar opened this issue Jul 29, 2019 · 22 comments
Closed

Let block for "the rest of the template" #520

mehulkar opened this issue Jul 29, 2019 · 22 comments

Comments

@mehulkar
Copy link
Contributor

I don't know if this is technically feasible, but it would be nice to put values into scope for the entire template. Something like let block, without having to close the tag. The use case is to instantiate N components.

currently

{{#let (component "foo-bar") as |FooBar|}}
  {{#let (component "baz") as |Baz|}}
    <FooBar />
    <Bar />
  {{/let}}
{{/let}}

after

{{let (component "foo-bar") as |FooBar|}}
{{let (component "baz") as |Baz|}}

<FooBar />
<Bar />

If I understand correctly, each component template has its own scope, so it should be possible to have a syntax that allows you to put something in scope for the whole template. Some of this may also interplay with #454 (template import primitives) as that syntax does something similar.

@kellyselden
Copy link
Member

What about

<FooBar />

{{let (component "foo-bar") as |FooBar|}}

or

<div>
  {{let (component "foo-bar") as |FooBar|}}
</div>

<FooBar />

@mehulkar
Copy link
Contributor Author

I’d be fine with a directive that makes it available in the whole template, as well as something that makes it available below the directive. Whichever makes more sense / easier to achieve. Mostly, I think the nesting lets doesn’t quite convey the intention in my use case, since the lets are meant to be siblings, not parent/child.

@davewasmer
Copy link
Contributor

@mehulkar you might be interested in ember-template-component-import

@mehulkar
Copy link
Contributor Author

@davewasmer thanks! The implementation of that addon might be helpful! But I'm not specifically looking to put a component in scope (although that is my said use case), I'm wanting to put any let evaluation into scope.

That said, this is purely for DevX, so I would probably never implement it as a custom thing if it wasn't in the framework.

@mmun
Copy link
Member

mmun commented Jul 30, 2019

https://github.com/thefrontside/ember-let implements "rest of the block" semantics, e.g.

{{#if person.isActive}}
  <div>
    {{let name=person.name}}
    <span>{{name}}</span>
  </div>
  {{!-- The name binding is not accessible here... --}}
{{/if}}
{{!-- ...or here. -- }}

Copy link
Member

rwjblue commented Jul 30, 2019

What @mmun said, also we have generally called this form “inline let” (you can see it mentioned in the original let RFC IIRC).

@mehulkar
Copy link
Contributor Author

Oh awesome, thanks for that those references! (For others looking, here's the link: https://emberjs.github.io/rfcs/0286-block-let-template-helper.html#inline-form).

Going to read through #286 before saying more. It seems like a good amount of discussion has already happened.

@mmun
Copy link
Member

mmun commented Jul 30, 2019

I'm still a fan of the feature and encourage you to push on it more :)

@locks
Copy link
Contributor

locks commented Aug 1, 2019

I think most of the work here would be defining the scope semantics of inline let. Draft it up!

@mehulkar
Copy link
Contributor Author

Since this is already available as an addon and it's just ergonomics, I'm not too motivated to pursue this. Closing down.

@runspired
Copy link
Contributor

I'd also note that one reason many folks being looking for "inline let" is due to rightward creep when multiple lets are needed. FWIW this can sometimes be solved using block-form let with multiple positional params:

{{#let (component "foo-bar") (component "baz") as |FooBar Baz|}}
  <FooBar />
  <Bar />
{{/let}}

@buschtoens
Copy link
Contributor

Can we potentially reopen this? AFAICT there seems to be general interest and agreement from many. I currently don't have the resources to champion an RFC myself, but I do believe this is still very worthwhile to pursue.

On a meta level: Would it make sense to add a label for such suggestions? "champion-needed" or something?

@mehulkar
Copy link
Contributor Author

mehulkar commented Dec 3, 2019

Sure, I can reopen it!

@mehulkar mehulkar reopened this Dec 3, 2019
@locks
Copy link
Contributor

locks commented Dec 3, 2019

@buschtoens champions are people from the relevant core teams that would make sure to advance a proposal through the team, so I don't think that would apply here 😅

@buschtoens
Copy link
Contributor

buschtoens commented Dec 4, 2019

@locks True! Maybe "rfc-needed"? I don't care about the name, but I think there are a few proposals, which are basically accepted and from a high level agreed upon, which just have no high priority and people putting in the time to author a proper RFC for them. This label could be useful for people that just want to get involved by writing an RFC, but have no concrete idea in mind.

I'm sorry for hijacking this thread with this off-topic. @locks, feel free to ping me on Discord, if you want to discuss further.

@sclaxton
Copy link

sclaxton commented Mar 4, 2020

IMO the desire for inline-let stems from the pain involved in expressing multiple assignment succinctly with current block-let, not a desire to change the current scoping semantics. Further, as @locks and I'm sure others have mentioned before, the complexity of changing the scoping semantics is what's holding the inline-let proposal back. Usually when in the situation of not wanting to change the semantics of the language but wanting to make the language for expressive/succinct, syntactic sugar is what PL designers reach for.

As I see it, we'd want to come up with sugar for this case of block-let:

{{#let a b c as |d e f|}}
  {{!-- stuff --}}
{{/let}} 

This is hard to grok because of the work required to positionally map a->d, b->e, c->f. To make this sweeter, we essentially just need to get rid of this positional mapping, with something akin to the following:

{{#let as |a=d c=e d=f|}}
  {{!-- stuff --}}
{{/let}} 

I'm not necessarily proposing exactly the above (though it does come pretty naturally IMO and syntax highlighting looks good), any sort of syntactic sugar that gets rid of the need to positionally map values would "fix" block-let when you want to sanely express multiple assignments.

All of that said, I'm also onboard with changing scoping semantics. Just wanted to call the above out as another answer to what I perceive the problem to be.

@nightire
Copy link

nightire commented Mar 4, 2020

@sclaxton This is achievable just using the current syntax and has decent readability.

{{#let (hash a=d b=e c=f) as |subject|}}
  {{subject.a}} {{subject.b}} {{subject.c}}
{{/let}}

People want one step further, to:

{{let (hash a=d b=e c=f) as |subject|}}

Using it anywhere: 
<p>
  {{subject.a}}
</p>

<Image @src={{subject.b}} alt={{subject.c}} />

@sclaxton
Copy link

sclaxton commented Mar 4, 2020

@nightire Yeah I'm aware, just also kind of feels bad introducing a whole new namespacing variable just to get a better syntax for multiple assignment. My suggestion is definitely inspired by the pattern you mention, I use it often. So I'd consider my suggestion sugar for that pattern as well, since it lowers the cognitive load of deciding what to call your namespacing variable...

@sclaxton
Copy link

sclaxton commented Mar 4, 2020

People want one step further, to:

{{let (hash a=d b=e c=f) as |subject|}}

Using it anywhere: 
<p>
  {{subject.a}}
</p>

<Image @src={{subject.b}} alt={{subject.c}} />

I don't think this is necessarily true, the only advantage of this vs. the current state is you don't have to close the let tag. I know for me, the pain of the hash pattern is having to spend the mental overhead of what to call subject and then having to add subject. prefix to the references of the variables I multi-assigned to. I don't mind having to close the let tag haha...

I think people would want inline-let to do this instead:

{{let a=d}}
{{let b=d}}
{{let c=f}}

@nightire
Copy link

nightire commented Mar 5, 2020

@nightire both ways are fine for me, I'd just prefer concise code. if introduce a new namespace is not what people expected, I'd like this much:

{{let a=d b=e c=f}}

the as |...| part is not necessary. only wrapping them by helper like {{hash}} requires an as |...| part because it essentially introduces a namespace object.

@sclaxton
Copy link

sclaxton commented Mar 5, 2020

Right, but that goes back to my overall point about altering the scoping semantics of the templating language: inline-let changes the semantics, syntactic sugar on top of block-let provides conciseness while maintaining semantics. Both solve the problem of concise multi-assignment.

@wagenet
Copy link
Member

wagenet commented Jul 23, 2022

It looks like this has already been closed and reopened once. Unfortunately, reopening it didn't actually help get it any closer to completion. For now I'm going to close this. If someone wants to write an RFC for this and needs guidance, please let me know and I'll try to help facilitate that.

@wagenet wagenet closed this as completed Jul 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests