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

Named templates within a class-based component don't have this #249

Closed
rykov opened this issue Sep 25, 2024 · 6 comments
Closed

Named templates within a class-based component don't have this #249

rykov opened this issue Sep 25, 2024 · 6 comments

Comments

@rykov
Copy link

rykov commented Sep 25, 2024

Having the following component:

import Component from '@glimmer/component';

export default class Hello extends Component {
  value = "HELLO";

  <template>
    From top template: {{ this.value }}<br/>
    <this.Subtemplate/><br/>
  </template>

  Subtemplate = <template>
    From subtemplate: {{ this.value }}
  </template>
}

I get the following output:

From top template: HELLO
From subtemplate:

It seems intuitive that all templates defined within a Component would expose this to access the instance.

@NullVoxPopuli
Copy link
Collaborator

NullVoxPopuli commented Sep 25, 2024

Multiple templates within a class is not supported that way. The component assigned to a variable is a template-only component. :/

The relationship here is 1:1, and idk if it's worth while to support multiple this-accessing instance-assigned templates.

Today, we could think of the classes template as being on the prototype, so it's shared between all instances. The property assigned template would not have that benefit.

Instead, you can do this:

import Component from '@glimmer/component';

export default class Hello extends Component {
  value = "HELLO";

  <template>
    From top template: {{ this.value }}<br/>
    <Subtemplate @value={{this.value}} /><br/>
  </template>
}

const Subtemplate = <template>
    From subtemplate: {{ @value }}
  </template>;

@rykov
Copy link
Author

rykov commented Sep 26, 2024

@NullVoxPopuli The context for this is trying to break up a complex template into one main and a few sub-templates within one component. I did end up passing around @self={{ this }} similar to what you've described.

I understand that there may be a technical reason to have the 1:1 template/component relationship, however, from developer aesthetics perspective, I was surprised that this was not available, expecting a similar experience to global/standalone vs. class member functions.

Is it possible, if it makes sense, to define sub-templates on the prototype somehow, and to share the component? If property assignment is not the correct way to define it, maybe something like <template name="Subtemplate">?

@NullVoxPopuli
Copy link
Collaborator

Naw it's more that <template> is not defined as a separate thing that just be assigned places.

In emberjs/rfcs#779, we have two definitions, around components (not <template>) (paraphrasing)

  • A component is a class with a single <template> in class-body space
  • A component is a lone <template> assigned to a const in module space

There is some wiggle room around the second, but (without having seen examples) it mostly gets in to understanding what <template> is compiled to, component managers, and how all that works and what their limitations are.

from developer aesthetics perspective, I was surprised that this was not available

yeah, one thing that might not be intuitive with these components is that the <template> content does not have access to all scope.

otherwise, someone could define window.div, and your <div> in your components becomes whatever window.div is -- potentially bad! -- may even be a security issue.

Is it possible, if it makes sense, to define sub-templates on the prototype somehow, and to share the component?

it is not


Is there any reason why defining components in module scope is not ideal for your use case?

I know you said you were splitting up a large component -- but passing this around to other components is kinda re-inventing partial, yeah? maybe the data flow in that component needs some deeper evaluation?

@NullVoxPopuli
Copy link
Collaborator

that said, there is some very early planned work to better align this access to how folks expect: emberjs/babel-plugin-ember-template-compilation#61

but I don't know if anyone is prioritizing it

@NullVoxPopuli
Copy link
Collaborator

I'm going to close this, as any work in this space would need to be in babel-plugin-ember-template-compilation.

I appreciate your use case, explanations, and we can keep discussing here if you want, but there is nothing for this library to do

@rykov
Copy link
Author

rykov commented Sep 26, 2024

@NullVoxPopuli Thank you for the explanation. It sent me back to the docs that clearly state that <template> "defines a template-only component" when I assign one to a class property 🤦.

Is there any reason why defining components in module scope is not ideal for your use case?

This is our current solution.

maybe the data flow in that component needs some deeper evaluation?

Recognizing sub-templates as separate components puts things in a new light.

I'll keep on eye on emberjs/babel-plugin-ember-template-compilation#61.

Thanks again.

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

2 participants