Worried about what Ember 2.x will become

That would have been exactly my point.

The isolation and explicitness is indeed a good thing. I sure hope that you did not interpret my comments as a reasoning to propose reverting that, because that is most certainly not my intention. My primary concern is where and how the explicitness is to be implemented. In the templates in a format that is not really suitable and harder to maintain.

I’ve been trying to convince you there is room for improvement here. Whilst you haven’t really confirmed this, if I interpret your reply correctly you’re also not denying it and you are open to suggestions.

Basically I’m searching for a solution that would mitigate my concerns while preserving explicitness. Personally I would like to move some explicitness away from the template and into the components. Increasing templates maintainability with some obfuscation in the template as a trade-off.

So far I came up with one approach which isn’t entirely thought through yet, but we should start from somewhere. If you believe it would be a useful addition to Ember I wouldn’t mind turning it into an RFC.

I’m thinking of the possibility to define keywords in a component. This definition would contain the default component and bindings to use. So instead of having to write:

{{profile-component profile=poster}}

With the defined keyword “poster”, component “profile-component” default binding “profile=poster” you could simply write:

{{poster}}

The other way around I think it ought to be possible to explicitly define the attributes a component accepts and whether it’s required or optional. Perhaps even with type checking when debugging and maybe an option to disallow the binding of not explicitly defined attributes.

I agree on the personal taste thing. I’m primarily annoyed by the dash requirement. I would like to have this in pods:

post/navigation/component.js post/navigation/item/component.js

instead of

post/post-navigation/component.js post/navigation/navigation-item/component.js or post/post-navigation/navigation-item/component.js

I think I’ve gotten a bit used to the dash notation in Ember but I still find a little odd to have camel-case naming in my javascript with the dash notation counterparts as file names.

I haven’t thought it through, or anything, but I kind of like this idea. I’d prefer templates to be nice and clean and uncluttered and semantic, and configuring which parameters go to which component seems like something that it’d make sense to do in the JS file.

IMHO, there seems to be a tendency to make templates as powerful as possible (see truth helpers, etc), while I’d rather have my templates being dead stupid.

I’m glad you like it. Think it through and comment.

I also like my templates as dumb as possible. Mainly for maintainability and as I mentioned in my original post, to make them easy on our designers.

On the other hand, these powerful templates are extremely useful for quick prototyping or solving some edge case that you don’t want to support on a lower level.

No, I want to say that I explicitly think this would be a really bad idea, and that one of the great things about using components is that you can see, all in one place at the call site, exactly what you’re binding into to component. I think it would be a huge step backwards - what you’re proposing would be pretty much the situation we had with views and it was a really bad situation in most apps because the implicit context was bad.

Fundamentally I disagree with this. I have personally found the explicitness in templates massively increases maintainability, and moving the explicitness away from the templates would be something I’m strongly against.

Essentially, my opinion is that this debate was had and decided over a year ago, my impression being that within the community the essentially unanimous conclusion was the opposite to what you desire. If you want to reopen that debate, RFCs are the place to do it - but I would be strongly against proposals like you suggest above, and whilst I cannot unilaterally speak for the core team (which I am not on) or the rest of the community, my impression is that there is very broad agreement on this.

I do see exactly what you’re saying, the issue is that I disagree and I think it’s unlikely you’re going to convince me otherwise - I have a large level of experience with both approaches and find the current approach to be a clear winner. But if you want to open a more formal proposal that reaches people who are actually decision makers, an RFC is the place to do it. I think your chances of success are extremely small but as I said, I’m not on the core team and I don’t make the decisions on the future of Ember.

Components require a dash in line with the Custom Elements Spec - which becomes even more important as angle bracket components are introduced. The idea is eventually that ember components will be a subclass of HTMLElement. This is a way off in the future but keeping in line with draft specs now helps that future to come faster.

PR submitted (with demo) in: [FEATURE ember-htmlbars-local-lookup] by rwjblue · Pull Request #12673 · emberjs/ember.js · GitHub

