My primary worry is about how we’re supposed to be working with components in templates.
In my opinion templates should only be used to define where and how something is rendered. I always aim on shielding templaters/designers from as much logic as possible. To me it seems the way we are supposed to use components (e.g. as replacement to the itemController) causes too much business/program logic to bleed into the templates.
I’m afraid that in the future even small changes in the logic will have more impact on the templates and templaters/designers need far more understanding of the program internals than desired.
I try to have my applications seem like magic to the templaters/designers in the same way Ember is magic to me as a developer. Follow convention and you have to do almost nothing and add X when you want something more specific. I feel like I’m losing this ability.
If my worries have not merit at all, feel free to comfort me with rationale. If they do have merit, I’d love to discuss how we could address this issue.
Ember will be using more and more components for everything, as a way to make coherently composable units of isolated functionality. This is a good thing, as it makes everything self-contained and easy to understand.
People writing ember templates will need to be comfortable with using components too. Ember is not specifically designed so that non-programmers can write templates, I don’t believe it’s an explicit design goal nor should it be - optimising a framework for non-programmers comes at the cost of making it more annoying to programmers usually.
Thank you for your reply. I would like to clarify that I’m not opposed to the component centered design Ember is heading towards.
Personally I have some doubts about removing the controller abstraction layer, but then again I’m also aware that half of the time I don’t use it. For the other half a majority could perfectly live inside components. But that is not the issue I’m trying to raise here.
I also agree that facilitating ease of templating for non-emberists let alone non-programmers shouldn’t be a goal by itself. This is just something I personally try to pursue, it was just an example. I welcome the new features we get in templates.
The point I’m trying to make is that I fear too much logic, other than component compositing (which is nice), is leaking into the templates. There are many cool and useful features being added to the templates which in my opinion are great for fast prototyping and perfect for implementing edge case scenarios which are specific to the template. For anything else it is nice it “could” be done in the template, but I want to be able to put it in my component where it “should” be.
This may not be much of an issue for very generic components, but we will also get a lot of components with a bit tighter coupling. I start seeing examples where that coupling is being pushed in the templates where it’s obscuring and much harder to maintain.
Routable controllers are being replaced with routable components. The difference to most app code will be negligable - mostly this is misunderstood. See this post for more details.
Everyone wants templates to be maintainable, coupling to be minimised, and logic in templates to be presentational only. I and certainly most others have found increasing usage of components to meet this goal very successfully. I am so glad that itemControllers are gone now, they were a constant source of implicit coupling and bugs. Do you have specific examples of where newer component driven designs have negative impact? I have found the opposite to be true and I would be very surprised if this wasn’t also the finding of the majority of ember devs who’ve used it through the transition.
I noticed {{partial}} was on the list to be replaced by components, along with {{render}} and {{view}}. I understand why render and view should be replaced (controllers and views, respectively, are going away), but what is the reason that partial is deprecated?
Partial is not currently deprecated. I don’t know if it will be in the future. Sometimes it’s useful, the argument against it is that it makes it too easy to rely on implicit state and not explicit dependencies
I had a short holiday and did not have the opportunity to reply. I would like to thank you for taking the time to discuss this. In order to keep the discussion organized I’ll just give one example and we’ll see how it goes from there.
Keep in mind I have no problem with components, but I do have a problem with how I think we’re supposed to use them at this time.
Also while I’m by no means advocating the resurrection of the itemController, I will use it in my examples as I think it was pretty obvious how it worked and limit the number of questions “but why do you want to do that, can’t you do …”.
First we did something like this:
`{{#each itemController in controller}}
{{/each}}`
Which I guess should be refactored to something like this:
{{#each models as |model|}} {{#component 'model-component' model=model}} <!-- Render stuff in model-component context --> {{/component}} {{/each}}
The good thing here is that the template got better readable, it’s more obvious what is happening. However in my opinion:
I’m configuring too much in the template: Which “model-component” should be used is highly dependent on the context. While I think we should be able to specify the component in the template, in most cases there is only one specific component suitable for this task.
The same thing applies to the model binding and other bindings that might be required.
It doesn’t scale well. As far as I know, in ember-cli, we can only put components in the components folder. In real life applications we’re going to have dozens of highly specialized components. Naming them is going to become a real pain.
(a) you wouldn’t use the component helper unless it was a dynamic lookup. (b) You could use the block form but more likely you’re use the inline form - otherwise there’s not much point because you’re still in the outer context
Yes, it’s dependent on the context - much like itemController. Now you’re creating a component instead of an itemController, not much difference there
Incorrect. Components can be nested, stored in pods, and are likely to have heirarchical lookup in the future anyways to avoid giving them slashed paths in templates if they are local to that pod.
(a) the helper notation was to trick somebody into suggesting to bind “this.childComponentName” to let the parent (the current contextual) component decide which component to use.
(b) indeed, but out of the scope of my example. Assume it’s just psuedo code.
Not much difference indeed. Except that my ArrayController could decide which itemController should be used. This is now fixed in the template. I think it “could” go there. You might even “need” it there in edge cases. In regular cases it should not. It is reducing the templates re-usability and maintainability. Now both my component as my template have become highly specialized.
Do you mind commenting on my note concerning attribute bindings?
I would love to see a proper example on how to correctly include a component that is nested in a pod.
Not sure what you mean here - the component helper is useful, for example, if you have a list of different items that need to be displayed differently - an example would be a chat application, you could have an array of events in order and display each component {{chat-message}}, {{chat-joined-room}}, {{chat-left}} by doing {{component item.componentType}} instead of a giant if statement.
This removal of implicit differences where you can’t tell what a template will do easily without looking in multiple disparate files is considered by many (myself included, @mixonic did a talk on it at emberfest a long time ago) as a bad pattern and I believe it to be a very good thing that you can’t do it any more.
Templates are specialised, and if you want to make them more generic, then you can wrap them up in a component easily enough so that they are reusable.
Not sure what you mean by this. Do you mean you have to do {{some-component item=item}}? I consider this a great win of isolation and explicitness – you pass in exactly what you specify to the component, nothing more and nothing less.
I too have been using the nest components structure in my app (though I don’t use pods because I find them to be very buggy). Here is a basic example.
{{#foo/bar/my-component foo=bar as |value|}}
<label>{{value}}</label>
{{/foo/bar/my-component}}
That’s nothing short of horrific. First off, that syntax. Secondly ‘/’ is an operator for HTML so I have no idea how this will work with angle brackets. Maybe: <foo/bar/my-component>....</foo/bar/my-component>. But really the fact that I have to constantly include the full path to use the component when it’s is nested relative to a sibling is the worst part.
So while this technically works, I’m quite frankly embarrassed to even explain this solution to others. Everytime I show this to someone, the result is a facepalm.
I don’t mind the syntax at all - I think it makes a lot of sense because the components are nested like that. I have no idea how angle bracket components will handle this actually, it’s for sure more of an issue there.
Yea, sorry if that wasn’t clear. I just meant pods in general have been kind of buggy. We do use the nested components solution in our app like you’ve shown in that twiddle.
Well the intend in the example was that the component to be used wouldn’t change per model. So I wouldn’t want to bind that. The situation you give as an example is one I would also like to address, but I will post my example a later moment so we’re not discussing several topics at cone.
About the implicit differences/explicitness. I totally agree with the theory. But in practice some (well designed) implicitness is a bliss.
Imagine a blog app. I have posts. Each post has the profile of the poster attached. I have several different layouts for viewing a post, all of them use the profile component to render the associated profile. Every template needs to include the profile binding (shrug, I hate repeating myself, oh well). Now for some reason the profile component needs an additional binding (i dunno, perhaps the post model itself?). I would need to adjust every template. Now consider I also have the same application running for different clients with different sets of templates. The templates requiring changes starts growing exponentially.
It comes down to this. If two or more components are required to be used in conjunction (they’re very specialized and have tighter coupling by design and are never or rarely used otherwise) it ought to be possible to define (default/implicit) binding on a level before the actual template.
An important reason I choose Ember over Angular in the past is the convention over configuration paradigm. I’m starting to do an awful lot of configuration in a place I don’t want that, the templates, the “leaves” of the application. While this is perfectly fine for very generic components, it’s becoming annoying in all other cases.
About the templates specialization. Yeah, you’re right. That’s what I said but not what I meant. I think the above paragraph covers what I meant but let me summarize: In templates, while indeed specialized, I keep repeating the same things over and over again, triggering my abstraction reflex.
Thanks. Now I remember why I didn’t want to use it. The way the resolver handles components pods, leaves me with all those one file directories. This is something I’m considering creating an issue about. The requirement to use a dash in a component name. But let’s not discuss that here now. I’m aware of the complications of keyword recognition and the compatibility issues/design choices regarding angle bracket components.
Well I also find it hideous and not very well readable. Then again, I haven’t been able to think of a more elegant notation either. Thanks though for not adopting the double dash notation to reflect those slashes as I believe was suggested somewhere. That would have made thing worse .
Angle bracket components will not support / in their invocation.
Local lookup is being added to prevent the use of {{post/x-title}} style invocation that is required now (when rendering x-title from within the post route, you would use {{x-title}} and it would automatically look for post/x-title first). Look out for a PR adding this functionality in the next few days.
In the example, you had {{#component 'model-component' model=model}} . Whilst that works, there doesn’t seem to be any reason you’d actually type that. You’d type {{#model-component model=model}} instead of using the component helper.
We went down that path with views. It was generally a pain, and Ember decided to make explicitness a core tenet. Obviously some people will not prefer that approach, but it’s the one Ember has settled on. At this point, I really don’t see that changing as the reception has been overwhelmingly positive. Feel free to open RFCs if you think you have better proposals, but at this point it’s a debate that was pretty much settled on the side of explicitness quite a long time ago.
So two things - one file directories are again something that’s really down to personal taste, but ember has strongly adopted a layout that leads to this kind of arrangement if you have one thing at a certain path. The proliferation of directories is likely to get worse not better as pods become the blessed path.
On the other hand, “one file directory” is a bit of a red herring. You’re likely to have pods that contain a route.js, component.js, template.hbs and component subdirs that have template.hbs and component.js. Usually you’ll have a few files that are organized in their respective namespaced directories. Like tabs or spaces, it’s something you can argue about all day but it’s the direction ember has taken, and I think that really it doesn’t matter as long as there is a strong convention. Pods allow for this and allow nicely organizing files in your project in a way it’s easy to find them, and lots of directories is the way that it’s happening.
Angle bracket components will not support / in their invocation.
So how would you use {{x-title}} outside of the “post” directory? It seems like you wouldn’t? If that’s the case, how would you even use {{post}} or how would {{post}} include {{x-title}} if they reside in different directories?
Additionally, we’ve used nested components as a means of organizing and grouping components, not just as hierarchy. Having directories/nesting result in isolated would be not awesome so hopefully I just misunderstood what was happening