-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Implement {{component}} helper #10093
Conversation
@mmun @krisselden @mixonic would love a review and feedback |
this.notify(); | ||
}, | ||
destroy: function(){ | ||
if (this._super$destroy()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this._super$destroy doesn't seem to be defined?
Might be nice to warn if 'ember-htmlbars-component-helper' is defined but 'ember-htmlbars-binding-aware-view-helper' is not |
|
||
var self = this; | ||
|
||
this._boundViewOptions.viewStream.subscribe(function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You seem to using a different style for subscribing here compared to component.js. Any reason we can't do
this._boundViewOptions.viewStream.subscribe(this._updateBoundChildView, this)
?
Excited to see this feature get fleshed out :-) 👍 will review more. |
Seems that using a ContainerView would mess with views that care about their parentView, though those are mostly components. If I am reading the PR correctly, using the component helper wouldn't create an intermediate component right? |
Given that we will likely remove |
"The `component` helper expects exactly one argument, plus name/property values.", | ||
params.length === 1 | ||
); | ||
var container = this.container || this._keywords.view.value().container; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again I'd suggest read
instead of accessing value()
Agreed w/ @tomdale re: new |
import { read, isStream } from "ember-metal/streams/utils"; | ||
import EmberError from "ember-metal/error"; | ||
|
||
function ComponentLookupStream(source, componentLookup, container) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to suggest you explore chainStream
for this logic instead of making a custom stream. chainStream
, like read
is non-stream safe.
Values get into the chain via scope instead of an object instance.
var component = chainStream(source, function(){
var componentParam = read(source);
return componentLookup.lookupFactory(componentParam, container);
});
// component is maybe a component, maybe a stream of component values
Because both the utils are non-stream safe, you don't even need to branch the initial logic based on if this is a stream.
I think chainSteam
could greatly reduce the amount of code required to implement this feature.
@mmun also mentions that lookupComponent
could possibly return a stream itself, instead of wrapping it.
@tomdale It would be a shame to loose Just my $0.02. |
Components now support |
@workmanw We will support coupled components without needing the {{view}} helper. |
@@ -199,17 +205,23 @@ export function viewHelper(params, hash, options, env) { | |||
viewClassOrInstance = View; | |||
} | |||
} else { | |||
viewClassOrInstance = readViewFactory(params[0], container); | |||
var viewParam = params[0]; | |||
if (Ember.FEATURES.isEnabled('ember-htmlbars-binding-aware-view-helper') && isStream(viewParam)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feature flag checks have to be by themselves for them to be properly stripped by defeatureify. This would have to be rewritten as:
if (Ember.FEATURES.isEnabled('ember-htmlbars-binding-aware-view-helper')) {
if (isStream(viewParam)) {
/* stuff */
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching this! I was thinking it was busted.
Thanks for all the great feedback. I'm laid up with a cold today, but look forward to taking another pass. |
@mmun I'm sorry, I don't understand what you mean. Are you saying, |
@workmanw - Yes, {{component someBoundProp}} should absolutely work (and is what this PR is all about). |
@rwjblue Awesome. Thanks a lot. It wasn't clear to me if "someBoundProp" could be a class object as well as a string name. |
Should be a string name to be looked up in the container. |
@workmanw I mean that we won't deprecate the view helper until there are well defined upgrade paths. Localized / scoped components is something we've been thinking about for a while but nothing concrete yet. Expect an RFC before EmberConf. |
6d83dba
to
5549f09
Compare
@igorT @mmun @mixonic @rwjblue @tomdale Just pushed a second pass, removing the new view feature and applying the excellent feedback. A few questions:
|
5549f09
to
a959165
Compare
import EmberError from "ember-metal/error"; | ||
|
||
/** | ||
`{{component}}` is a `Ember.Handlebars` helper for adding instances of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ember.HTMLBars
or "template" helper? Once 1.10 lands Ember.Handlebars
is for backwards compat only (and Handlebars itself isn't actually used/needed)...
@lukemelia great work. I plan to do a thorough review soon. |
We discussed this at the weekly meeting and reached consensus that this is good to merge once @mmun finishes his review. |
@module ember | ||
@submodule ember-htmlbars | ||
*/ | ||
import Ember from "ember-metal/core"; // Ember.warn, Ember.assert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe flagged aswell so we don't pull in the extra bytes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow. Do you have an example of this, @stefanpenner?
….resolving.to.component.name}}` to dynamically update the component when the bound value changes.
7b2efd3
to
16b7023
Compare
Couple of questions/thoughts:
|
both
yes |
@stefanpenner We should enforce component lookup via strings and disallow classes and instances, no? I don't want people writing inline component classes inside of their components until the story has been fleshed out. |
Perhaps I am missing the obvious but what advantage does this have over:
Functionally it appears this implementation does exactly the same but adds additional code to Ember. |
@bcardarella if I'm not mistaken, this will allow to pass a component name to the helper dynamically. So you will avoid the need to have {{select content=chartTypes selection=chartType}}
{{component chartType}} where there's a |
@bcardarella - there are many cases where the actual component name to use is determined at runtime (like from a model property). This was not previously possible out of the box for components. |
@tobscure @stefanpenner @mmun Test coverage only covers name lookups, and IIRC, component class references are not supported per discussions during the issue/PR process. It would be trivial to support class references, but my understanding from @mmun is that we want to come up with another approach to support those use cases. |
Confirm, we only want to support strings to be looked up in the container (not component instances or classes) at this point. As you said, it would be possible to add support for instances and classes, but we definitely do not want to start with so much extra API surface. |
As of #10193 this is enabled by default on canary (and slated for 1.11 barring any issues). |
How are you supposed to pass data to your component while using this helper? |
@shinzui name value pairs, just like on your components, see tests for an example (https://github.com/emberjs/ember.js/pull/10093/files#diff-de0c559d2c25a9811bd9876f63269098R36) |
@lukemelia great, thanks. I asked based on reading the code, i should have tried it. |
Are there plans to enhance this to allow passing component classes? The discussion above mentions this functionality, but I don't see it in the commit. It would be useful for 'private' components, that are only used within a parent component (which they are coupled with). |
@sandstrom see emberjs/rfcs#64 I think that is the solution for private child components. |
@ef4 thanks! |
This PR implements the
{{component}}
helper, which allows passing of a param that is resolved and used to look up the component. Leveraging the first feature described above, it also automatically will swap the component for another when the bound value changes.See #5007 for more discussion and background.
What's left:
{{component}}
helper docs