1 Like

I completely agree. The explicitness in the templating layer is definitely a win, and has been carefully crafted over a long period of time.

Ember truth helpers can easily make templates way overcomplex - for this reason I’d be surprised if they were ever brought into ember core. Sometimes they are extremely useful to avoid single-use computed properties for equality - I think if you can do an if statement then comparing if two things are equal in a template is not much of a stretch - perhaps an if-equal or unless-equal built into ember core would be more acceptable, but that’s not something I’d advocate for either way - I’d probably use it if it was there, but I don’t think it’s a glaring omission that is needing focus right now (as there are a quite a few).

You can’t really have both - either they are terse and full of magic or they are dead stupid and verbose. There’s essentially scale between the two. I’ve been using ember since it was a bit further towards the magic end, and worked on many apps that leveraged this, and found it to be very painful - that’s why I’m very glad for the current swing towards stupid, explicit templates. Yes, they are a little more verbose to write. However that initial cost of a bit of verbosity pays huge dividends in long term maintainabilty that I’ve experienced repeatedly first hand over the past few years.

No, I disagree. You can have both. You have it with computed properties for example. If you have

<p>{{username}}</p>

The template is stupid: Is has no knowledge of anything but that it’s passed some string and that it should render it. Contrast this with something like

<p><%= User.find(@user_id).name %></p>

Which you sometimes see in Rails.

Here, making the template stupid - i.e. not in the business of knowing anything except how to render stuff - also makes it non-verbose.

I don’t see configuring a component in the JS file as “magic”. It’s exactly as explicit as doing it in the template, the only difference is that you move the configuration into code instead of a template. As for maintainability, I explicitly think that maintainability is gained by moving stuff as much out of templates as possible. For one thing, anything that is code can be unit tested (in principle). Templates are untestable.

I don’t argue against explicitness or verbosity. I want that. I don’t necessarily want it in the template though.

I agree that the current situation is a big improvement over what we had with views. I totally disagree however on why the explicitness “must” be in the template and how on earth it would increase maintainability. In my opinion the increased verbosity makes it more error prone and refactoring more of a pain. But since you say it’s unlikely I can convince you, I’ll say no more.

That’s a completely different discussion which I might want to address later on. My main issue in the context of my comment: I understand that you require the dash if you want to use the angle bracket syntax and that the dash is required to let a keyword be recognized as a component. While from a standardization point of view it is good practice to use a dash in a component name, I think it shouldn’t be enforced.

That’s my view as well. But I doubt we can convince @alexspeller and I’m affraid @rwjblue is also opposed. If there would come some support for this idea from the community I wouldn’t mind drafting an RFC.

PS. Templates are not untestable but I’d rather not if I don’t have to.

Actually, more fundamentally, I think you’re wrong here. Your templates are basically just functions (in the mathematical sense). They take some input and they produce an output (HTML). There’s a very easy way to make sure the template neither has magic nor is cluttered and verbose, and that’s dependency inversion. Instead of the template being in the business of instantiating a component, let the component JS file instantiate the component and pass it to the template. DI is a well-proven approach in a lot of cases and I don’t really understand what makes templates so different here.

I think it would help to give some examples why you think moving the component instantiation to the JS file would decrease maintainability, because I’m not seeing it. Not that I necessarily want to convince you, but I want to understand the tradeoffs that you think we have to make.

I’m going to stop responding here as it has changed from a quick answering of a question into a philosophical debate that I’m not actually that interested in having - again - as I mentioned this has all been settled for quite a long time and I’m sure you can find a lot more discussion on it if you search the archives here, RFCs and github PRs.

Here’s a start from one year ago :smile:

Fair enough. I would still be glad if somebody could summarize the main points of the past discussions as they relate to the topic at hand.

IMHO, there seems to be a conception that we either have views and lots of magic or templates with a lot of logic, and that’s where @Emrvb and myself disagree: We think that there’s a third way.

