You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The ability to create curried component definitions via the (component ...) helper has proven tremendously useful in a variety of patterns. Often times however we find ourselves wanting to generate these curried definitions from the JS side (inside a component or controller class), which is not currently possible.
Examples
The list is long, but a couple of use cases that we have run into lately:
Example 1 - Yielding a collection of pre-configured component definitions
Given a large enough set of components to yield, this becomes painful to maintain, instead we'd prefer to programmatically generate these curried component definitions:
Note that createCurriedComponentDefinition() is the missing piece here.
some-component/template.hbs
{{yieldcontextualComponents}}
Example 2 - Overlay container
This example is obviously simplified quite a bit, but here it is in essence:
We would like to render out-of-band overlays such as modals or notifications at the top-most level of our application. For this purpose let's create a "host" component instantiated in our application template that will house any number of overlay components we throw at it:
Our host component will read the component definitions for the overlays it's supposed to render from a globally accessible location: the overlay-central service, whose job is to do the book-keeping of which overlays are currently displayed on screen:
Modals could be instantiated like any other components within the template of a given route, and it makes a lot of sense in a variety of scenarios, but in some other cases, modals may not be in the context of any particular route, and are rather application-wide concerns. For the purpose of handling the latter case, let's create a modal service that exposes several utility methods:
Note that createCurriedComponentDefinition() is the missing piece here.
Example usage from a route:
pods/some-route/route.js
exportdefaultRoute.extend({modalCentral: inject(),actions: {asyncdelete(){if(awaitmodalCentral.confirm('Are you sure?')){// Handle deletion here...}}}});
Workarounds
Pass around hashes instead of curried component definitions
Piggybacking off our 2nd example here, we could have our overlay-container component feed off of a collection of objects describing what needs to be instantiated, and have it create the actual component definitions:
However this forces overlay-container to suddenly know an awful lot about the type of overlays that it will house, and it makes it difficult for our ember addons to leverage this overlay-container for additional types of overlay.
If HTMLBars had a spread operator (from hash to named attributes), then this would also greatly simplify this particular problem:
We have used a custom mechanism to create what we call component closures (they are essentially curried component definitions). Here is the outline:
createCurriedComponentDefinition(componentName, attrs) {
// 1. Resolve componentName to a component class
// 2. Subclass the resolved class and pass `attrs` to `.extend()`
// 3. Register this subclass with the container under a randomly generated name
// 4. Return this randomly generated name
}
We have used this successfully since the early days of Ember, before the nested form of the component helper was even a thing, but it has the following downsides:
It uses the private component-lookup:main.
It's probably quite a bit less performant, although we haven't measured it.
You can use (component) to further curry a curried component definition that was generated with createCurriedComponentDefinition(), but the opposite is not true.
The text was updated successfully, but these errors were encountered:
I personally think this is a good feature and relates to emberjs/rfcs#432 and emberjs/rfcs#434. It will need a design proposal as an RFC. I see the main difficulty as how to pass "bound" values to this JavaScript API. Let's move this discussion into emberjs/rfcs#434.
The ability to create curried component definitions via the
(component ...)
helper has proven tremendously useful in a variety of patterns. Often times however we find ourselves wanting to generate these curried definitions from the JS side (inside a component or controller class), which is not currently possible.Examples
The list is long, but a couple of use cases that we have run into lately:
Example 1 - Yielding a collection of pre-configured component definitions
some-component/template.hbs
Given a large enough set of components to yield, this becomes painful to maintain, instead we'd prefer to programmatically generate these curried component definitions:
some-component/component.js
Note that
createCurriedComponentDefinition()
is the missing piece here.some-component/template.hbs
Example 2 - Overlay container
This example is obviously simplified quite a bit, but here it is in essence:
We would like to render out-of-band overlays such as modals or notifications at the top-most level of our application. For this purpose let's create a "host" component instantiated in our application template that will house any number of overlay components we throw at it:
application.hbs
components/overlay-container/template.hbs
Our host component will read the component definitions for the overlays it's supposed to render from a globally accessible location: the
overlay-central
service, whose job is to do the book-keeping of which overlays are currently displayed on screen:components/overlay-container/component.js
services/overlay-central.js
Let's suppose we have a modal component:
components/modal/template.hbs
Modals could be instantiated like any other components within the template of a given route, and it makes a lot of sense in a variety of scenarios, but in some other cases, modals may not be in the context of any particular route, and are rather application-wide concerns. For the purpose of handling the latter case, let's create a modal service that exposes several utility methods:
services/modal-central.js
Note that
createCurriedComponentDefinition()
is the missing piece here.Example usage from a route:
pods/some-route/route.js
Workarounds
Pass around hashes instead of curried component definitions
Piggybacking off our 2nd example here, we could have our
overlay-container
component feed off of a collection of objects describing what needs to be instantiated, and have it create the actual component definitions:components/overlay-container/template.hbs
However this forces
overlay-container
to suddenly know an awful lot about the type of overlays that it will house, and it makes it difficult for our ember addons to leverage thisoverlay-container
for additional types of overlay.If HTMLBars had a spread operator (from hash to named attributes), then this would also greatly simplify this particular problem:
but this is as far as I know not possible.
Homemade
createCurriedComponentDefinition()
We have used a custom mechanism to create what we call component closures (they are essentially curried component definitions). Here is the outline:
We have used this successfully since the early days of Ember, before the nested form of the
component
helper was even a thing, but it has the following downsides:component-lookup:main
.(component)
to further curry a curried component definition that was generated withcreateCurriedComponentDefinition()
, but the opposite is not true.The text was updated successfully, but these errors were encountered: