-
Notifications
You must be signed in to change notification settings - Fork 27.4k
feat(loader): add convenience method for creating components #12933
Conversation
For completeness we ought to mention that this PR is related to the discussion at #10007. @shahata can you clarify how this version compares with the suggestion at #10007 (comment)? Also have we considered the idea of ditching the magic symbols: |
* @description | ||
* TODO... | ||
*/ | ||
component: function(name, options) { |
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.
should be using invokeLaterAndSetModuleName
?
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 is just a wrapper around module.directive
. module.directive
will do the invokeLaterAndSetModuleName
Once comment: IMO we should avoid the |
@petebacondarwin this proposal is consistent with #10007 (comment) with the exceptions that module.component accepts an options obj instead of factory method and that scope isolation is optional I'll look into the |
@petebacondarwin I thought a bit about ditching the magic symbols today and I think that I'm leaning against it. Main reasons are that terminology is not the same since ng1 doesn't really have one way binding (would you use |
@petebacondarwin @btford @pkozlowski-opensource @caitp |
@shahata - I kind of like ditching the magical |
I don't think the functionality needs to line up 100% between ng1 and ng2 |
@shahata I'm with @petebacondarwin here - the pb is that both So no, we shouldn't map existing symbols to props / events. |
@petebacondarwin @pkozlowski-opensource if we decide to go forward with adding one way binding maybe we can use |
@shahata just fyi I must say that I'm not huge fan of the whole "make ng1 look like ng2 even if concepts don't match" story |
This is why I suggested to do this only if we decide to match the concept of one way binds. Regarding naming I'm not going to touch it, we'll just do whatever ng2 does. :) |
Let's stick with |
@shahata what is the one way binding in ng1 for you? In ng2 you can bind any type so |
@pkozlowski-opensource the one-way binding we are talking about is this PR - #12835 - but using a different symbol rather than Here is an interesting idea, which @MikeRyan52 has:
This seems reasonable. I can't think of a situation where you would want a "component" that doesn't provide a template. And if that is the case then we would always be clearing out any child nodes of the element where the component is instantiated, so we might as well stick it in a transclude function. Previously this would have incurred a performance penalty but now that we have lazy compilation of transcluded contents, it would be negligible. Side note - if the multi-slot transclusion lands, then this proposal would change to:
|
@petebacondarwin thnx for the info. I like the And I completely agree that each component must have template / templateUrl. I would also add that each component need to use isolated scope (consequence of having a template and most probably state that goes with it)
I don't think I understand reasoning behind it. There are many examples of components that don't need to transclude anything (ex.: pagination, rating etc.) |
Yes, I agree that components should also always have Regarding transclusion, it means that the configuration object that gets passed to If there was no content below the element then we could optmize so that nothing would be transcluded anyway. In any case, now that we have lazy compilation the cost will barely be noticed, and if it was a problem then we could allow people to explicitly override it with So I guess my suggestion is that for components the default would be |
@petebacondarwin makes sense if there are no side effect / perf hit |
So the API that I would be happy with is: angular.module('myApp').component('myComponent', {
template: '<div></div>', //string | Function, default: undefined
templateUrl: 'a.html', //string | Function, default: undefined
controller: MyCtrl, //string | Function | Array, default: function(){}
controllerAs: 'vm', //string, default: component name
bindings: {abc: '@'}, //object, default: {} (passed to bindToController)
$canActivate: MyCtrl.canActivate, //Function, default: undefined (passed to factory.$canActivate)
$routeConfig: MyCtrl.routeConfig, //RouteConfig, default: undefined (passed to factory.$routeConfig)
isolate: false, //boolean, default: true (scope: {} .vs. scope: true)
transclude: false //boolean | object, default: true
}); where
|
To be honest I've never was fan of 2 properties here. How about |
np, I'll add |
I prefer the case as stated where it defaults to the name of the component |
+1 for @petebacondarwin |
Okay sounds good! 👍 |
* - `template` – `{string=|function()=}` – html template as a string or a function that | ||
* returns an html template as a string which should be used as the contents of this component. | ||
* | ||
* If `template` is a function, then it is {@link auto.$injector#invoke injected} with |
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.
Why are we deviating from the "normal" DDO's template
/templateUrl
(which don't get injected) ?
There's probably a good reason; I just want to know it :)
Maybe we should stress it more, because more experienced users might get biten by this.
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.
The reason is that in module.component
there is no factory function. In classic DDO, the template
and templateUrl
properties are in the closure of the factory function and so have access to injectables from there.
I left a coule of minor comments. One thing that is missing imo, is the It might also be useful to make all defaults globally configurable, but I am not sure it is a good idea to give too much power to the user 😛 |
The defaults need to be consistent globally, since people may be loading in 3rd party libraries that also register using |
As a user (of the framework) I would prefer to be able to configure the defaults (espacially if I have a large number of components) and 3rd-party libraries better define explicit values to avoid being broken. But I agree it might be too much for now - it's probably better to keep things as straightforward as possible. |
IMO defaulting to |
Updated docs & didn't squash on purpose to make it easy to see diff. I'm staying with capital letters for now until we decide otherwise. Regarding |
I agree, let's default to |
Cool. Done. |
Any more feedback before we try to get this merged? |
LGTM 😸 |
We should probably change "bindings" to "providers" right? |
@shairez - nope. Bindings in this context are template bindings. Nothing to do with the DI system. |
@petebacondarwin sorry, skipped that part in the discussion, I see now it's like what used to be the scope object in the DDO. |
Let there be...:sparkles: component :sparkles: Woohoo ! 🎉 |
Well done everyone who had a hand in this, especially @shahata for the implementation |
Sorry for the late feedback but I find that using Thinking a bit more about this I created a separate issue to track this #13566 |
The proposed syntax:
This means that for the most common use-case of simple component ppl will only need to pass template, controller and bindings.
I've discussed this with @btford and we've decided to change a couple of things from #12907:
Docs are still missing obviously, but I would like to get some feedback before moving on.
Closes #10007