I wonder how you would interpret my original post and its title as a simple question that would not potentially turn into a debate. I don’t need you to respond here, I do however appreciate comments from people who are opposed to my concerns and idea’s. Having debated something in the past is in my humble opinion not a very good argument against reopening a debate. Those debates have resulted in the current situation. I for one am not completely satisfied with the results and I now wish to debate whether there is room for improvement and what those improvements could be.

I’d like to complement this:

Let’s assume my little proposal would be viable. Then I would also propose that it’s optional.

1 Like

Here’s a very, very rough sketch of at least what I am imagining (I’m sure @Emrvb has other ideas). Bear with me if it’s not the most useful example:

// template file
<p>{{itemName}}</p>
{{adBox}}

// JS file
itemName: Ember.computed.alias('item.name'),
adBox: Ember.computed('item', function() {
  if (this.get('item.onSale')) {
    return this.component('on-sale-item-ad-box', { item: this.get('item') });
  } else {
    return this.component('item-ad-box', { item: this.get('item') });
  }
}) 

and contrast with what you’d probably use right now:

// template file
<p>{{item.name}}</p>
{{if item.onSale}}
  {{on-sale-item-ad-box item=item}}
{{else}}
  {{item-ad-box item=item}}
{{/if}}

Personally, I think the current way leaks logic into the template and makes maintainability harder, while the first approach cleanly encapsulates the decision of which ad box to render, makes it much easier to add more ad box types in the future (do templates actually have elseifs?), and is also unit testable in a straightforward way - and it doesn’t add any magic whatsoever.

That may not be the best example as right now you could write this as:

// item
...
adBoxComponent: computed('onSale', () => {
   return this.get('onSale') ? 'on-sale-item-ad-box' : 'item-ad-box';
})
...
<p>{{item.name}}</p>
{{component item.adBoxComponent item=item}}

Everything stays explicit, it’s easy to follow the data flow and there’s no additional magic you need to learn/remember/work-around when it doesn’t fit your use case.

Well I would certainly have some idea’s for the JS syntax but I think implementation details are a bit premature until enough members in the community back something like this up or we convince enough core members this is an issue that requires improvement.

Fair enough, you’re correct (although I would personally never put that adBoxComponent property on the model, it’s a presentational concern). The example can be adapted easily, though, with different components that for some reason need different parameters being passed to them (because they are reusable for example). Let’s say you have a form that you want to fill out that is generated dynamically:

// template
<p>{{question}}</p>
{{answerInput}}

// JS file
answerInput: computed('question', function() {
  if (this.get('question.answerType') === 'boolean') {
    return this.component('yes-no', { selectAnswer: 'select-answer' });
  } else if (this.get('question.answerType') === 'text')) {
    return this.component('text-input', { inputAnswer: 'select-answer' });
  } else if (this.get('question.answerType') === 'select')) {
    return this.component('select-box', { values: this.get('question.possibleAnswers'), selectAnswer: 'select-answer' });
  }
})

etc.

Where’s this “magic” idea coming from? As far as I see it, nobody is advocating any magic, au contraire, everything is very explicit. I don’t want to go back to views with their implicit contexts. Edit: In fact, there’s less to remember if your logic is in JS - you only need to know JS. If you have logic in your template, by contrast, you have to remember more, because you also have to know how your templating language lets you do logic.

I’m not saying that we should settle on some syntax, but a rough sketch of what it should look like would prove more helpful to discuss use cases than a very abstract discussion.

I think you have this completely upside down. The logic of which DOM elements (which is what components ultimately boil down into) to render is 100% absolutely the concern of the template domain.

IMO, the template version is much easier to understand and follow. @lookingsideways’s suggestion is also easy to follow.

This is precisely why the {{component}} helper exists, to allow you to invoke any component given its name (and is ultimately what you are trying to recreate in the JS file).

Yes:

{{#if foo}}
{{else if bar}}
{{/if}}