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

Routable Components RFC #38

Closed
wants to merge 5 commits into
base: master
from

Conversation

Projects
None yet
@ef4
Contributor

ef4 commented Feb 27, 2015

RFC

@chancancode

This comment has been minimized.

Show comment
Hide comment
@chancancode

chancancode Feb 28, 2015

Member

👏 Great work!

So just earlier today, I was mentioning the async component use case to @rwjblue and @ef4.

A friend was asking for ideas on how to implement this, and he mentioned something along the lines of "you almost want a component with its own mini-route". That sounded bizarre at first, but as I think about it a bit more, it is starting to make a lot of sense.

Of course, a "route" for a component doesn't make any sense. What we actually want is the "almost free" asynchrony handling and state management offered by the Ember router. Async and states are much more generic than the problem of routing, and since this approach worked out so well for routing, it makes a lot sense that you would desire the same kind of mechanisms in other places that you need to deal with these problems.

So, I think I would be interested in something along the lines of http://emberjs.jsbin.com/bujufi/1/edit. Basically, like the router, you have a promise hook (I would have called it model like the router, but that clashes with the property that holds the actual resolved value) where you can optionally implement and return a promise. If you did return a promise from the hook, it will put the component into the loading substate and render the component-name/loading template, if there is one. When the promise resolves, it will assign the resolved value to the model property and render the regular component-name template. If it rejects, it will render the component-name/error.

This is not a formal proposal, of course, and there are many nuances to be addressed. But overall, I feel that it fits in quite naturally with the rest of the framework.

I would also like to draw your attention to this part of the code:

App.YelpReviewComponent = Ember.Component.extend({

  businessId: null, // Passed in

  promise: function() {
    if (this.get('businessId')) {
      return GetYelpReview( this.get('businessId') );    
    } else {
      return null;
    }
  }.property('businessId'),

  ...

});

The highlight is that the promise hook is actually just a regular computed property, so you just declare its dependencies like you normally would. When one or more of its dependencies changed, this will "re-fire", and the framework can just observe this computed property to determine whether the component has changed state.

To me, this feels very natural and aligns very well with other parts of the framework (unlike refreshModel, etc, which are special-occasion concepts that I need to learn).

Once we have asynchronous components, it may be tempting to handle
all data loading through them, eliminating traditional Routes, and
essentially moving the model hook onto Components.

Is this really so bad?

My gut feeling is that the routable component use case might just be a special case of async components. I think data-fetching async components should actually a pretty quite common thing, and the reason we aren't thinking/implementing them this way today is mostly just a side-effect of the poor ergonomics. If you think about it, <img> <audio> <video> <iframe> etc are all data-fetching async components – with window.fetch coming to browsers this should feel much more natural and second-nature over time.

