Rystraum
Rystraum

Reputation: 2025

EmberJS: How to update model attributes

I've got a list of messages that are provided by a Rails backend. What I need is when the "toggle_visibility" action button is pressed, it would toggle the "publicly_viewable" property. This means, making a corresponding REST call (to effect the database) and changing the state of the corresponding cached message. Here is where I'm at so far.

Here's what I've got so far, that manages to end up on the debug console:

# app.js
App.Store = DS.Store.extend({
  revision: 12,
  adapter: DS.RESTAdapter.extend({
    url: 'http://localhost:3000'
  })
});

App.Message = DS.Model.extend({
  body: DS.attr('string'),
  mobile_number: DS.attr('string'),
  publicly_viewable: DS.attr('boolean'),
  created_at: DS.attr('date')
});

App.Router.map(function() {
  this.resource('messages');
});

App.MessagesRoute = Ember.Route.extend({
  model: function() { return App.Message.find() }
});

App.MessagesController = Ember.ArrayController.extend({
  toggle_visibility: function(){
    debugger;
  }
});

# index.html
{{#each model}}
<button class="close" {{action toggle_visibility this}}><i class="icon-eye-close"></i></button>
<p class="message_body lead">{{body}}</p>
<small class="source_number">from {{mobile_number}}, received {{date created_at}}</small>
{{/each}}

I've been spending the past few hours reading through the Ember Guides and while I've gotten an idea on what the different classes there are, I still can't visualize clearly how to go about it. Particularly, I'm not sure if this should be a route concern or a controller, and I know that if ever it was a controller responsibility, I know that it should be on an ObjectController but I've been having trouble making it work.

Upvotes: 1

Views: 3201

Answers (1)

MilkyWayJoe
MilkyWayJoe

Reputation: 9092

You can use ArrayController#itemController and define a controller for the individual record in your ModelArray. Then you have to specify in the Array Controller the Object Controller responsible for a single object, which you have to reference as well in Handlebars. You can do something like this:

JS:

App.MessageController = Ember.ObjectController.extend({
    visibilityClass: function() {
        var visibility = this.get('model.publiclyViewable');
        return 'toggle-visibility mdi-action-visibility%@'.fmt(
            visibility ? '':'-off'
        );
    }.property('model.publiclyViewable'),
    actions: {
        toggleVisibility: function() { 
            var model = this.get('model');
            model.toggleProperty('publiclyViewable');
            model.save();
        }
    }
});

Handlebars:

<script type="text/x-handlebars" data-template-name="messages">
    <!-- 
    At this point the {{each}} helper will know how to lookup for
    the controller simply by it's name
    -->
    {{#each model itemController="message"}}
    <div class="panel panel-primary">
        <div class="panel-heading">
            <div class="pull-left">
                <h3 class="panel-title">{{title}}</h3>
            </div>
            <div class="pull-right">
                <a {{action 'toggleVisibility'}}>
                    <i class={{visibilityClass}} style="color: #FFF"></i>
                </a>
            </div>
        </div>
        <div class="panel-body">
          {{body}}
        </div>
        <div class="panel-footer">
          <i class="mdi-communication-quick-contacts-dialer"></i> {{mobileNumber}}
          <i class="mdi-notification-event-note"></i> {{createdAt}} 
        </div>
    </div>

    {{/each}}
</script> 

(see fiddle)

Note: Updated to Ember 1.11.x-beta and changed the code a little bit

Upvotes: 2

Related Questions