Conditional Views and URLs. Am I doing this “the Ember Way”?


#1

Hello everyone,

I am absolutely new to Ember, I have watched it for quite a while and this weekend I decided to dive in with a real-life small scale project. Obviously I encountered many a-obstacles, but this test has overrall been successfull and made me want to participate actively into this community. Hopefully you will bear with me.

Now, on with the question: I am trying to do things “the Ember Way” as much as it is possible, as I understand that this is a great advantage in the convention-over-configuration type of frameworks, and, of course, I try to learn from the best and apply the best practices.

I have some data that gets displayed into two different forms of visualization (let’s call them overview and list). As far as I understood reading the guides and especially this post by @eviltrout it is best practice to approach this problem using a property in the controller (especially this last post made me change my approach, given the similarity between the use cases). So I have:

App.MyController = Ember.ArrayController.extend({
   actions: {
     viewAsList: function(){
       this.set('viewMode', 'list');	
     },
     viewAsOverview: function(){
       this.set('viewMode', 'overview');
     }
   },
   viewMode: 'overview',
   viewingList: function(){
      return this.get('viewMode') === 'list'
   }.property('viewMode'),
   viewingOverview: function(){
     return this.get('viewMode') === 'overview'
   }.property('viewMode')
})

In my View, I then have simply:

{{#if viewingList}}
    {{view "itemList"}}
{{/if}}
{{#if viewingOverview}}
    {{view "overview"}}
{{/if}}

However, in this way I don’t get the advantage of using URL endpoints. Is this approach preferred to simply making new routes? If so, why? I understand the simplicity and I really dig it, but how to implement correct routing in this use case?


#2

I wouldn’t presume to know The Ember Way, but the developers have often expressed the principle that URLs should behave the way people expect them to, meaning you should be able to link to them, bookmark them, share them, and all that.

So in your case, the question is: are the overview and list of the same item separate pages, which it should be possible to link to individually, or are they both the same page in different states? To put it another way, if I go to your site and do whatever I need to in order to see the list view of some item, and then email the URL to somebody, when they click on the link in their email does it matter whether they see exactly what I saw – the list view – or would it make as much sense to see the overview with some control that said something like ‘More detail’ to get at the list? Only use separate routes if they would really need to be able to go straight to the one view or the other.

If you stick with the approach you have presently adopted, I would suggest that you think about using a component instead of a view. That, I believe, is now The Ember Way.


#3

@sunnykgupta, I agree with most of what @macavon said except for “Only use separate routes if they would really need to be able to go straight to the one view or the other.” Routes are state of your app, serialized in url form. The router converts your url into app state and sets up the app accordingly. It will do a lot for you and I would recommend for you to learn to use as much of it as possible.

In your code example, you’re actually doing a lot of the things that the Router would setup for you automatically.

For example:

  • Your controller tracks state: list or overview
  • Your controller handles transition from states ( going from list to overview and vise versa )
  • Your template handles presenting different views according to state of the controller
  • I presume that you also have itemList and overview classes that you’re not showing ( btw, view helper takes View class as a parameter. Classes should have capital names and namespaced ie. App.ItemListView )

Everything that you’re doing can be done by the Router for you.

Everything that you’re doing can be done with:

JavaScript

App = Ember.Application.create();

App.Router.map(function() {
  this.route('overview');
  this.route('listview');
});

HTML

<script type="text/x-handlebars">
    <h2>Welcome to Ember.js</h2>

    {{outlet}}
  </script>

  <script type="text/x-handlebars" data-template-name="index">
  <ul>
      <li>{{#link-to 'overview'}}Overview{{/link-to}}</li>
      <li>{{#link-to 'listview'}}Listview{{/link-to}}</li>
  </ul>
  </script>

  <script type="text/x-handlebars" data-template-name="overview">
    <h3>Overview</h3>
    
    <p>{{#link-to 'listview'}}Go to listview{{/link-to}}</p>
  </script>
  
  <script type="text/x-handlebars" data-template-name="listview">
    <h3>Listview</h3>
    
    <p>{{#link-to 'overview'}}Go to overview{{/link-to}}</p>
  </script>

Here is a JSBin http://emberjs.jsbin.com/obEWUJig/1/edit

If you use LOG_ACTIVE_GENERATION: true flag when creating your app, you can see how much Ember is actually doing for you.


#4

I think URLs are very important, and generally if you can serialize the state of your application into them you should.

Some people would definitely make the choice the user made of which graph style they were looking at integrate into the URL, but for that simple blog post it felt like a bit much. It was meant more of an example of hey, look how easy it is to use #if statements in ember and change things.


#5

view helper takes View class as a parameter. Classes should have capital names and namespaced ie. App.ItemListView

@tarasm Thank you for the pointer. I thought that by giving the lowercase parameter (like {{view 'itemList'}}) Ember would automatically look for App.ItemList, which is what it really seems to do. Parameters given to helper functions are slightly confusing.

And I totally agree that to leverage the power of Ember, the URLs should represent the state of the application as best as possible, and that’s where I partly disagree with macavon. I wasn’t really thinking about whether or not my application URL should represent the state of my application, I was thinking whether or not it was possible to use this approach and represent it in the URL.

On the other hand, you mentioned using components rather than views is the newest Ember Way. I am intrigued as I didn’t yet come to use them. Would you mind elaborating on the advantages of using a component over using a view?

And thanks @eviltrout for explaining the rationale behind your blog post. I think it is indeed an easy and straightforward way to approach the problem: as I mentioned I was indeed wondering if one could take such an easy approach and integrate it with the URLs. Thank you for all your work!


#6

You’re right, I forgot about that. Using lookup string in view handler looks funny to me, but its correct.