So, I think it would need to have an a solid API for async components regardless. Since people need to learn/do that anyway, it is perhaps not a bad idea at all to put most of this responsibility (async management, substates) in the component, and implement routing in terms of async components. Most people coming from server-side MVC have NFI what a "route" object is (to be honest, I still don't know if I understand what it /really/ is, as opposed to just understanding how to use them), so I think it is not necessarily a bad thing if you can get away with not doing much at all with them in the 80% common cases.

I am completely thinking out loud here, so bullshit alert on please. I feel like I am not smart enough to put together all the pieces, but there seems to be some interesting stuff in there somewhere. Substates, for example, are interesting. Since they don't actually change the URLs anyway (and in fact, we iterated a few times on whether they should eagerly update the URLs and stuff like that), it perhaps suggest that it is not intrinsically a routing concern. The CP + dependencies promise hook is also interesting. Then perhaps {{outlet}}s are really just {{yield}}s (now you can yield variables, callbacks etc, perhaps it would get rid of some of the controllerFor/modelFor global-punch-through awkwardness). Maybe all the route need to do is just instantiate the WhateverRouteComponent, set all the params as attributes on it and let it figure out what to do (promise, substates and whatnot). Perhaps the component (or links, etc) will call setState on the component to change between its child states/routes/components/templates, and the router just observe
these states to change URL accordingly...

Anyway. I don't really have much concrete suggestions at the moment, and definitely haven't considered any backwards compatibility things at all. Just thought that I would throw this out there and let people smarter than me decide if it's pure snake oil or what 😄

I should also mention, it's almost 5AM here, so take it with many grains of salt 🙊

Member

chancancode commented Feb 28, 2015

👏 Great work!

So just earlier today, I was mentioning the async component use case to @rwjblue and @ef4.

A friend was asking for ideas on how to implement this, and he mentioned something along the lines of "you almost want a component with its own mini-route". That sounded bizarre at first, but as I think about it a bit more, it is starting to make a lot of sense.

Of course, a "route" for a component doesn't make any sense. What we actually want is the "almost free" asynchrony handling and state management offered by the Ember router. Async and states are much more generic than the problem of routing, and since this approach worked out so well for routing, it makes a lot sense that you would desire the same kind of mechanisms in other places that you need to deal with these problems.

So, I think I would be interested in something along the lines of http://emberjs.jsbin.com/bujufi/1/edit. Basically, like the router, you have a promise hook (I would have called it model like the router, but that clashes with the property that holds the actual resolved value) where you can optionally implement and return a promise. If you did return a promise from the hook, it will put the component into the loading substate and render the component-name/loading template, if there is one. When the promise resolves, it will assign the resolved value to the model property and render the regular component-name template. If it rejects, it will render the component-name/error.

This is not a formal proposal, of course, and there are many nuances to be addressed. But overall, I feel that it fits in quite naturally with the rest of the framework.

I would also like to draw your attention to this part of the code:

App.YelpReviewComponent = Ember.Component.extend({

  businessId: null, // Passed in

  promise: function() {
    if (this.get('businessId')) {
      return GetYelpReview( this.get('businessId') );    
    } else {
      return null;
    }
  }.property('businessId'),

  ...

});

The highlight is that the promise hook is actually just a regular computed property, so you just declare its dependencies like you normally would. When one or more of its dependencies changed, this will "re-fire", and the framework can just observe this computed property to determine whether the component has changed state.

To me, this feels very natural and aligns very well with other parts of the framework (unlike refreshModel, etc, which are special-occasion concepts that I need to learn).

Once we have asynchronous components, it may be tempting to handle
all data loading through them, eliminating traditional Routes, and
essentially moving the model hook onto Components.

Is this really so bad?

My gut feeling is that the routable component use case might just be a special case of async components. I think data-fetching async components should actually a pretty quite common thing, and the reason we aren't thinking/implementing them this way today is mostly just a side-effect of the poor ergonomics. If you think about it, <img> <audio> <video> <iframe> etc are all data-fetching async components – with window.fetch coming to browsers this should feel much more natural and second-nature over time.

So, I think it would need to have an a solid API for async components regardless. Since people need to learn/do that anyway, it is perhaps not a bad idea at all to put most of this responsibility (async management, substates) in the component, and implement routing in terms of async components. Most people coming from server-side MVC have NFI what a "route" object is (to be honest, I still don't know if I understand what it /really/ is, as opposed to just understanding how to use them), so I think it is not necessarily a bad thing if you can get away with not doing much at all with them in the 80% common cases.

I am completely thinking out loud here, so bullshit alert on please. I feel like I am not smart enough to put together all the pieces, but there seems to be some interesting stuff in there somewhere. Substates, for example, are interesting. Since they don't actually change the URLs anyway (and in fact, we iterated a few times on whether they should eagerly update the URLs and stuff like that), it perhaps suggest that it is not intrinsically a routing concern. The CP + dependencies promise hook is also interesting. Then perhaps {{outlet}}s are really just {{yield}}s (now you can yield variables, callbacks etc, perhaps it would get rid of some of the controllerFor/modelFor global-punch-through awkwardness). Maybe all the route need to do is just instantiate the WhateverRouteComponent, set all the params as attributes on it and let it figure out what to do (promise, substates and whatnot). Perhaps the component (or links, etc) will call setState on the component to change between its child states/routes/components/templates, and the router just observe
these states to change URL accordingly...

Anyway. I don't really have much concrete suggestions at the moment, and definitely haven't considered any backwards compatibility things at all. Just thought that I would throw this out there and let people smarter than me decide if it's pure snake oil or what 😄

I should also mention, it's almost 5AM here, so take it with many grains of salt 🙊

@workmanw

This comment has been minimized.

Show comment
Hide comment
@workmanw

workmanw Feb 28, 2015

Contributor

Thanks a lot! This is quite the RFC. Overall I'm pretty happy with how this shakes out. I love the idea of async components and the use of fragments.

But I do have a few concerns based on app's usage of Ember. I've grouped them into sections below. These are grouped by priority of concern or impact to our application (biggest impact to smallest).


What about controllerFor or componentFor? We have dozens of cases where a route needs to communicate with an ancestor resource's controller. Sometimes it's as simple as toggling state (like showing/hiding elements on when another route's active/deactivate are called). Other times those controllers house large reusable logic pertaining to their model's state.

Similarly, what about Ember.inject.controller or Ember.inject.component? Very similar to above, our controllers frequently contact parent resource controllers. This type of thing happens a lot with our global nav-bars. Different routes can add/remove/enable/disable different nav options. Also when a controller creates a new model and requires one or more ancestor models to build a relationship.


It's not clear from this RFC if actions will still exist as a hash on routes. It's also not clear if there will be any method of action bubbling on the route will exist. We have countless scenarios where we leverage action bubbling, anything sending realtime messages, to contextually handling alerts, to opening modal with different options depending on where the user is in the app. It would be a huge blow to loose action bubbling on routes.


Therefore, if you want to send an action from a component up to the Route that rendered it, you should pass an action handler function as one of your component's attributes.

We have near a hundred cases of controller actions that bubble to the route. Most of the time the action originates in a component and we want it to behave differently depending on where it is used in the app. This feels like it will add a lot of boilerplate.


Storage for transient application state? We have some places in our app where we did get value from controllers being singletons. Where it was good to keep "temporary data". If you imagine Gmail, you can select a few emails, click to see the details of one, then navigate back and your selection is maintained. I know the goal of routes are to be stateless and I agree with that. I was just curious if there was a recommendation for this? Should I make a service just to store temp-selection?


This RFC deprecates calling render outside of route transitions.

We, like many other people, have been using this approach to modals: http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/ This would break this pattern. That's okay with me, I didn't really love it. But I'm wondering if there is an alternative. Maybe using a ContainerView as modal manager.


Thanks again! I hope this didn't come across as negative. I appreciate the amount of thought that went into this RFC by everyone and I'm excited to see this come to fruition.

Contributor

workmanw commented Feb 28, 2015

Thanks a lot! This is quite the RFC. Overall I'm pretty happy with how this shakes out. I love the idea of async components and the use of fragments.

But I do have a few concerns based on app's usage of Ember. I've grouped them into sections below. These are grouped by priority of concern or impact to our application (biggest impact to smallest).


What about controllerFor or componentFor? We have dozens of cases where a route needs to communicate with an ancestor resource's controller. Sometimes it's as simple as toggling state (like showing/hiding elements on when another route's active/deactivate are called). Other times those controllers house large reusable logic pertaining to their model's state.

Similarly, what about Ember.inject.controller or Ember.inject.component? Very similar to above, our controllers frequently contact parent resource controllers. This type of thing happens a lot with our global nav-bars. Different routes can add/remove/enable/disable different nav options. Also when a controller creates a new model and requires one or more ancestor models to build a relationship.


It's not clear from this RFC if actions will still exist as a hash on routes. It's also not clear if there will be any method of action bubbling on the route will exist. We have countless scenarios where we leverage action bubbling, anything sending realtime messages, to contextually handling alerts, to opening modal with different options depending on where the user is in the app. It would be a huge blow to loose action bubbling on routes.


Therefore, if you want to send an action from a component up to the Route that rendered it, you should pass an action handler function as one of your component's attributes.

We have near a hundred cases of controller actions that bubble to the route. Most of the time the action originates in a component and we want it to behave differently depending on where it is used in the app. This feels like it will add a lot of boilerplate.


Storage for transient application state? We have some places in our app where we did get value from controllers being singletons. Where it was good to keep "temporary data". If you imagine Gmail, you can select a few emails, click to see the details of one, then navigate back and your selection is maintained. I know the goal of routes are to be stateless and I agree with that. I was just curious if there was a recommendation for this? Should I make a service just to store temp-selection?


This RFC deprecates calling render outside of route transitions.

We, like many other people, have been using this approach to modals: http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/ This would break this pattern. That's okay with me, I didn't really love it. But I'm wondering if there is an alternative. Maybe using a ContainerView as modal manager.


Thanks again! I hope this didn't come across as negative. I appreciate the amount of thought that went into this RFC by everyone and I'm excited to see this come to fruition.

@wycats

This comment has been minimized.

Show comment
Hide comment
@wycats

wycats Feb 28, 2015

Member

I really think it's important to differentiate between "I know what component I'm going to but I have work to do before I can show it" (async component) and "I have to do some work to do before I even know where I'm going" (route).

Member

wycats commented Feb 28, 2015

I really think it's important to differentiate between "I know what component I'm going to but I have work to do before I can show it" (async component) and "I have to do some work to do before I even know where I'm going" (route).

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Feb 28, 2015

Contributor

Yes, @wycats has hit on the main reason that I think Routes still needs to be a thing.

The problem with doing all the routing in components is that there is often important work to do before you can even establish a component hierarchy. Authorization decisions, for example, are really nicely done in routes.

I think this will become even more significant as we work on lazily loading chunks of application. Routes are a natural place to manage decisions around what source code is even going to be needed, without having the components themselves present yet.

Contributor

ef4 commented Feb 28, 2015

Yes, @wycats has hit on the main reason that I think Routes still needs to be a thing.

The problem with doing all the routing in components is that there is often important work to do before you can even establish a component hierarchy. Authorization decisions, for example, are really nicely done in routes.

I think this will become even more significant as we work on lazily loading chunks of application. Routes are a natural place to manage decisions around what source code is even going to be needed, without having the components themselves present yet.

@zeppelin

This comment has been minimized.

Show comment
Hide comment
@zeppelin

zeppelin Feb 28, 2015

Based on choice of words in the RFC is it safe to assume that naming routable components won't have to be consistent with the requirements of regular components - like how it proposed for fragments?

zeppelin commented Feb 28, 2015

Based on choice of words in the RFC is it safe to assume that naming routable components won't have to be consistent with the requirements of regular components - like how it proposed for fragments?

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Feb 28, 2015

Contributor

@zeppelin Yes, definitely. We don't want everyone to need to rename their routes to contain dashes just became Web Component names need dashes.

Contributor

ef4 commented Feb 28, 2015

@zeppelin Yes, definitely. We don't want everyone to need to rename their routes to contain dashes just became Web Component names need dashes.

@jerel

This comment has been minimized.

Show comment
Hide comment
@jerel

jerel Feb 28, 2015

Since the 2.0 plan was announced I started focusing on components and services with minimal usage of controllers in my apps and I feel this RFC is well done and covers the pain points that I've felt.

A couple questions I still have:

  1. What about the use case of manipulating (filtering, sorting, etc) data before it is displayed? Sorting, filtering, etc used to be done in a route's ArrayController. Will the documented path be to create a service for this data or to do it in a parent component with the {{#each}}{{/each}} in that component's template?
  2. With async components is there something that will keep new developers from eliminating all routes except the application route and breaking the url behavior (back button) like so many other SPA frameworks allow?

jerel commented Feb 28, 2015

Since the 2.0 plan was announced I started focusing on components and services with minimal usage of controllers in my apps and I feel this RFC is well done and covers the pain points that I've felt.

A couple questions I still have:

  1. What about the use case of manipulating (filtering, sorting, etc) data before it is displayed? Sorting, filtering, etc used to be done in a route's ArrayController. Will the documented path be to create a service for this data or to do it in a parent component with the {{#each}}{{/each}} in that component's template?
  2. With async components is there something that will keep new developers from eliminating all routes except the application route and breaking the url behavior (back button) like so many other SPA frameworks allow?
@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Feb 28, 2015

Contributor

@workmanw So we almost certainly don't want something like Ember.inject.component, because one of the key things about components is their isolation. They can be understood and re-rendered reliably precisely because all their incoming state comes via their attributes or via services.

Where you're using controllerFor or needs to access a parent controller, you would instead have the parent component explicitly pass attributes or action handlers downward.

Where you're using controllerFor or needs to access some completely separate controller elsewhere, that should probably become a shared service that is injected into both.

I should probably update the document to be explicit about the fate of controllerFor and modelFor. I think they go away entirely.

Contributor

ef4 commented Feb 28, 2015

@workmanw So we almost certainly don't want something like Ember.inject.component, because one of the key things about components is their isolation. They can be understood and re-rendered reliably precisely because all their incoming state comes via their attributes or via services.

Where you're using controllerFor or needs to access a parent controller, you would instead have the parent component explicitly pass attributes or action handlers downward.

Where you're using controllerFor or needs to access some completely separate controller elsewhere, that should probably become a shared service that is injected into both.

I should probably update the document to be explicit about the fate of controllerFor and modelFor. I think they go away entirely.

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Feb 28, 2015

Contributor

@jerel Any data manipulation an ArrayController was doing before can be done the same on the component instead. For example, if your component receives a model that is a list of people, it can derive a filteredPeople property to be rendered.

Your second question is harder to answer. I agree that we don't want to make it easy to break the URL. We already run this risk today as people build their own ad-hoc asynchronous components, but by making asynchronous components easier we may get more of them, in scenarios that really should have been reflected in the URL.

Contributor

ef4 commented Feb 28, 2015

@jerel Any data manipulation an ArrayController was doing before can be done the same on the component instead. For example, if your component receives a model that is a list of people, it can derive a filteredPeople property to be rendered.

Your second question is harder to answer. I agree that we don't want to make it easy to break the URL. We already run this risk today as people build their own ad-hoc asynchronous components, but by making asynchronous components easier we may get more of them, in scenarios that really should have been reflected in the URL.

@workmanw

This comment has been minimized.

Show comment
Hide comment
@workmanw

workmanw Feb 28, 2015

Contributor

@ef4

Where you're using controllerFor or needs to access a parent controller, you would instead have the parent component explicitly pass attributes or action handlers downward.

I guess the reason I struggle with this is because I don't know where this data would live. Like let's say I have a left nav that can be collapsed/expanded. Right now that is a boolean value on a controller high up in the ancestor chain. The controller for a leftnav uses needs and some of the routes use needs to get to the aforementioned controller. Now any controller can just do this.set('controllers.application.leftNavOpen', false');. But since I can't do needs and I can't do Ember.inject.component, where does that state live? How can components way down the chain change his application state.

Contributor

workmanw commented Feb 28, 2015

@ef4

Where you're using controllerFor or needs to access a parent controller, you would instead have the parent component explicitly pass attributes or action handlers downward.

I guess the reason I struggle with this is because I don't know where this data would live. Like let's say I have a left nav that can be collapsed/expanded. Right now that is a boolean value on a controller high up in the ancestor chain. The controller for a leftnav uses needs and some of the routes use needs to get to the aforementioned controller. Now any controller can just do this.set('controllers.application.leftNavOpen', false');. But since I can't do needs and I can't do Ember.inject.component, where does that state live? How can components way down the chain change his application state.

@chancancode

This comment has been minimized.

Show comment
Hide comment
@chancancode

chancancode Feb 28, 2015

Member

I really think it's important to differentiate between "I know what component I'm going to but I have work to do before I can show it" (async component) and "I have to do some work to do before I even know where I'm going" (route).

I think that differentiation makes sense.

The problem with doing all the routing in components is that there is often important work to do before you can even establish a component hierarchy. Authorization decisions, for example, are really nicely done in routes.

I think this will become even more significant as we work on lazily loading chunks of application. Routes are a natural place to manage decisions around what source code is even going to be needed, without having the components themselves present yet.

Those seems to be perfectly legit uses, too.

I think, what I am really getting at is the former ("I have work to do before I can show it") seems like a very common need for components in general, not just routable ones. Therefore, it appears (again, I am very much just speculating) to be a nice thing to be able to reconcile and always use the same pattern in both the routable and non-routable cases, whatever that API ended up looking like.

So, I agree there's very much still a need for routes. "80% common cases" is probably overstating it by a lot, but I mean "in the simple examples you see in the guides today (the blog app, or a github issue browser)", ideally you wouldn't/shouldn't have to touch the routes much, because those really just fall under "have work to do before I can show it".

I agree with @wycats that those two are separate things, and I think they are currently too coupled/easily confused today. If we can encourage a good separation of the two (something like, "routing decision should go into the routes", "data fetching should be in the component"), that would make a lot of sense to me.

This is basically the difference between what you put in your before_action in Rails controllers vs what you do in the body of your controller action. You can technically just have one or the other, but that would be mega confusing.

It could be that the work you to figure out your routing problems just so happens to give you the right data for display purposes, too. It should be possible to re-use those precious bits you downloaded for both purposes, but that feels it's technically more like an optimization (even though it is quite common) rather than the default way to reason about them ( => "since it's so common you should always do that in the routes").

By the way, I think the re-using data thing will be a problem outside of routable components, too. For example, in http://emberjs.jsbin.com/bujufi/1/edit, the {{ related-yelp-reviews }} component fetches a list of related reviews, and wants to reuse the {{ yelp-review }} component to display them. Since the list already has the data for displaying the reviews, you would want to pass those materialized models down instead of the IDs.

I'm not sure if the strawman API in the jsbin is really that great of an idea to accomplish this, but I am just saying this would need to be solved anyway, and that solution (whatever it turned out to be) is probably reusable in this case.


Edit: strawman Saturday – http://emberjs.jsbin.com/gadano/1/edit

(The framework "implementation" is obviously just HAX to fake the strawman API.)


Anyway! I don't usually look at or comment on these things, and I think my comments has very little to do with the concrete proposal you are making, so I hope they aren't too distracting from the real work that is going on here 😄 If this is counter-productive, I will very gladly move it to somewhere more appropriate 😄

Member

chancancode commented Feb 28, 2015

I really think it's important to differentiate between "I know what component I'm going to but I have work to do before I can show it" (async component) and "I have to do some work to do before I even know where I'm going" (route).

I think that differentiation makes sense.

The problem with doing all the routing in components is that there is often important work to do before you can even establish a component hierarchy. Authorization decisions, for example, are really nicely done in routes.

I think this will become even more significant as we work on lazily loading chunks of application. Routes are a natural place to manage decisions around what source code is even going to be needed, without having the components themselves present yet.

Those seems to be perfectly legit uses, too.

I think, what I am really getting at is the former ("I have work to do before I can show it") seems like a very common need for components in general, not just routable ones. Therefore, it appears (again, I am very much just speculating) to be a nice thing to be able to reconcile and always use the same pattern in both the routable and non-routable cases, whatever that API ended up looking like.

So, I agree there's very much still a need for routes. "80% common cases" is probably overstating it by a lot, but I mean "in the simple examples you see in the guides today (the blog app, or a github issue browser)", ideally you wouldn't/shouldn't have to touch the routes much, because those really just fall under "have work to do before I can show it".

I agree with @wycats that those two are separate things, and I think they are currently too coupled/easily confused today. If we can encourage a good separation of the two (something like, "routing decision should go into the routes", "data fetching should be in the component"), that would make a lot of sense to me.

This is basically the difference between what you put in your before_action in Rails controllers vs what you do in the body of your controller action. You can technically just have one or the other, but that would be mega confusing.

It could be that the work you to figure out your routing problems just so happens to give you the right data for display purposes, too. It should be possible to re-use those precious bits you downloaded for both purposes, but that feels it's technically more like an optimization (even though it is quite common) rather than the default way to reason about them ( => "since it's so common you should always do that in the routes").

By the way, I think the re-using data thing will be a problem outside of routable components, too. For example, in http://emberjs.jsbin.com/bujufi/1/edit, the {{ related-yelp-reviews }} component fetches a list of related reviews, and wants to reuse the {{ yelp-review }} component to display them. Since the list already has the data for displaying the reviews, you would want to pass those materialized models down instead of the IDs.

I'm not sure if the strawman API in the jsbin is really that great of an idea to accomplish this, but I am just saying this would need to be solved anyway, and that solution (whatever it turned out to be) is probably reusable in this case.


Edit: strawman Saturday – http://emberjs.jsbin.com/gadano/1/edit

(The framework "implementation" is obviously just HAX to fake the strawman API.)


Anyway! I don't usually look at or comment on these things, and I think my comments has very little to do with the concrete proposal you are making, so I hope they aren't too distracting from the real work that is going on here 😄 If this is counter-productive, I will very gladly move it to somewhere more appropriate 😄

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Feb 28, 2015

Contributor

@workmanw that's a good example. I see two possibilities, depending on your particular situation.

The default thing to do when you want to share state from a parent component down to some children is to pass mut attributes explicitly. The benefit is that this is completely transparent and there's never any mystery about where a state change is coming from. The downside is that it does require each intermediate level to explicitly pass the value onward to its own children.

The second option is for cases where you have some widely-shared state that doesn't make sense to pass everywhere explicitly, and you create a service to manage it. Services are intended to be the well-defined escape hatch for sharing state "sideways" through the application. You could make a "leftNav" service that is injected into all the components that need it, and they can all read and write the shared state through the service.

I think we need to publish more concrete details about services, because they are clearly critical for routeable components.

Contributor

ef4 commented Feb 28, 2015

@workmanw that's a good example. I see two possibilities, depending on your particular situation.

The default thing to do when you want to share state from a parent component down to some children is to pass mut attributes explicitly. The benefit is that this is completely transparent and there's never any mystery about where a state change is coming from. The downside is that it does require each intermediate level to explicitly pass the value onward to its own children.

The second option is for cases where you have some widely-shared state that doesn't make sense to pass everywhere explicitly, and you create a service to manage it. Services are intended to be the well-defined escape hatch for sharing state "sideways" through the application. You could make a "leftNav" service that is injected into all the components that need it, and they can all read and write the shared state through the service.

I think we need to publish more concrete details about services, because they are clearly critical for routeable components.

@workmanw

This comment has been minimized.

Show comment
Hide comment
@workmanw

workmanw Feb 28, 2015

Contributor

@ef4 Thanks for the back and forth. The first option would not be desirable for us, it would just create too much boilerplate because we have so many cases where descendant controllers contact ancestor controllers. The second option would be more ideal for us, but I'm not exaggerating when I say that 2/3 of my routes would end up with their own services.

It's possible that our app is in the minority, we have a lot of "dense" UI interactions, but the more I try to apply this API conceptually to our app, the more I feel like it's putting handcuffs on me. Things like action bubbling, controllerFor, modelFor, needs, Ember.inject.controller all made it easy to communicate top down and bottom up. It feels like this API proposal decouples and insulates the routes and components along the ancestry chain.

Again, hopefully this doesn't come off as negative. I'm just trying to provide honest feedback based on our needs and how we've used Ember. Thanks a lot for hearing me out! See you guys at Emberconf.

Contributor

workmanw commented Feb 28, 2015

@ef4 Thanks for the back and forth. The first option would not be desirable for us, it would just create too much boilerplate because we have so many cases where descendant controllers contact ancestor controllers. The second option would be more ideal for us, but I'm not exaggerating when I say that 2/3 of my routes would end up with their own services.

It's possible that our app is in the minority, we have a lot of "dense" UI interactions, but the more I try to apply this API conceptually to our app, the more I feel like it's putting handcuffs on me. Things like action bubbling, controllerFor, modelFor, needs, Ember.inject.controller all made it easy to communicate top down and bottom up. It feels like this API proposal decouples and insulates the routes and components along the ancestry chain.

Again, hopefully this doesn't come off as negative. I'm just trying to provide honest feedback based on our needs and how we've used Ember. Thanks a lot for hearing me out! See you guys at Emberconf.

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Feb 28, 2015

Contributor

@workmanw your concerns are totally appropriate and valid. We absolutely need to make sure the API is great for those scenarios. This discussion is the whole point of publishing RFCs.

Contributor

ef4 commented Feb 28, 2015

@workmanw your concerns are totally appropriate and valid. We absolutely need to make sure the API is great for those scenarios. This discussion is the whole point of publishing RFCs.

@jesse-black

This comment has been minimized.

Show comment
Hide comment
@jesse-black

jesse-black Feb 28, 2015

My questions:

  • Will it be possible to pass actions on the route to nested components without polluting the implementation of outer components to manually relay unrelated actions?
  • How will it handle reusable (from multiple routes) components that require operations on the ember-data store such as creating records? Right now the store is injected to controllers and we could create a controller to be reused from multiple routes. I assume the store won't be injected into components, so instead they will have to be handled on the top level application route if the components are to be used from multiple routes. It seems like this will lead to a bloated application route full of unrelated functionality to support multiple components like this.

jesse-black commented Feb 28, 2015

My questions:

  • Will it be possible to pass actions on the route to nested components without polluting the implementation of outer components to manually relay unrelated actions?
  • How will it handle reusable (from multiple routes) components that require operations on the ember-data store such as creating records? Right now the store is injected to controllers and we could create a controller to be reused from multiple routes. I assume the store won't be injected into components, so instead they will have to be handled on the top level application route if the components are to be used from multiple routes. It seems like this will lead to a bloated application route full of unrelated functionality to support multiple components like this.
@davidlormor

This comment has been minimized.

Show comment
Hide comment
@davidlormor

davidlormor Mar 1, 2015

First off, let me say great job with RFC 👍 - this deals with some of the issues I've run into moving to a component-oriented structure (on v1.10 right now). In particular, async components is a much needed addition - this is a friction point I've run into many times now. Also, glad to see the transition to a singular attributes hook vs. the current beforeModel, model, afterModel implementation with no clear way to "force" reload of model data.

Just wanted point out one method I've come across that never seems to be mentioned (this might be of use for @workmanw re: action bubbling). There seems to be quite a bit of confusion/worry/apprehensiveness in the discussions around having to explicitly pass in methods to a component.

There is another way...although I seem to be the only one advocating this (wondering if I'm missing something...): using the 'targetObject' property allows you to access the current parent when a component is inserted into the DOM. The example that I use (a common pattern in my application) is the cancel button (JS Bin). As you can see, I don't have to pass in the action, but rather the action is fired from the component with assumption that it will be handled up the chain. Curious to hear any thoughts on this method of firing actions, and what might be done to improve upon this way of action "bubbling." Perhaps borrowing from the ideas presented in the Flux architecture about having a single "action dispatcher"?

Also...very much this (from @ef4):

I think we need to publish more concrete details about services, because they are clearly critical for routeable components.

I can definitely see the value in the services concept, but details are vague at best around how they work...would be happy to help make them a "first-class citizen" if someone could point me in the right direction.

davidlormor commented Mar 1, 2015

First off, let me say great job with RFC 👍 - this deals with some of the issues I've run into moving to a component-oriented structure (on v1.10 right now). In particular, async components is a much needed addition - this is a friction point I've run into many times now. Also, glad to see the transition to a singular attributes hook vs. the current beforeModel, model, afterModel implementation with no clear way to "force" reload of model data.

Just wanted point out one method I've come across that never seems to be mentioned (this might be of use for @workmanw re: action bubbling). There seems to be quite a bit of confusion/worry/apprehensiveness in the discussions around having to explicitly pass in methods to a component.

There is another way...although I seem to be the only one advocating this (wondering if I'm missing something...): using the 'targetObject' property allows you to access the current parent when a component is inserted into the DOM. The example that I use (a common pattern in my application) is the cancel button (JS Bin). As you can see, I don't have to pass in the action, but rather the action is fired from the component with assumption that it will be handled up the chain. Curious to hear any thoughts on this method of firing actions, and what might be done to improve upon this way of action "bubbling." Perhaps borrowing from the ideas presented in the Flux architecture about having a single "action dispatcher"?

Also...very much this (from @ef4):

I think we need to publish more concrete details about services, because they are clearly critical for routeable components.

I can definitely see the value in the services concept, but details are vague at best around how they work...would be happy to help make them a "first-class citizen" if someone could point me in the right direction.

@sandstrom

This comment has been minimized.

Show comment
Hide comment
@sandstrom

sandstrom Mar 1, 2015

Interesting, I think this is great overall – very much looking forward to it!

Two thoughts:

  1. beforeModel has quite a few uses besides those mentioned in the RFC. One example is pausing to setup authentication[1], which must occur before calling the model hook. And moving that to say an initializer isn't ideal, because it's common that only certain routes are authenticated (requires auth).

    Will there still be a promise-aware hook to handle such cases?
    (if not I vote for keeping beforeModel)

    One great thing with Ember is that it's easy to customize (hooks are a part of this). Perhaps one could keep both beforeModel and afterModel (possibly under different names) since they have use-cases not directly tied to models.

  2. Under drawbacks it's mentioned that:

    "[it] makes the framework [..] opinionated about [...] Routes. For example, they can no longer render into outlets at arbitrary times."

    I think modals are commonly handled by having the application route (or another route) rendering into a specific 'modal outlet'. I don't have a clear idea of how that should be handled, but it would be great if that use-case is given some thought.

    I'm not a fan of modals and think they should be avoided, but to be fair they also have their use-cases.

[1] https://github.com/simplabs/ember-simple-auth/blob/master/packages/ember-simple-auth/lib/simple-auth/mixins/authenticated-route-mixin.js#L42

sandstrom commented Mar 1, 2015

Interesting, I think this is great overall – very much looking forward to it!

Two thoughts:

  1. beforeModel has quite a few uses besides those mentioned in the RFC. One example is pausing to setup authentication[1], which must occur before calling the model hook. And moving that to say an initializer isn't ideal, because it's common that only certain routes are authenticated (requires auth).

    Will there still be a promise-aware hook to handle such cases?
    (if not I vote for keeping beforeModel)

    One great thing with Ember is that it's easy to customize (hooks are a part of this). Perhaps one could keep both beforeModel and afterModel (possibly under different names) since they have use-cases not directly tied to models.

  2. Under drawbacks it's mentioned that:

    "[it] makes the framework [..] opinionated about [...] Routes. For example, they can no longer render into outlets at arbitrary times."

    I think modals are commonly handled by having the application route (or another route) rendering into a specific 'modal outlet'. I don't have a clear idea of how that should be handled, but it would be great if that use-case is given some thought.

    I'm not a fan of modals and think they should be avoided, but to be fair they also have their use-cases.

[1] https://github.com/simplabs/ember-simple-auth/blob/master/packages/ember-simple-auth/lib/simple-auth/mixins/authenticated-route-mixin.js#L42

mitchlloyd added a commit to mitchlloyd/realtime-metro-web-client that referenced this pull request Mar 2, 2015

Update arrivals outside of model hook
The loading message was showing when it shouldn’t have.

This can’t come soon enough: emberjs/rfcs#38
@tim-evans

This comment has been minimized.

Show comment
Hide comment
@tim-evans

tim-evans Mar 2, 2015

I have a few thoughts around the mut keyword. First of all, it's strange to consider something mutable v. not mutable, since Ember doesn't use immutable objects. Is mutable the wrong word for what's being expressed here?

In addition, I'm not sure if I buy the use cases. Can someone explain to me the pain points that are solved by using mut? For a developer like myself, it adds a lot of friction with development. I'm all on board with making Ember great for new devs, but handicapping experienced devs seems like it's not the right approach. I'm confident that I know whats mutating what, and I'm not scared of 3rd party addons that consume my data, for two reasons. 1) The pool of addons is small and 2) They can access any data in my app by rummaging through my app's container and registry.

I think the question here is, what perks do experienced Ember devs get out of this change?

(Btw, I think this is great. Thanks for doing the hard work of formalizing this 👍 )

tim-evans commented Mar 2, 2015

I have a few thoughts around the mut keyword. First of all, it's strange to consider something mutable v. not mutable, since Ember doesn't use immutable objects. Is mutable the wrong word for what's being expressed here?

In addition, I'm not sure if I buy the use cases. Can someone explain to me the pain points that are solved by using mut? For a developer like myself, it adds a lot of friction with development. I'm all on board with making Ember great for new devs, but handicapping experienced devs seems like it's not the right approach. I'm confident that I know whats mutating what, and I'm not scared of 3rd party addons that consume my data, for two reasons. 1) The pool of addons is small and 2) They can access any data in my app by rummaging through my app's container and registry.

I think the question here is, what perks do experienced Ember devs get out of this change?

(Btw, I think this is great. Thanks for doing the hard work of formalizing this 👍 )

@slindberg

This comment has been minimized.

Show comment
Hide comment
@slindberg

slindberg Mar 3, 2015

Huge thanks to @ef4 for tackling the most challenging of all changes in 2.0. 🍻

However, we can simplify all of this by moving the problem of avoiding model reloading into the data layer. ember-data is already capable of sufficiently intelligent caching.

I really like the idea of the model hook being idempotent; it makes complete sense take advantage of a data store's identity map. However I don't see this working well for routes that have model hooks that find record collections. For instance, say a route does something like this:

// app/routes/things/index.js
export default Ember.Route.extend({
  model: function() {
    return this.store.findAll('things');
  }
});

Does this mean that when query params are updated on the things.index route, a transition is triggered and all records are re-requested? Ember Data could do a slightly better job here of knowing if all records have been fetched previously, but the point still stands for things like store.findQuery({ ... }).

Therefore, we can collapse the three hooks down to a single model hook that always fires regardless of whether the transition references a model or an id

Does this mean that the first parameter to model is a params hash sometimes and a model other times? This seems backwards incompatible. EDIT: silly question

slindberg commented Mar 3, 2015

Huge thanks to @ef4 for tackling the most challenging of all changes in 2.0. 🍻

However, we can simplify all of this by moving the problem of avoiding model reloading into the data layer. ember-data is already capable of sufficiently intelligent caching.

I really like the idea of the model hook being idempotent; it makes complete sense take advantage of a data store's identity map. However I don't see this working well for routes that have model hooks that find record collections. For instance, say a route does something like this:

// app/routes/things/index.js
export default Ember.Route.extend({
  model: function() {
    return this.store.findAll('things');
  }
});

Does this mean that when query params are updated on the things.index route, a transition is triggered and all records are re-requested? Ember Data could do a slightly better job here of knowing if all records have been fetched previously, but the point still stands for things like store.findQuery({ ... }).

Therefore, we can collapse the three hooks down to a single model hook that always fires regardless of whether the transition references a model or an id

Does this mean that the first parameter to model is a params hash sometimes and a model other times? This seems backwards incompatible. EDIT: silly question

@kimroen

This comment has been minimized.

Show comment
Hide comment
@kimroen

kimroen Mar 3, 2015

Does this mean that the first parameter to model is a params hash sometimes and a model other times? This seems backwards incompatible.

@slindberg I think this was referring to the way link-to, transitionTo and friends currently either fire or don't fire the model hook depending on if the passed in reference are params or a model, and that it will now fire either way. I don't think the parameters passed to model changes.

kimroen commented Mar 3, 2015

Does this mean that the first parameter to model is a params hash sometimes and a model other times? This seems backwards incompatible.

@slindberg I think this was referring to the way link-to, transitionTo and friends currently either fire or don't fire the model hook depending on if the passed in reference are params or a model, and that it will now fire either way. I don't think the parameters passed to model changes.

@slindberg

This comment has been minimized.

Show comment
Hide comment
@slindberg

slindberg Mar 3, 2015

I don't think the parameters passed to model changes.

You're right, they just can't change. I guess this just means that the params will need to be extracted from the model when passed in via link-to or transitionTo.

slindberg commented Mar 3, 2015

I don't think the parameters passed to model changes.

You're right, they just can't change. I guess this just means that the params will need to be extracted from the model when passed in via link-to or transitionTo.

@kimroen

This comment has been minimized.

Show comment
Hide comment
@kimroen

kimroen Mar 3, 2015

You're right, they just can't change. I guess this just means that the params will need to be extracted from the model when passed in via link-to or transitionTo.

Yes, just like Ember.Route#serialize already does to construct the URL from the passed in model.

kimroen commented Mar 3, 2015

You're right, they just can't change. I guess this just means that the params will need to be extracted from the model when passed in via link-to or transitionTo.

Yes, just like Ember.Route#serialize already does to construct the URL from the passed in model.

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Mar 6, 2015

Contributor

In response to @sandstrom 's question:

beforeModel has quite a few uses besides those mentioned in the RFC. One example is pausing to setup authentication[1], which must occur before calling the model hook.

As long as the model hook is always called, you can encapsulate that behavior inside the model hook itself:

  model: function(params) {
    return setupMyAuthentication().then(() => MyModel.find(params));
  }

The only reason we had to have a separate beforeModel in the current system is that you couldn't rely on model always running.

Contributor

ef4 commented Mar 6, 2015

In response to @sandstrom 's question:

beforeModel has quite a few uses besides those mentioned in the RFC. One example is pausing to setup authentication[1], which must occur before calling the model hook.

As long as the model hook is always called, you can encapsulate that behavior inside the model hook itself:

  model: function(params) {
    return setupMyAuthentication().then(() => MyModel.find(params));
  }

The only reason we had to have a separate beforeModel in the current system is that you couldn't rely on model always running.

@sandstrom

This comment has been minimized.

Show comment
Hide comment
@sandstrom

sandstrom Mar 6, 2015

@ef4 I agree that's a way of solving it.

However, I like that Ember has hooks for common things, e.g. willDestroy, didInsertElement and didTransition. I think it's convenient with hooks for common things, instead of having to call this._super() in the model method of all child classes (needed if using a mixin or ancestor class).

I argue in favor of keeping these hooks.

sandstrom commented Mar 6, 2015

@ef4 I agree that's a way of solving it.

However, I like that Ember has hooks for common things, e.g. willDestroy, didInsertElement and didTransition. I think it's convenient with hooks for common things, instead of having to call this._super() in the model method of all child classes (needed if using a mixin or ancestor class).

I argue in favor of keeping these hooks.

@mitchlloyd

This comment has been minimized.

Show comment
Hide comment
@mitchlloyd

mitchlloyd Mar 12, 2015

@workmanw I think that particular modal pattern is going to be simpler now that we have better components and better thought technology around them ("data down actions up").

We, like many other people, have been using this approach to modals: http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/ This would break this pattern. That's okay with me, I didn't really love it. But I'm wondering if there is an alternative. Maybe using a ContainerView as modal manager.

I was planning to update that guide as soon as the foo={{action 'bar'}} syntax lands (it's noted on the Glimmer branch). Here is a hacky version: http://emberjs.jsbin.com/cisoko/5/edit?html,js,output

mitchlloyd commented Mar 12, 2015

@workmanw I think that particular modal pattern is going to be simpler now that we have better components and better thought technology around them ("data down actions up").

We, like many other people, have been using this approach to modals: http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/ This would break this pattern. That's okay with me, I didn't really love it. But I'm wondering if there is an alternative. Maybe using a ContainerView as modal manager.

I was planning to update that guide as soon as the foo={{action 'bar'}} syntax lands (it's noted on the Glimmer branch). Here is a hacky version: http://emberjs.jsbin.com/cisoko/5/edit?html,js,output

@workmanw

This comment has been minimized.

Show comment
Hide comment
@workmanw

workmanw Mar 12, 2015

Contributor

@mitchlloyd Well I was referring to the fact that you can no longer call render outside of the normal render hook. With the cook book example you'd call render in an action handler to insert a modal into an outlet. With this change, you'll have to have all modals rendered into outlets up front.

So I've been experimenting with building a ModalManager which is really just a ContainerView that binds to a ModalService. Allowing anyone with access to the service to open one or more modals that end up stacked.

Contributor

workmanw commented Mar 12, 2015

@mitchlloyd Well I was referring to the fact that you can no longer call render outside of the normal render hook. With the cook book example you'd call render in an action handler to insert a modal into an outlet. With this change, you'll have to have all modals rendered into outlets up front.

So I've been experimenting with building a ModalManager which is really just a ContainerView that binds to a ModalService. Allowing anyone with access to the service to open one or more modals that end up stacked.

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Mar 12, 2015

Contributor

@workmanw I think that's a good approach. Liquid Fire already uses a modal service in the same way. It's probably something we can abstract into a shared addon.

Contributor

ef4 commented Mar 12, 2015

@workmanw I think that's a good approach. Liquid Fire already uses a modal service in the same way. It's probably something we can abstract into a shared addon.

attributes: function(params, queryParams) {
return {
model: this.model(params)
}

This comment has been minimized.

@stefanpenner

stefanpenner Mar 14, 2015

Member

missing: ;

@stefanpenner

stefanpenner Mar 14, 2015

Member

missing: ;

that are present get stuffed directly into the attributes as well,
alongside `model`.)
Unlike today's `model` hook, `attributes` gets called *every* time

This comment has been minimized.

@stefanpenner
@stefanpenner
it up to Ember to optimize.
For cases where you really need to do something different on initial
render, the existing `activate` action will still reliably fire only

This comment has been minimized.

@stefanpenner

stefanpenner Mar 14, 2015

Member

seems strange for this to be an action that could also bubble up

@stefanpenner

stefanpenner Mar 14, 2015

Member

seems strange for this to be an action that could also bubble up

when a route is first entered, after Ember invokes your `attributes`
method.
We will add a complementary `update` action that fires after your

This comment has been minimized.

@stefanpenner

stefanpenner Mar 14, 2015

Member

same as ^

@stefanpenner

stefanpenner Mar 14, 2015

Member

same as ^

### Loading and error states

This comment has been minimized.

@stefanpenner

stefanpenner Mar 14, 2015

Member

same as ^

seems like these should be methods, not actions/

@stefanpenner

stefanpenner Mar 14, 2015

Member

same as ^

seems like these should be methods, not actions/

upward unless you explicitly tell them to. Routable components
preserve this same behavior.
Therefore, if you want to send an action from a component up to the

This comment has been minimized.

@stefanpenner

stefanpenner Mar 14, 2015

Member

so like ?

attributes( ) {
  return {
    save: this.actions.save
  };
},

actions: {
   async save(name) {
    await this.store.createRecord('user', { name });
   }
}
@stefanpenner

stefanpenner Mar 14, 2015

Member

so like ?

attributes( ) {
  return {
    save: this.actions.save
  };
},

actions: {
   async save(name) {
    await this.store.createRecord('user', { name });
   }
}
````js
queryParams: {
foo: { as: 'bar', default: 0 }

This comment has been minimized.

@stefanpenner

stefanpenner Mar 14, 2015

Member

we should describe the behaviour around unsetting and re-defaulting if it the value becomes undefined

@stefanpenner

stefanpenner Mar 14, 2015

Member

we should describe the behaviour around unsetting and re-defaulting if it the value becomes undefined

@mixonic

This comment has been minimized.

Show comment
Hide comment
@mixonic

mixonic Mar 14, 2015

Member

@ef4 awesome writeup, very clear and thoughtful thanks :-)

attributes vs. attrs

At the component level, we talk about a component having this.attrs as a bucket for data passed down. I find the distinction between attrs (the data bucket) and attributes (the attributes of your shadowed elements) to be really useful when building a mental model. The word attributes is already so overloaded that I'm wary of adding it again at the model level.

Would you consider changing the route hook to be getAttrs or initialAttrs, or generally something that ties it more directly to the component-level concept? Conventionally it would mean most of your uses of "attibutes" in this document would become "attrs".

Happy to PR something against your branch.

semantic argument for beforeModel

Merging beforeModel, model, and afterModel is definitely possible. Where do you see something like authentication going? It seems a poor pattern to suggest that devs throw authorization into a hook named attributes. I can foresee some nightmarishly complex attributes functions.

But since attributes runs on every transition, it doesn't seem the correct place to validate entrance into a route anyway. activate is not an asynchronous hook on the routes, though it fires at the correct time. Could activate be made async? Or can we preserve a hook semantically equivalent to beforeModel? validateEntrance?

Member

mixonic commented Mar 14, 2015

@ef4 awesome writeup, very clear and thoughtful thanks :-)

attributes vs. attrs

At the component level, we talk about a component having this.attrs as a bucket for data passed down. I find the distinction between attrs (the data bucket) and attributes (the attributes of your shadowed elements) to be really useful when building a mental model. The word attributes is already so overloaded that I'm wary of adding it again at the model level.

Would you consider changing the route hook to be getAttrs or initialAttrs, or generally something that ties it more directly to the component-level concept? Conventionally it would mean most of your uses of "attibutes" in this document would become "attrs".

Happy to PR something against your branch.

semantic argument for beforeModel

Merging beforeModel, model, and afterModel is definitely possible. Where do you see something like authentication going? It seems a poor pattern to suggest that devs throw authorization into a hook named attributes. I can foresee some nightmarishly complex attributes functions.

But since attributes runs on every transition, it doesn't seem the correct place to validate entrance into a route anyway. activate is not an asynchronous hook on the routes, though it fires at the correct time. Could activate be made async? Or can we preserve a hook semantically equivalent to beforeModel? validateEntrance?

@ebryn

This comment has been minimized.

Show comment
Hide comment
@ebryn

ebryn Aug 11, 2015

Member

@workmanw I believe the solution to your problem is to inject the routing service and subscribe to a willTransition event on your component

Member

ebryn commented Aug 11, 2015

@workmanw I believe the solution to your problem is to inject the routing service and subscribe to a willTransition event on your component

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Aug 11, 2015

Contributor

Yes, it's the editor component that holds the unsaved state, and that's where you want to be configuring rules for not accidentally dropping that state. It's not really a property of the current route at all.

Contributor

ef4 commented Aug 11, 2015

Yes, it's the editor component that holds the unsaved state, and that's where you want to be configuring rules for not accidentally dropping that state. It's not really a property of the current route at all.

@workmanw

This comment has been minimized.

Show comment
Hide comment
@workmanw

workmanw Aug 11, 2015

Contributor

@ebryn @ef4 @mitchlloyd Yea, I completely agree that it's the component who is really responsible for making the decision about preventing route transition, I just wasn't sure how that API would look. Using the router service makes sense to me. Hopefully it will be publicized around the same time as routable components.

Thanks for weighing in!

Contributor

workmanw commented Aug 11, 2015

@ebryn @ef4 @mitchlloyd Yea, I completely agree that it's the component who is really responsible for making the decision about preventing route transition, I just wasn't sure how that API would look. Using the router service makes sense to me. Hopefully it will be publicized around the same time as routable components.

Thanks for weighing in!

@knownasilya

This comment has been minimized.

Show comment
Hide comment
@knownasilya

knownasilya Aug 11, 2015

Contributor

What's the router/routing service? Any RFCs or discussions I can have a look at?

Contributor

knownasilya commented Aug 11, 2015

What's the router/routing service? Any RFCs or discussions I can have a look at?

@2468ben

This comment has been minimized.

Show comment
Hide comment
@2468ben

2468ben Aug 11, 2015

Oh, the "routing service" :)

This year of Ember has been like going on a long trip to somewhere, sometime, for a while, and we'll tell you more as we get there but all your friends are going

You should pack everything you can think of and expect to throw out almost all of it once we get there. But your tour guides are friendly and the New World is gonna be awesome

Oh, did you pack for the snow we forgot to mention the snow

And the bears

2468ben commented Aug 11, 2015

Oh, the "routing service" :)

This year of Ember has been like going on a long trip to somewhere, sometime, for a while, and we'll tell you more as we get there but all your friends are going

You should pack everything you can think of and expect to throw out almost all of it once we get there. But your tour guides are friendly and the New World is gonna be awesome

Oh, did you pack for the snow we forgot to mention the snow

And the bears

@wycats

This comment has been minimized.

Show comment
Hide comment
@wycats

wycats Aug 11, 2015

Member

@2468ben I'm really sorry you feel that way. We have worked somewhat hard to try to avoid regressions from what you're already doing (we were careful not to deprecate anything without a way to immediately transition to something else), while laying out a somewhat long-term sense of where we're going.

In retrospect, all of that long-term discussion has created the "road trip" sense. I'm curious: is there some way that we have broken an existing pattern that you were using that requires the "routing service" to work again? Or is the frustration just that the solution for certain questions that are not yet supported often ends up being a long-term proposal that we haven't yet started to work on?

Either of those is a problem, of course.

Member

wycats commented Aug 11, 2015

@2468ben I'm really sorry you feel that way. We have worked somewhat hard to try to avoid regressions from what you're already doing (we were careful not to deprecate anything without a way to immediately transition to something else), while laying out a somewhat long-term sense of where we're going.

In retrospect, all of that long-term discussion has created the "road trip" sense. I'm curious: is there some way that we have broken an existing pattern that you were using that requires the "routing service" to work again? Or is the frustration just that the solution for certain questions that are not yet supported often ends up being a long-term proposal that we haven't yet started to work on?

Either of those is a problem, of course.

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Aug 11, 2015

Contributor

@2468ben This repo is for discussing the future. It's entirely appropriate for concepts to pop up here that aren't documented or implemented anywhere else yet.

but all your friends are going

It's true that we celebrate teams that manage to stay on the bleeding edge. But we celebrate them for a reason: it's hard to do.

People should not be feeling pressured to live on the bleeding edge. There is zero risk in sticking with stable 1.x APIs for as long as you need to. We are committed to providing security support for the 1.x branch for the foreseeable future, because we know many apps will continue to run it until 2.x has time to bake and stabilize.

Contributor

ef4 commented Aug 11, 2015

@2468ben This repo is for discussing the future. It's entirely appropriate for concepts to pop up here that aren't documented or implemented anywhere else yet.

but all your friends are going

It's true that we celebrate teams that manage to stay on the bleeding edge. But we celebrate them for a reason: it's hard to do.

People should not be feeling pressured to live on the bleeding edge. There is zero risk in sticking with stable 1.x APIs for as long as you need to. We are committed to providing security support for the 1.x branch for the foreseeable future, because we know many apps will continue to run it until 2.x has time to bake and stabilize.

@2468ben

This comment has been minimized.

Show comment
Hide comment
@2468ben

2468ben Aug 11, 2015

Don't worry, I'm fine! I was hoping that by typing a smiley face plus the phrase "and the bears" into a github thread, I could communicate that I'm being lighthearted about this whole situation. Ember is a community-created cutting-edge open-source project, and everyone expects a ever-evolving thing with ever-shifting goalposts. I'd say I'm 1% frustrated at Ember, and 99% frustrated at how it's impossible to sound lighthearted online.

2468ben commented Aug 11, 2015

Don't worry, I'm fine! I was hoping that by typing a smiley face plus the phrase "and the bears" into a github thread, I could communicate that I'm being lighthearted about this whole situation. Ember is a community-created cutting-edge open-source project, and everyone expects a ever-evolving thing with ever-shifting goalposts. I'd say I'm 1% frustrated at Ember, and 99% frustrated at how it's impossible to sound lighthearted online.

@mitchlloyd

This comment has been minimized.

Show comment
Hide comment
@mitchlloyd

mitchlloyd Aug 11, 2015

@2468ben You had me laughing out loud and I took it as lighthearted :)

mitchlloyd commented Aug 11, 2015

@2468ben You had me laughing out loud and I took it as lighthearted :)

@2468ben

This comment has been minimized.

Show comment
Hide comment
@2468ben

2468ben Aug 11, 2015

-- Take all of this with the same lighthearted tone please --

To be fair, there is absolutely pressure to live on the bleeding edge, and I'm not even living there. I'm on Ember 1.11, Ember Data beta 15, ember cli 0.2.3, and a couple addons that are still compatible.

I could have stayed away from ember-cli, but after a year of being told in every official and non-official resource why I should totally use it, why the future would be devoted to it, why it would be in lockstep with core Ember, and why all useful addons/plugins would move to it, I spent the weeks to migrate. For two different companies. That's a decent hunk of pressure especially for software that was still technically alpha.

I could have stayed away from the regular requests to run in beta and canary whenever possible to help fix bugs, although that was only slight pressure. I helped out with 1.0-1.7 but couldn't handle it this time around and checking the daily changelogs.

I could stay away from 1.13 and all of the breaking changes needed upgrading Ember Data and my addons, with the only downside being that the addons have some bugs that probably won't be fixed for 1.11. The whole Ember addon "ecosystem" is tremendous, but by the time an addon bug is fixed, it might only work under a newer collection of lockstep Ember core libraries, in which case we work to update all of them together. In that sense there is upgrade pressure, with the alternative being to fork addons and fix the bugs for your version. Of course this applies everywhere in software, just faster nowadays.

This is an amazing framework, and not surprisingly those of us who use it are building big, important, job-dependent things. And it's a job priority to reach for a stable framework whenever possible. After riding the Ember data beta train and ember-cli alpha train for months/years, there is a lot of external company pressure to tell your customers you're running the stable versions of code. And internal company pressure that you're running code versions that a coworker can find docs or stackoverflow answers for, in case they're new to the game.

There might be a little peer pressure in the Ember community to try the latest and greatest things, but it's the stability + "does any answer match my stack" that is the real vocational pressure. For everyone not at the 1.13-for-everything, if I say I'm under pressure, I mean overwhelming vocational pressure, and I thank the community for making the 1.13 ecosystem and taking that pressure off. Until everyone gets there, some of us may get cranky and need a nap (or alcohol).

For @wycats and the core team, here's why the "routing service" (which, great idea, thanks to all involved) and other soon-to-be-released features made me write a joke on Github: I'm trying to plan for the future just like everyone else, even if I'm sticking on 1.11 for a while. But when I'm in the code building a big new feature, of course I want to write it with components and services and in a way that won't need a big rewrite or a feature freeze! When I read the Road to 2.X or all the blog posts on preparing for the new architecture, I'd be a bad engineer if I said "to hell with my company's future, I'll write things the deprecated way". So I build my new features in a way that seems compatible for the (1 month or 1 year later) migration 2.x, in case my company ever really needs something in 2.x. Not all the features are there yet so I make a few mixins or utilities that serve as unofficial bridges, knowing that eventually Ember will release the official way.

So when I've built much of my app towards what Ember evangelizes is the future, I'm always guessing a little. And when the answer appears out of nowhere like the "routing service", I have to laugh because I can't believe I never guessed there would be a routing service! And I laugh because some custom mixins and utilities I made in preparation are now totally disposable. And I laugh because I have no idea if the routing service will disappear before 2.2, or if it will appear but not until 2.4, or what else will change by then. It's the joy and slight craziness of building with the future in mind: every time I write new code, I imagine I'm playing mini-golf with my eyes closed :)

If the routing service will solve our problem when Routeable Components come out, then awesome. But until then, I'll still want to code my present/future features in a compatible way, and what function or mixin could be a great "stand-in" that's easiest to refactor once this all is live?

2468ben commented Aug 11, 2015

-- Take all of this with the same lighthearted tone please --

To be fair, there is absolutely pressure to live on the bleeding edge, and I'm not even living there. I'm on Ember 1.11, Ember Data beta 15, ember cli 0.2.3, and a couple addons that are still compatible.

I could have stayed away from ember-cli, but after a year of being told in every official and non-official resource why I should totally use it, why the future would be devoted to it, why it would be in lockstep with core Ember, and why all useful addons/plugins would move to it, I spent the weeks to migrate. For two different companies. That's a decent hunk of pressure especially for software that was still technically alpha.

I could have stayed away from the regular requests to run in beta and canary whenever possible to help fix bugs, although that was only slight pressure. I helped out with 1.0-1.7 but couldn't handle it this time around and checking the daily changelogs.

I could stay away from 1.13 and all of the breaking changes needed upgrading Ember Data and my addons, with the only downside being that the addons have some bugs that probably won't be fixed for 1.11. The whole Ember addon "ecosystem" is tremendous, but by the time an addon bug is fixed, it might only work under a newer collection of lockstep Ember core libraries, in which case we work to update all of them together. In that sense there is upgrade pressure, with the alternative being to fork addons and fix the bugs for your version. Of course this applies everywhere in software, just faster nowadays.

This is an amazing framework, and not surprisingly those of us who use it are building big, important, job-dependent things. And it's a job priority to reach for a stable framework whenever possible. After riding the Ember data beta train and ember-cli alpha train for months/years, there is a lot of external company pressure to tell your customers you're running the stable versions of code. And internal company pressure that you're running code versions that a coworker can find docs or stackoverflow answers for, in case they're new to the game.

There might be a little peer pressure in the Ember community to try the latest and greatest things, but it's the stability + "does any answer match my stack" that is the real vocational pressure. For everyone not at the 1.13-for-everything, if I say I'm under pressure, I mean overwhelming vocational pressure, and I thank the community for making the 1.13 ecosystem and taking that pressure off. Until everyone gets there, some of us may get cranky and need a nap (or alcohol).

For @wycats and the core team, here's why the "routing service" (which, great idea, thanks to all involved) and other soon-to-be-released features made me write a joke on Github: I'm trying to plan for the future just like everyone else, even if I'm sticking on 1.11 for a while. But when I'm in the code building a big new feature, of course I want to write it with components and services and in a way that won't need a big rewrite or a feature freeze! When I read the Road to 2.X or all the blog posts on preparing for the new architecture, I'd be a bad engineer if I said "to hell with my company's future, I'll write things the deprecated way". So I build my new features in a way that seems compatible for the (1 month or 1 year later) migration 2.x, in case my company ever really needs something in 2.x. Not all the features are there yet so I make a few mixins or utilities that serve as unofficial bridges, knowing that eventually Ember will release the official way.

So when I've built much of my app towards what Ember evangelizes is the future, I'm always guessing a little. And when the answer appears out of nowhere like the "routing service", I have to laugh because I can't believe I never guessed there would be a routing service! And I laugh because some custom mixins and utilities I made in preparation are now totally disposable. And I laugh because I have no idea if the routing service will disappear before 2.2, or if it will appear but not until 2.4, or what else will change by then. It's the joy and slight craziness of building with the future in mind: every time I write new code, I imagine I'm playing mini-golf with my eyes closed :)

If the routing service will solve our problem when Routeable Components come out, then awesome. But until then, I'll still want to code my present/future features in a compatible way, and what function or mixin could be a great "stand-in" that's easiest to refactor once this all is live?

@mitchlloyd

This comment has been minimized.

Show comment
Hide comment
@mitchlloyd

mitchlloyd Aug 11, 2015

@2468ben Just know that you are not alone here, Ember users feel this pain every day. We're building mental models around how Ember ought to work and then it's up to the community and the core team to get us there. The value proposition of Ember is that we can change the framework without throwing it away, but it requires a lot of careful work and experimentation.

The best case scenario is that when you feel this pain, you would have the time and motivation to get involved and familiar with Ember and then help move it to where we want it. I know that not everyone can do that but in my experience, if you do have the desire, the Ember core team is really good at getting people involved. Maybe you could hold the torch for getting the routing service in a better place?

No pressure 😉

mitchlloyd commented Aug 11, 2015

@2468ben Just know that you are not alone here, Ember users feel this pain every day. We're building mental models around how Ember ought to work and then it's up to the community and the core team to get us there. The value proposition of Ember is that we can change the framework without throwing it away, but it requires a lot of careful work and experimentation.

The best case scenario is that when you feel this pain, you would have the time and motivation to get involved and familiar with Ember and then help move it to where we want it. I know that not everyone can do that but in my experience, if you do have the desire, the Ember core team is really good at getting people involved. Maybe you could hold the torch for getting the routing service in a better place?

No pressure 😉

@2468ben

This comment has been minimized.

Show comment
Hide comment
@2468ben

2468ben Aug 11, 2015

@mitchlloyd Thanks for the response, I honestly am fine with wherever Ember wants to go, and however they decide to get there. I've built a few frameworks before this but I decided to focus 100% on end products, and to work with whatever big tools are out there. I have zero disagreement with any architecture or implementation decision that Ember has made; my passion is using their great decisions to build my product.

So instead of influencing the eventual routing service implementation, I really just want to know if there's something I could do to get 1.x code more compatible with the parts that are already ironed out.
Lots of changes are "mechanical" or easily explained in a few lines of blog post, but routeable components is a big one and the RFC hasn't been updated since February, so maybe there's a really quick update someone could give, even if it's "not sure yet". Something to tide us over for a few months until there's a blog post.

  • Currently planning to land in 2.2, 2.3 or later?
  • There was an announcement somewhere that a 'first step' landed in Canary, any link or short answer if that's for public use?
  • Is the routing service a pretty sure thing, and will it be pretty much like the old Router or something alongside it?
  • Anything else in the RFC you'd say has changed a lot and is worth mentioning? If there is, do you have a quick idea/suggestion for a 'prefactor' or pattern that might help ease the breaking change? Like "move your controller logic to a component if you want to get a headstart".

2468ben commented Aug 11, 2015

@mitchlloyd Thanks for the response, I honestly am fine with wherever Ember wants to go, and however they decide to get there. I've built a few frameworks before this but I decided to focus 100% on end products, and to work with whatever big tools are out there. I have zero disagreement with any architecture or implementation decision that Ember has made; my passion is using their great decisions to build my product.

So instead of influencing the eventual routing service implementation, I really just want to know if there's something I could do to get 1.x code more compatible with the parts that are already ironed out.
Lots of changes are "mechanical" or easily explained in a few lines of blog post, but routeable components is a big one and the RFC hasn't been updated since February, so maybe there's a really quick update someone could give, even if it's "not sure yet". Something to tide us over for a few months until there's a blog post.

  • Currently planning to land in 2.2, 2.3 or later?
  • There was an announcement somewhere that a 'first step' landed in Canary, any link or short answer if that's for public use?
  • Is the routing service a pretty sure thing, and will it be pretty much like the old Router or something alongside it?
  • Anything else in the RFC you'd say has changed a lot and is worth mentioning? If there is, do you have a quick idea/suggestion for a 'prefactor' or pattern that might help ease the breaking change? Like "move your controller logic to a component if you want to get a headstart".
@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Aug 12, 2015

Contributor

@2468ben There is already a routing service in Ember, and has been for a while. It's just still marked private, because it needs a public design discussion before people start depending on it. But I expect whatever we finally mark as public to be pretty similar. See:

https://github.com/emberjs/ember.js/blob/5a023f33afa2cedb5a652cd2efd354352aa3d7c7/packages/ember-routing/lib/services/routing.js

It's not a replacement for the router, it's just a standardized way for components to communicate with the router.

Contributor

ef4 commented Aug 12, 2015

@2468ben There is already a routing service in Ember, and has been for a while. It's just still marked private, because it needs a public design discussion before people start depending on it. But I expect whatever we finally mark as public to be pretty similar. See:

https://github.com/emberjs/ember.js/blob/5a023f33afa2cedb5a652cd2efd354352aa3d7c7/packages/ember-routing/lib/services/routing.js

It's not a replacement for the router, it's just a standardized way for components to communicate with the router.

@tomdale

This comment has been minimized.

Show comment
Hide comment
@tomdale

tomdale Aug 12, 2015

Member

But I expect whatever we finally mark as public to be pretty similar.

I don't think I can endorse that. As the person who worked on extracting the routing service from the existing code, there are still a lot of rough edges that I would like to get sanded down when working on the public routing service API.

Feel free to use the private API, but I would peg the odds of code that relies on it breaking in a future release at close to 100%.

Member

tomdale commented Aug 12, 2015

But I expect whatever we finally mark as public to be pretty similar.

I don't think I can endorse that. As the person who worked on extracting the routing service from the existing code, there are still a lot of rough edges that I would like to get sanded down when working on the public routing service API.

Feel free to use the private API, but I would peg the odds of code that relies on it breaking in a future release at close to 100%.

@2468ben

This comment has been minimized.

Show comment
Hide comment
@2468ben

2468ben Aug 12, 2015

@tomdale That's honestly great to hear, a "don't count on X" keeps me and others from refactoring because we keep hearing about X as the future. I think what I'm poking at above is if there's also "do count on X" for any bit of the Routeable Components RFC. It's mentioned constantly in Ember conversations as the future architecture and a set of big changes landing at any moment; I'm happy if the only update right now is "stay back, hide your children, nothing is certain". Or "this one tiny part will is definitely going in".

We're all gonna refactor through umpteen deprecations, so while we're in there, any yes/nos on something solidifying since February could keep a lot of folks from planning based on the old RFC. Until then I'll just putt around a little more.

2468ben commented Aug 12, 2015

@tomdale That's honestly great to hear, a "don't count on X" keeps me and others from refactoring because we keep hearing about X as the future. I think what I'm poking at above is if there's also "do count on X" for any bit of the Routeable Components RFC. It's mentioned constantly in Ember conversations as the future architecture and a set of big changes landing at any moment; I'm happy if the only update right now is "stay back, hide your children, nothing is certain". Or "this one tiny part will is definitely going in".

We're all gonna refactor through umpteen deprecations, so while we're in there, any yes/nos on something solidifying since February could keep a lot of folks from planning based on the old RFC. Until then I'll just putt around a little more.

Fix the link to the Element and Fragment RFC
Since the Element and Fragment RFC is contained in a separate branch of this repository - and ideally the link tracks with the latest version of the file - there's no straightforward way to have GitHub auto-link it (that I know of). So, this updates the Markdown link to go to the GitHub blob URL for the current Element and Fragment RFC.
@konradjurk

This comment has been minimized.

Show comment
Hide comment
@konradjurk

konradjurk Sep 16, 2015

Hey,
how can I pass initial attributes to a routable component?

The way which is described in the RFC (https://github.com/ef4/rfcs/blob/routeable-components/active/0000-routeable-components.md#specifying-component-attributes) seems not to work for me. Has something changed or has been implemented in a different way?

I'm on 2.2.0-canary+851e4d1f and the routable-component feature flag is set to true.

konradjurk commented Sep 16, 2015

Hey,
how can I pass initial attributes to a routable component?

The way which is described in the RFC (https://github.com/ef4/rfcs/blob/routeable-components/active/0000-routeable-components.md#specifying-component-attributes) seems not to work for me. Has something changed or has been implemented in a different way?

I'm on 2.2.0-canary+851e4d1f and the routable-component feature flag is set to true.

@knownasilya

This comment has been minimized.

Show comment
Hide comment
@knownasilya

knownasilya Sep 16, 2015

Contributor

@berlincityboy according to the tests, it looks the same as it is now: https://github.com/emberjs/ember.js/blob/5351b9458f306398f6168acaa6f5eafe7a0bce2b/packages/ember/tests/routing/basic_test.js#L388 also see where the attrs are set here: https://github.com/emberjs/ember.js/blob/000a248921d0d121fb17d4665b66575fc4f6abb3/packages/ember-routing/lib/system/route.js#L2156 which is still using a controller and the old model hook.

You could go around it by setting attrs in render.

Contributor

knownasilya commented Sep 16, 2015

@berlincityboy according to the tests, it looks the same as it is now: https://github.com/emberjs/ember.js/blob/5351b9458f306398f6168acaa6f5eafe7a0bce2b/packages/ember/tests/routing/basic_test.js#L388 also see where the attrs are set here: https://github.com/emberjs/ember.js/blob/000a248921d0d121fb17d4665b66575fc4f6abb3/packages/ember-routing/lib/system/route.js#L2156 which is still using a controller and the old model hook.

You could go around it by setting attrs in render.

@ming-codes

This comment has been minimized.

Show comment
Hide comment
@ming-codes

ming-codes Sep 23, 2015

I would love to see there's a way to pass arguments into {{outlet}}. This way it'll feel like the outlet actually is the routed component. Or rather, the {{outlet}} helper can just be like the {{component}} helper except the component name is supplied by the route.

{{#x-component as |yield1}}
  {{outlet param1=yield1}}
{{/x-component}}

ming-codes commented Sep 23, 2015

I would love to see there's a way to pass arguments into {{outlet}}. This way it'll feel like the outlet actually is the routed component. Or rather, the {{outlet}} helper can just be like the {{component}} helper except the component name is supplied by the route.

{{#x-component as |yield1}}
  {{outlet param1=yield1}}
{{/x-component}}
@mellatone

This comment has been minimized.

Show comment
Hide comment
@mellatone

mellatone Oct 14, 2015

@tomdale Is there a sense of where the public routing service is at? I feel that it is a pretty important aspect to routable components, and one that the community can gather around to move forward. The {{link-to}} helper has been something of a stand-in for older versions of Ember, but it only works in the simplest of use cases.

mellatone commented Oct 14, 2015

@tomdale Is there a sense of where the public routing service is at? I feel that it is a pretty important aspect to routable components, and one that the community can gather around to move forward. The {{link-to}} helper has been something of a stand-in for older versions of Ember, but it only works in the simplest of use cases.

@jcope2013

This comment has been minimized.

Show comment
Hide comment
@jcope2013

jcope2013 Oct 14, 2015

@mellatone there is an open RFC for one #95

jcope2013 commented Oct 14, 2015

@mellatone there is an open RFC for one #95

@RGL9032

This comment has been minimized.

Show comment
Hide comment
@RGL9032

RGL9032 Mar 4, 2016

@chadhietala

Perhaps I should just wait 8 months like I did for HTMLBars.

@mixonic

I highly doubt they are 8 months out.

Surely it won't be another 8 months before Ember delivers on their promise, right? I mean Ember.View is being deprecated soon so surely we won't be left dangling without any guidance or insight on future direction. Ember would never do that to the devs who have supported them over the years ...

RGL9032 commented Mar 4, 2016

@chadhietala

Perhaps I should just wait 8 months like I did for HTMLBars.

@mixonic

I highly doubt they are 8 months out.

Surely it won't be another 8 months before Ember delivers on their promise, right? I mean Ember.View is being deprecated soon so surely we won't be left dangling without any guidance or insight on future direction. Ember would never do that to the devs who have supported them over the years ...

@locks

This comment has been minimized.

Show comment
Hide comment
@locks

locks Mar 4, 2016

Contributor

@RGL9032 ember-legacy-views will be supported until Ember 2.8 LTS, if the refactoring work is concluded by then ("will likely be").
If you wish to continue supporting Ember, words of encouragement will be more effective. If you feel frustrated, imagine the core developers that are in the core specifically for their commitment to improving the framework.

Contributor

locks commented Mar 4, 2016

@RGL9032 ember-legacy-views will be supported until Ember 2.8 LTS, if the refactoring work is concluded by then ("will likely be").
If you wish to continue supporting Ember, words of encouragement will be more effective. If you feel frustrated, imagine the core developers that are in the core specifically for their commitment to improving the framework.

@sandstrom

This comment has been minimized.

Show comment
Hide comment
@sandstrom

sandstrom Mar 4, 2016

@RGL9032 there is a ton of effort behind Ember. Sure, a thing or two may have been slower out the door than initially expected, but that's pretty common with any project (open-source or not). I think Ember kept great pace recently!

sandstrom commented Mar 4, 2016

@RGL9032 there is a ton of effort behind Ember. Sure, a thing or two may have been slower out the door than initially expected, but that's pretty common with any project (open-source or not). I think Ember kept great pace recently!

@HeroicEric HeroicEric referenced this pull request Mar 13, 2016

Open

Routeable Components #23

@buschtoens

This comment has been minimized.

Show comment
Hide comment
@buschtoens

buschtoens Apr 23, 2016

It would be super useful if attributes set on the {{outlet}} would be propagated to the component. Take CSS classes as an example.

buschtoens commented Apr 23, 2016

It would be super useful if attributes set on the {{outlet}} would be propagated to the component. Take CSS classes as an example.

@grapho

This comment has been minimized.

Show comment
Hide comment
@grapho

grapho Apr 25, 2016

@buschtoens I imagine that case will be handled by classNames and/or classNameBindings on the routable component js

comment retracted. i was corrected about classBindings. glimmer components wont work that way.. but there will be other ways to get the behavior you will need though

grapho commented Apr 25, 2016

@buschtoens I imagine that case will be handled by classNames and/or classNameBindings on the routable component js

comment retracted. i was corrected about classBindings. glimmer components wont work that way.. but there will be other ways to get the behavior you will need though

@mitchlloyd

This comment has been minimized.

Show comment
Hide comment
@mitchlloyd

mitchlloyd Apr 26, 2016

@grapho Could you expand on those other ways? Feels odd to me that we wouldn't be able pass things from a template context into a routable component.

One use case is where one would normally use this.modelFor('parent') and model() or setupController() inside of a route to get access to a parent model inside of a template. We already have a natural API to pass attributes from a parent context into a component in our templates, why not for routable components?

{{route-component parent=parent}}

mitchlloyd commented Apr 26, 2016

@grapho Could you expand on those other ways? Feels odd to me that we wouldn't be able pass things from a template context into a routable component.

One use case is where one would normally use this.modelFor('parent') and model() or setupController() inside of a route to get access to a parent model inside of a template. We already have a natural API to pass attributes from a parent context into a component in our templates, why not for routable components?

{{route-component parent=parent}}
@grapho

This comment has been minimized.

Show comment
Hide comment
@grapho

grapho Apr 26, 2016

@mitchlloyd tbh routable components are still fuzzy for me, i need to re-read some of the RFC and other videos I have seen.

The final implementation is still undecided as far as I know. There are still many pieces missing before it can happen.

What I have heard at least is, setupController() and the 3 model hooks will be replaced by a more semantic hook more specific to passing attrs into the routable component... something like an attributes() hook (confirm?). That is where you will be "passing in" the attributes and actions to the routable component.

Will the route template contain an actual invocation to the routable component like your example above? Or perhaps a combination of the new attr hook and renderTemplate() as the original rfc suggests? or maybe the routable component's template itself will be responsible to setting things like classNames? I dont think there is a clear answer on any of that yet... otherwise it might already be more common knowledge. I have a feeling though it might be closer to option 3 though ;) ;)

:P

grapho commented Apr 26, 2016

@mitchlloyd tbh routable components are still fuzzy for me, i need to re-read some of the RFC and other videos I have seen.

The final implementation is still undecided as far as I know. There are still many pieces missing before it can happen.

What I have heard at least is, setupController() and the 3 model hooks will be replaced by a more semantic hook more specific to passing attrs into the routable component... something like an attributes() hook (confirm?). That is where you will be "passing in" the attributes and actions to the routable component.

Will the route template contain an actual invocation to the routable component like your example above? Or perhaps a combination of the new attr hook and renderTemplate() as the original rfc suggests? or maybe the routable component's template itself will be responsible to setting things like classNames? I dont think there is a clear answer on any of that yet... otherwise it might already be more common knowledge. I have a feeling though it might be closer to option 3 though ;) ;)

:P

@RGL9032

This comment has been minimized.

Show comment
Hide comment
@RGL9032

RGL9032 Nov 26, 2016

Is there anything that can be done to advance this? Is this still a goal for the core team? There is such a vacuum about the state of ember, the framework goals and the timeline for things. Engines and FastBoot are looking great and have gotten a lot of attention, but those features benefit primarily larger ember users. Glimmer 2 is also looking great, and it does benefit us all, but it's taken so much time and at this point it does not bring any new features beyond performance.

Features like routable components, enhanced pods, routing service, and test unification are foundational improvements that benefit all of us. Beyond RFCs and old PRs, those features seem to be mostly stuck. What can the community at large do to help these goals move forward? I worry things have gotten so big and so complex that it's hard for the devs with only a few hours of availability to contribute. Additionally, with the bigger efforts like Glimmer 2 and Engines underway for months, I've sensed an unwillingness to take on medium and smaller features until the larger ones had completed. I definitely understand where that comes from, but some how we have to work past that.

The amount of time that's gone into building larger features has me really worried for the future. Competing frameworks have done a much better job at iterating core parts of their API over the past 2 years, while ember has mostly focused on the edges. If you compare the framework changes from Ember-1.0 thru Ember-1.10 to Ember-2.0 thru Ember-2.10 it's night and day.

RGL9032 commented Nov 26, 2016

Is there anything that can be done to advance this? Is this still a goal for the core team? There is such a vacuum about the state of ember, the framework goals and the timeline for things. Engines and FastBoot are looking great and have gotten a lot of attention, but those features benefit primarily larger ember users. Glimmer 2 is also looking great, and it does benefit us all, but it's taken so much time and at this point it does not bring any new features beyond performance.

Features like routable components, enhanced pods, routing service, and test unification are foundational improvements that benefit all of us. Beyond RFCs and old PRs, those features seem to be mostly stuck. What can the community at large do to help these goals move forward? I worry things have gotten so big and so complex that it's hard for the devs with only a few hours of availability to contribute. Additionally, with the bigger efforts like Glimmer 2 and Engines underway for months, I've sensed an unwillingness to take on medium and smaller features until the larger ones had completed. I definitely understand where that comes from, but some how we have to work past that.

The amount of time that's gone into building larger features has me really worried for the future. Competing frameworks have done a much better job at iterating core parts of their API over the past 2 years, while ember has mostly focused on the edges. If you compare the framework changes from Ember-1.0 thru Ember-1.10 to Ember-2.0 thru Ember-2.10 it's night and day.

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Nov 26, 2016

Contributor

@RGL9032 we have more activity and contributors now than ever before. I agree that it takes time and effort to stay abreast of what's going on, but that's because there's so much of it, not so little.

Please realize that when an account with no participation history jumps onto an old RFC to complain even though three major initiatives are "looking great", that doesn't leave much productive room for a helpful response.

If you have only "a few hours" but want to help I suggest spending that time looking through the latest notes to see what's already ongoing and who is working on it, and using that are a starting point to talk to the people involved in areas that interest you.

Contributor

ef4 commented Nov 26, 2016

@RGL9032 we have more activity and contributors now than ever before. I agree that it takes time and effort to stay abreast of what's going on, but that's because there's so much of it, not so little.

Please realize that when an account with no participation history jumps onto an old RFC to complain even though three major initiatives are "looking great", that doesn't leave much productive room for a helpful response.

If you have only "a few hours" but want to help I suggest spending that time looking through the latest notes to see what's already ongoing and who is working on it, and using that are a starting point to talk to the people involved in areas that interest you.

Merge pull request #3 from nbibler/patch-1
Fix the link to the Element and Fragment RFC
@mirague

This comment has been minimized.

Show comment
Hide comment
@mirague

mirague Mar 24, 2017

Routable components look very promising!

mirague commented Mar 24, 2017

Routable components look very promising!

@wycats

This comment has been minimized.

Show comment
Hide comment
@wycats

wycats Jan 7, 2018

Member

This RFC was opened more than three years ago and literally predates the release of Ember 2.0.

At the time, we were in the process of removing Ember 1.x-era "views", and we finally did eliminate legacy support for them after Ember 2.4. During the end of the 1.x timeframe, we deprecated and removed a lot of features very quickly. We also introduced a series of React-inspired data-flow APIs in Ember 1.13 (the last release of Ember 1.x) that became canonical APIs in Ember 2.0.

While we were making all of these changes, we assumed that we would quickly deprecate controllers and unify the concept of controllers with components. There are two reasons that didn't happen.

First, soon after Ember 2.0, we very quickly came to regret the pace of changes in the Ember 1.13 era, and resolved to avoid doing anything similar again. This more-or-less meant that any plans we had to continue deprecating, removing and consolidating features around that time were put on hold. The community had enough churn, and we wanted to let things settle before creating any more.

Second, Ember 1.13 introduced the first version of Glimmer, and at the time we were highly optimistic that the Glimmer 1 architecture would make it easy to implement Glimmer components (with angle bracket invocation) quickly. We assumed that the new "routeable components" would want to default to the new "Glimmer component" semantics in the case where a routeable component didn't have a JavaScript class, which at the time, made it seem that routeable components blocked on finishing the Glimmer component work.

Unfortunately, my personal work attempting to implement Glimmer components quickly ran into roadblocks, which ultimately led to the Glimmer 2 work, which resulted in a rather large and time consuming initiative.

Between our desire to avoid introducing churn in the early 2.x era and the fact that our efforts in the view layer got redirected into implementing and integrating the Glimmer 2 engine, our ideas for routeable components in that era got put on the shelf.

So much time has gone by since then, and the Glimmer architecture has evolved so much, that the original ideas that we had at the time aren't even relevant anymore. And in fact, the term "routeable component" has become a punchline that is permanently tainted with the long and sordid history of the exact details of this feature.


I think that we should still do a series of features with these characteristics:

  • Allowing a top-level template for a route to have a component class
  • Making it possible for routes to provide arguments to a its template other than model (and using the new @name syntax)
  • Making it possible to use query params in Ember without controllers

But I don't think we should call that feature "routeable components" and I don't think that feature shares much in common with the thinking we had at the time @ef4 originally wrote this RFC. I also think that we should look to emulate @chancancode's recent work in breaking down Glimmer component into multiple chunks when we work on this feature. Instead of one monolithic, entangled feature, I think we should break it apart into small bite-sized chunks we can land a bit at a time.

Finally, with @chancancode's latest work breaking apart the Glimmer component feature (#276, #278, #280), I no longer believe that allowing a route's template to have a component blocks on Glimmer components (but there are some design questions, like what should happen if a route has both a controller and a component, and whether it should be allowed at all).


For all of these reasons, I'm closing this RFC.

Member

wycats commented Jan 7, 2018

This RFC was opened more than three years ago and literally predates the release of Ember 2.0.

At the time, we were in the process of removing Ember 1.x-era "views", and we finally did eliminate legacy support for them after Ember 2.4. During the end of the 1.x timeframe, we deprecated and removed a lot of features very quickly. We also introduced a series of React-inspired data-flow APIs in Ember 1.13 (the last release of Ember 1.x) that became canonical APIs in Ember 2.0.

While we were making all of these changes, we assumed that we would quickly deprecate controllers and unify the concept of controllers with components. There are two reasons that didn't happen.

First, soon after Ember 2.0, we very quickly came to regret the pace of changes in the Ember 1.13 era, and resolved to avoid doing anything similar again. This more-or-less meant that any plans we had to continue deprecating, removing and consolidating features around that time were put on hold. The community had enough churn, and we wanted to let things settle before creating any more.

Second, Ember 1.13 introduced the first version of Glimmer, and at the time we were highly optimistic that the Glimmer 1 architecture would make it easy to implement Glimmer components (with angle bracket invocation) quickly. We assumed that the new "routeable components" would want to default to the new "Glimmer component" semantics in the case where a routeable component didn't have a JavaScript class, which at the time, made it seem that routeable components blocked on finishing the Glimmer component work.

Unfortunately, my personal work attempting to implement Glimmer components quickly ran into roadblocks, which ultimately led to the Glimmer 2 work, which resulted in a rather large and time consuming initiative.

Between our desire to avoid introducing churn in the early 2.x era and the fact that our efforts in the view layer got redirected into implementing and integrating the Glimmer 2 engine, our ideas for routeable components in that era got put on the shelf.

So much time has gone by since then, and the Glimmer architecture has evolved so much, that the original ideas that we had at the time aren't even relevant anymore. And in fact, the term "routeable component" has become a punchline that is permanently tainted with the long and sordid history of the exact details of this feature.


I think that we should still do a series of features with these characteristics:

  • Allowing a top-level template for a route to have a component class
  • Making it possible for routes to provide arguments to a its template other than model (and using the new @name syntax)
  • Making it possible to use query params in Ember without controllers

But I don't think we should call that feature "routeable components" and I don't think that feature shares much in common with the thinking we had at the time @ef4 originally wrote this RFC. I also think that we should look to emulate @chancancode's recent work in breaking down Glimmer component into multiple chunks when we work on this feature. Instead of one monolithic, entangled feature, I think we should break it apart into small bite-sized chunks we can land a bit at a time.

Finally, with @chancancode's latest work breaking apart the Glimmer component feature (#276, #278, #280), I no longer believe that allowing a route's template to have a component blocks on Glimmer components (but there are some design questions, like what should happen if a route has both a controller and a component, and whether it should be allowed at all).


For all of these reasons, I'm closing this RFC.

@wycats wycats closed this Jan 7, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment