Isolation of components - always required?

So, components are awesome. Isolation is awesome. But one thing I often hit is that I’d like to create nestable components that have specific behaviour based on how they are nested. An example is this split view I played with recently:

Fundamentally I think being able to do stuff like this:

{{#split-view}}
    {{#left-view}}
         left
    {{/left-view}}
    {{#right-view}}
        {{#split-view}}
              {{#top-view}}
                top
              {{/top-view}}
              {{#bottom-view}}
                  bottom
              {{/bottom-view}}
        {{/split-view}}
    {{/right-view}}
{{/split-view}}

is pretty awesome, but it requires some knowledge of the surrounding view hierarchy to achieve this. If you look at the jsfiddle, I’m accomplishing this using parentView and childViews properties.

I think that allowing access to these properties is a recipe for violating component isolation in general. As such, I propose adding parentComponent and childComponents properties to components that allow only accessing parent or child components, allowing you to build complex nested behaviours but still keeping direct access to parts of your application off the table.

It’d be good to hear feedback on this proposal, particularly from people who are more familiar with the web components spec. Is this a good idea or should you just never even try to do something like this?

9 Likes

One thing to add is that it seems like regular HTML elements have this kind of behaviour / constraints already. For example you have ul tags that must contain one or more li tags, and you can’t use li tags outside of that. I guess I’m wondering if there is anything like this in the web components spec and/or if there is any way to arrive at a common way to do this in Ember.

@alexspeller I love this!

This seems so much more in line with where @machty 's original intent was for components… or at least, where he wanted them to go… and I’ve been trying to bug the adepar guys to adapt ember-table to use this style of component construction for a while now…

:+1: :+1: :+1:

I ran into issues with the ember-table component precisely because it wasn’t constructed like this… when I wanted to specialise it to fit my specific needs… (was building a “simple” CRUD-table beacuse I got sick of repeating myself in my app for basic temporary scaffolding style code, and it turned into a bit of nightmare).

Another example of where this is useful:

http://alexspeller.com/simple-forms-with-ember/

1 Like

Anytime there is a parent-child relationship, then you’re bringing in some sort of inheritance. The reason that it is functionally different is that in your case, the child behaves differently depending on what its parent is. Components are supposed to be isolated though, and w/no context besides the one you choose to pass in.

e- whoops, I didn’t realize I was on edit mode.

I’m not sure what you mean by this - I don’t think anyone has mentioned inheritance anywhere. I’m also not sure how “parent components dictating what the sub-components do” is functionally any different - essentially there is information shared between parent and child components causing a change in behaviour. Could you clarify what exactly you mean by this?

Thanks, Alex

I really like this idea. I’m not convinced that direct access to parent/child components is a good idea though, the main benefit that I’ve seen from components is isolation and encapsulation, so I’d be keen to keep that as much as possible.

It occurs to me that we already have a really good model for communication across boundaries that is already in use in other places.

Would there be any issues with bubbling actions on child components up to their parent components in the usual way, and in return, allowing parent component to send events down to any child components where they exist? I think this would neatly solve your issues.

Hey Ben :smile:

I think actions bubbling to components would make sense - it might have some edge cases that make it hard though. For example, what if you have a component that renders another controller - the action should generally bubble from the template’s controller to the route, so in this case it might skip the parent controller.

Bubbling downwards would also be interesting - not sure how you would implement it though.

Altogether though, I’m not entirely convinced that in practice it makes that much difference - and there’s the risk you’d end up reimplementing bindings with these events in effect (i.e. watching for the event on both sides and then setting a property).

One thing I’ve been thinking of since I started this thread is explicitly specifying what’s accessible - I haven’t thought about this entirely so this is not a real API proposal, but something like:

App.ParentComponent = Em.Component.extend
  childrenCanBindTo: ['prop1', 'prop2']

App.ParentComponent = Em.Component.extend
  parentsCanBindTo: ['prop1', 'prop2']

Or something like that - so that you can explicitly specify and enforce dependencies, much like you do when you put components in a template anyway.

Regardless of what happens with bindings, I think that actions bubbling to parent components should happen if it’s possible to resolve the ambiguousness of how that works when switching controller scope in a template.

1 Like

So I suppose I was imagining something either manual or automatic along the lines of:

App.ParentComponent = Em.Component.extend
  actions:
    myAction: ->
      @resizeContainer()
      @children.sendAction 'resize'

App.ChildComponent = Em.Component.extend
  actions:
    doSomething: ->
      @sendAction 'updateModel'
      @parent.sendAction 'saved'

or something

Sorry for digging up this, but I am trying to do the exact same thing, that is: having a component that is filled up by subcomponents, the same way an <ul> gets its items from child <li>s. Though this can be achieved through breaking encapsulation by allowing child components to register on a parent binding, that’s ugly (yield this and binding in the template exposes what should be internal behavior) and that still means the data is not available until the template is fully rendered, at which point it is too late.

Has there been any news on that front? Ember development is much more active than documentation and I cannot find any central place summing all the changes around components that happened lately.