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

Implements RFC #60 (Component Unification) #11359

Merged
merged 1 commit into from
Jul 8, 2015
Merged

Conversation

tomdale
Copy link
Member

@tomdale tomdale commented Jun 6, 2015

emberjs/rfcs#60

This commit implements the proposed semantics for angle-bracket
components. The TLDR is that a component’s template represents its
“outerHTML” rather than its “innerHTML”, which makes it easier to
configure the element itself using templating constructs.

Some salient points:

  1. If there is a single root element, the attributes from the invocation
    are copied onto the root element.
  2. The invocation’s attributes “win out” over the attributes from the
    root element in the component’s layout.
  3. Classes are merged. If the invocation says class=“a” and the root
    element says class=“b”, the result is class=“a b”. The rationale
    is that when you say class=“a”, you are really saying “add the a
    class to this element”.

A few sticky issues:

  1. If the root element for the my-foo component is <my-foo>, we
    insert an element with tag name of my-foo. While this is intuitive,
    note that in all other cases, <my-foo> represents an invocation of
    the component. In the root position, that makes no sense, since it
    would inevitably produce a stack overflow.
    a. This “identity element” case makes it idiomatic to reflect the
    name of the component onto the DOM.
    b. Unfortunately, when we compile a template, we do not yet know
    what component that template is used for, and, indeed, whether it
    is even a template for a component at all.
    c. To capture the semantic differences, we do a bit of analysis at
    compile time (to determine candidates for top-level elements),
    and use runtime information (component invocation style and
    the name of the component looked up in the container) to
    disambiguate between a component’s element and an invocation of
    another component.
  2. If the root element for the my-foo component is a regular HTML
    element, we use the attachAttributes functionality of HTMLBars to
    attach the attributes that the component was invoked with onto the
    root element.
  3. In general, it is important that changes to attributes do not result
    in a change to the identity of the element that they are contained
    in. To achieve this, we reused much of the infrastructure built in
    buildComponentTemplate.

The consequence of (1) and (2) above is that the semantics are always
“a component’s layout represents its outerHTML”, even though the
implementation is quite different depending on whether the root element
is the same-named component or not.


state.manager = manager;
if (!isTopLevel || tagName !== env.view.tagName) {
var manager = ComponentNodeManager.create(renderNode, env, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the use of var here intentional? let is used heavily elsewhere.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not intentional; we were just moving around pre-existing code.

@tomdale tomdale force-pushed the in-template-config branch 2 times, most recently from 5d2c3fc to 5a084f7 Compare July 7, 2015 00:04
emberjs/rfcs#60

This commit implements the proposed semantics for angle-bracket
components. The TLDR is that a component’s template represents its
“outerHTML” rather than its “innerHTML”, which makes it easier to
configure the element itself using templating constructs.

Some salient points:

1. If there is a single root element, the attributes from the invocation
   are copied onto the root element.
2. The invocation’s attributes “win out” over the attributes from the
   root element in the component’s layout.
3. Classes are merged. If the invocation says `class=“a”` and the root
   element says `class=“b”`, the result is `class=“a b”`. The rationale
   is that when you say `class=“a”`, you are really saying “add the `a`
   class to this element”.

A few sticky issues:

1. If the root element for the `my-foo` component is `<my-foo>`, we
   insert an element with tag name of `my-foo`. While this is intuitive,
   note that in all other cases, `<my-foo>` represents an invocation of
   the component. In the root position, that makes no sense, since it
   would inevitably produce a stack overflow.
   a. This “identity element” case makes it idiomatic to reflect the
      name of the component onto the DOM.
   b. Unfortunately, when we compile a template, we do not yet know
      what component that template is used for, and, indeed, whether it
      is even a template for a component at all.
   c. To capture the semantic differences, we do a bit of analysis at
      compile time (to determine *candidates* for top-level elements),
      and use runtime information (component invocation style and
      the name of the component looked up in the container) to
      disambiguate between a component’s element and an invocation of
      another component.
2. If the root element for the `my-foo` component is a regular HTML
   element, we use the `attachAttributes` functionality of HTMLBars to
   attach the attributes that the component was invoked with onto the
   root element.
3. In general, it is important that changes to attributes do not result
   in a change to the identity of the element that they are contained
   in. To achieve this, we reused much of the infrastructure built in
   `buildComponentTemplate`.

The consequence of (1) and (2) above is that the semantics are always
“a component’s layout represents its outerHTML”, even though the
implementation is quite different depending on whether the root element
is the same-named component or not.
@tomdale
Copy link
Member Author

tomdale commented Jul 8, 2015

We are going to get this merged behind a feature flag. We will work on removing support for the fragment case due to some concerns, and instead implement an error message if you do not provide a root element.

tomdale added a commit that referenced this pull request Jul 8, 2015
Implements RFC #60 (Component Unification)
@tomdale tomdale merged commit b587c48 into master Jul 8, 2015
@mmun mmun deleted the in-template-config branch February 19, 2016 13:00
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

Successfully merging this pull request may close these issues.

None yet

3 participants