ember-polyfills / ember-angle-bracket-invocation-polyfill

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Single word components, path components

samselikoff opened this issue Β· comments

Amazing work! πŸŽ‰

We use a lot of "presenter" components, and they look like this:

{{#ui-title}}Hello, world!{{/ui-title}}

{{ui-spacer}}

{{#ui-container}}
  <h1>Welcome to our page.</h1>
{{/ui-container}}

I'm trying to experiment and figure out the best API for these kind of components in an angle-bracket world.

Same name

Keeping the same name makes the above template

<UiTitle>Hello, world!</UiTitle>

<UiSpacer>

<UiContainer>
  <h1>Welcome to our page.</h1>
</UiContainer>

which is ok, but the Ui prefix feels really noisy, and not sufficiently separated from the name of the component. Makes the template a bit hard to read.

Single word components

I think if we had single word components, we'd use those for presenters:

<Title>Hello, world!</Title>

<Spacer>

<Container>
  <h1>Welcome to our page.</h1>
</Container>

Looks gorg 😍

Path components

Is there an alternative using paths? I'm not sure how path components work in angle-bracket world.

<UI/Title>Hello, world!<UI/Title>

<UI/Spacer>

<UI/Container>
  <h1>Welcome to our page.</h1>
<UI/Container>

What about dot-paths, are those only supported inside of a contextual component?

<UI.Title>Hello, world!<UI.Title>

<UI.Spacer>

<UI.Container>
  <h1>Welcome to our page.</h1>
<UI.Container>

or with a lower-cased ui:

<ui.Title>Hello, world!<ui.Title>

<ui.Spacer>

<ui.Container>
  <h1>Welcome to our page.</h1>
<ui.Container>

What do you think? We're keen to try this out and start experimenting with good patterns for future Ember!

Is there an alternative using paths? I'm not sure how path components work in angle-bracket world.

Paths are not an option, the RFC states this:

Second, while Handlebars technically allows {{foo/bar}} as an equivilant alternative to the {{foo.bar}} path lookup (and therefore foo/bar is technically a valid Handlebars path expression), it will not be supported in angle bracket invocation. This is both because the / conflicts with the HTML closing tag syntax, and the fact that Ember overrides that syntax with a different semantic.

In today's semantics, {{foo/bar}} does not try to lookup this.foo.bar and invoke it as a component. Instead, it is used as a filesystem scoping syntax. Since this feature will be rendered unnecessary with Module Unification, we recommend apps using "slash components" to migrate to alternatives provided by Module Unification (or, alternatively, keep using curly invocations for this purpose).

I think if we had single word components, we'd use those for presenters:

<Title>Hello, world!</Title>

<Spacer />

<Container>
  <h1>Welcome to our page.</h1>
</Container>

Yep, I agree that this is really nice. This works already when using canary versions of ember-source, but I haven't figured out how the polyfill could work around the assertion in Ember's prior to 3.4.

I don't think you should do this (I like the one word version better), but another option is:

<Ui-Title>Hello, world!</Ui-Title>

<Ui-Spacer />

<Ui-Container>
  <h1>Welcome to our page.</h1>
</Ui-Container>

How would <Ui-Title> look on disk?

If one-word is the future and it just doesn't work pre-3.4, it's probably not worth spending too much effort discussing here. That's definitely what we'll use.

If one-word is the future and it just doesn't work pre-3.4, it's probably not worth spending too much effort discussing here.

Well, this addon is all about making the future available now πŸ˜‰...

How would look on disk?

Same place you are likely using now for {{ui-title}}: app/components/ui-title.js

Interesting, so the - in the name doesn't affect the lookup?

Well, this addon is all about making the future available now πŸ˜‰...

Aye, good point. Any ideas for hacking around the assertion, or ways I could help figure that out? Maybe someone to reach out to?

The dasherization that is used here is slightly different than Ember.String.dasherize, it is basically:

https://github.com/rwjblue/ember-angle-bracket-invocation-polyfill/blob/60db162aa6463cc6f734128cd6e0dec99db1b9a4/lib/ast-transform.js#L20-L28

Some tests (from Ember's test suite) for this show expected inputs/outputs:

  function equals(input, expected) {
    QUnit.test(`${input} -> ${expected}`, function(assert) {
      assert.equal(COMPONENT_NAME_SIMPLE_DASHERIZE_CACHE.get(input), expected);
    });
  }

  equals('Foo', 'foo');
  equals('foo-bar', 'foo-bar');
  equals('FooBar', 'foo-bar');
  equals('XBlah', 'x-blah');
  equals('X-Blah', 'x-blah');
  equals('Foo::BarBaz', 'foo::bar-baz');
  equals('Foo::Bar-Baz', 'foo::bar-baz');
  equals('Foo@BarBaz', 'foo@bar-baz');
  equals('Foo@Bar-Baz', 'foo@bar-baz');

Aye, good point. Any ideas for hacking around the assertion, or ways I could help figure that out? Maybe someone to reach out to?

I think a good first step is to get together a failing test PR. Something like this test (but using a one word component) should do the trick:

https://github.com/rwjblue/ember-angle-bracket-invocation-polyfill/blob/60db162aa6463cc6f734128cd6e0dec99db1b9a4/tests/integration/components/angle-bracket-invocation-test.js#L22-L28

From there we need to track down which assertion in Ember is actually being fired, and figure out how to hack it off πŸ‘Ώ

In the MU world I'd go with

{{use Title, Spacer, Container from 'ui'}}

<Title>
  Title
</Title>

<Spacer />

<Container>
  content
</Container>

Where 'ui' is in packages/ui.

In the MU world I'd go with

FWIW, this is still wildly in flux (the RFC update is not completed, and the WIP is somewhat incoherent still).

Yeah, just thought since we are talking about the future πŸ˜‰

Totally, but I can't reason about the MU changes yet (I've tried a lot and failed miserably), I need more details (e.g. the actual RFC update to be completed).

#34 should address this