How to share attributes between nested components


#1

I’m looking for feedback on how to share attributes between nested components that will be compatible with Ember 2.0.

For example, with the ember-nf-graph addon the svg width/height is inherited down to the child components which supports a nice clean syntax:

{{#nf-graph width=500 height=300}}
  {{#nf-graph-content}}
    {{nf-line data=myLineData}}
  {{/nf-graph-content}}
{{/nf-graph}}

Instead of having to explicitly pass the width and height to every child component:

{{#nf-graph width=500 height=300}}
  {{#nf-graph-content width=500 height=300}}
    {{nf-line data=myLineData width=500 height=300}}
  {{/nf-graph-content}}
{{/nf-graph}}

The ember-nf-graph addon accomplishes this by using the view method nearestWithProperty(): http://emberjs.com/api/classes/Ember.View.html#method_nearestWithProperty. Ex: https://github.com/Netflix/ember-nf-graph/search?q=nearestWithProperty&type=Code&utf8=✓

It seems like nearestWithProperty() will no longer be available in Ember 2.0 since views are going to private. Will there be a new convention for sharing attributes between nested components?


#2

Ember.Component = Ember.View.extend() so Ember.View#nearestWithProperty is not going anywhere, as long as they continue to follow Semantic Versioning (which they very serious about following so very little chance it’ll be gone).

i.e. what nf-graph is doing right now will indeed be supported in Ember 2.0, unless the core team randomly breaks semver.


#3

btw nearestOfType may be more robust instead of relying on duck typing with nearestWithProperty, like nf-graph does (for historical reasons aka no good reason)


#4

Thanks Jay! I didn’t realize Component is extended from View. I’m glad to hear this should still be supported in Ember 2.0. I will try using nearestOfType() for sharing attributes with nested components.


#5

You’re welcome! Feel free to ping with any additional queries.


#6

@jayphelps what do you think to allowing components to have defined relationships, I feel this would be a little more explicit than what is being used here.

Would it not be more consistent to allow scoped based definitions much like <ul> and <ol> change the meaning of <li> elements.

If a <my-input> can have specialist bindings to components that are/extend from <my-form> then I feel the use cases here are resolved whilst keeping affinity to the HTML spec.

<label> does this automatically and sets the label.control element, it strikes me a declarative syntax would help users setup parameters like this.

From my comment here:

https://github.com/emberjs/ember.js/pull/10244#issuecomment-96861683


#7

I’m absolutely for some sort of idiomatic way of inheriting information in certain parent element contexts, but in HTML there isn’t actually a concept of “scope” based definitions in the sense that an <option> inside a <select> is valid and works correctly with magic (though the spec doesn’t specify how the magic should work), but an <option> elsewhere is still an instance of the same HTMLOptionElement, it’s just invalid markup.

This is an important distinction. Only one tag can be registered to within an XML namespace (HTML in this case).

We may totally be on the same page and I’m just interpreting you incorrectly. :smile:


#8

Certainly scope was the wrong word there, however there are relationships as defined by these elements, I see the component.js files as the internals to the markup (again to ensure we are on the same page).

As I say label and the controls have similar relationships as to I am suggesting (without for attribute and just wrapping the input the label.control attribute is defined from it’s placement in the markup).