0

I am working on a habit tracking app. It is a port of native Android to Ember.js. A user is able to view a historical record of when they recorded various habits:

section headers

I am attempting to recreate the date section headers using Ember backed by CouchDB and D3. The code that I have to show events without section headers works:

<script type="text/x-handlebars" id="events">
  {{#each model}}
    {{#link-to 'event' this}}
      <div class="row">
        <div class="asset-id col-xs-9">{{habit.name}}</div>
        <div class="col-xs-3">{{format-time-passed time}}</div>
      </div>
    {{/link-to}}
  {{/each}}
</script>

App.EventsRoute = Ember.Route.extend( {
  model: function() {
    return this.store
      .findQuery( 'event', {
        designDoc: 'event',
        viewName: 'by_time',
        options: {
          descending: true,
          limit: 100
        }
      } )
  }
} )

The by_time view is one I've created that returns events keyed on time. This code works and displays a list of habit names and event times. The code I am trying to replace it with is:

App.EventsRoute = Ember.Route.extend( {
  model: function() {
    return this.store
      .findQuery(…)
      .then( function( data ) {
        var date = d3.time.format( '%Y-%m-%d' )
        return d3.nest()
          .key( function( d ) { return date( d.get( 'time' ) ) } )
          .rollup( function( d ) { return d } )
          .map( data.content )
      } )
  }
} )

This produces an object of the form:

{
  '2014-05-22': [*model obj*, *model obj*],
  ⋮
}

I then try to render that with the following template:

 <script type="text/x-handlebars" id="events">
   <div id="events">
     <ol>
       {{#each model}}
         <li>
           <div class="row">
             <div class="col-xs-12">{{@key}}</div>
           </div>
           <ol>
             {{#each this}}
               {{#link-to 'event' this}}
                 <li><div class="row">
                   <div class="asset-id col-xs-9">{{habit.name}}</div>
                   <div class="col-xs-3">{{format-time-passed time}}</div>
                 </div></li>
               {{/link-to}}
             {{/each}}
           </ol>
         </li>
       {{/each}}
     </ol>
   </div>
 </script>

The @key reference is from this post, but when I include it, Handlebars throws SyntaxError: Unexpected token ,. Also from that answer, I should be able to iterate over an object, but when I remove @key, I get the Error: Assertion Failed: The value that #each loops over must be an Array.

I can restructure the data to avoid this, but should I be able to iterate over object properties? I'm using Handlebars 1.1.2.

Community
  • 1
  • 1
dysbulic
  • 2,677
  • 2
  • 25
  • 40

2 Answers2

0

No, Ember Handlebars doesn't support iterating over object properties. There are some slight differences between handlebars and Ember Handlebars. Data binding being a large thing (which is why it doesn't work, it can't watch the object and consistently know that the object has changed).

You can convert it to an array, but you won't be able to watch the object in the case that an additional property is added. You'd be better off converting it to an array up front.

Kingpin2k
  • 47,007
  • 10
  • 75
  • 96
0

So the final solution looked something like:

App.EventsRoute = Ember.Route.extend( {
  model: function() {
    var self = this
    return this.store
      .findQuery( 'event', {
        designDoc: 'event',
        viewName: 'by_time',
        options: {
          descending: true,
          limit: 100
        }
      } )
      .then(
        function( data ) {
          var date = d3.time.format( '%Y-%m-%d' )
          var nested = d3.nest()
            .key( function( d ) { return date( d.get( 'time' ) ) } )
            .rollup( function( d ) { return d } )
            .map( data.content )
          var arr = []
          for( date in nested ) {
            arr.push( {
              date: date,
              events: nested[date]
            } )
          }
          return arr
        },
        function( err ) {
          alert( err.status + ": " + err.statusText )
          self.transitionTo( 'login' )
        }
      )
  }
} )
dysbulic
  • 2,677
  • 2
  • 25
  • 40