Tom Hammond
Tom Hammond

Reputation: 6080

Backbone Save() Not Sending Post

I'm new to Backbone so hopefully I'm just missing something simple. I'm working on building a simple survey creation/survey taking app to work through nested models, etc. I'm running a restful Rails server for the back-end.

I'm struggling with getting the survey models to save to the server though. It doesn't seem like a post request is actually happening and thus it's not actually getting updated. Any ideas what I'm missing?

Survey model:

class SurveyMe.Models.Survey extends Backbone.Model

Survey Edit View:

 class SurveyMe.Views.SurveyEdit extends Backbone.View

      template: JST['templates/surveys/survey_edit']

      initialize: ->
        @model.on('all', @render, this)

      events: {
        'click #back': 'back'
        'submit #survey': 'update'
      }

      render: ->
        $(@el).html(@template(survey: @model))
        this

      back: ->
        Backbone.history.navigate("surveys",true)

      update: ->
        @model.set("title", $('#title').val())
        @model.set("survey_limit", $('#survey_limit').val())
        @model.save()
        Backbone.history.navigate("surveys",true)

Survey Edit Template:

<h1>Edit Survey</h1>
<form id="survey">
<div class="input-group">
    <span class="input-group-addon">Title:</span>
    <input id="title" type="text" class="form-control" value="<%= @survey.get('title') %>">
    <br>
</div>
<br>
<div class="input-group">
    <span class="input-group-addon">Desired Responses:</span>
    <input id="survey_limit" type="text" class="form-control" value="<%= @survey.get('survey_limit') %>">
    <br>
</div>
<hr>
<button class="btn" id="back">Back</button>
<input type="submit" class="btn" id="update" value="Update">
</form>

EDIT: Adding Index/Router/Collection

Index:

class SurveyMe.Views.SurveysIndex extends Backbone.View

  template: JST['templates/surveys/index']

  events:
    'submit #survey':'createSurvey'

  initialize: ->
    @collection.on('reset', @render, this)
    @collection.on('add', @addSurvey, this)

  render: ->
    $(@el).html(@template())
    @collection.each(@addSurvey)
    console.log(@collection.length)
    this  

  addSurvey: (survey) ->
    view = new SurveyMe.Views.Survey(model: survey)
    @$('#surveys').append(view.render().el)

  createSurvey: ->
    console.log("Survey created")

Router:

class SurveyMe.Routers.Surveys extends Backbone.Router
  routes: 
    'surveys/:id': 'edit',
    'surveys': "index"

  initialize: ->
    @collection = new SurveyMe.Collections.Surveys()
    @collection.fetch(reset: true)

  index: ->
    view = new SurveyMe.Views.SurveysIndex(collection: @collection)
    $("#container").html(view.render().el)

  edit: (id) ->
    survey = @collection.get(id)
    view = new SurveyMe.Views.SurveyEdit(model: survey)
    $("#container").html(view.render().el)

Collection:

class SurveyMe.Collections.Surveys extends Backbone.Collection

  model: SurveyMe.Models.Survey

  url: '/surveys/'

Upvotes: 0

Views: 171

Answers (3)

Subbu
Subbu

Reputation: 56

Your model should also be having something like this,

model.collection

If you pass a {collection: ...} as the options, the model gains a collection property that will be used to indicate which collection the model belongs to, and is used to help compute the model's url. The model.collection property is normally created automatically when you first add a model to a collection. Note that the reverse is not true, as passing this option to the constructor will not automatically add the model to the collection. Useful, sometimes.

One more thought, are you sure your REST url should be "/surveys"? In our application, we have separate url for models specified in the urlRoot.

For eg, if Collection c has models m1, m2,

c1 -> url (/surveys) - where surveys will accept a collection of objects

m1 , m2 -> (/survey) - where survey will accept a model (single object)

Hope this helps.

Upvotes: 0

Tallmaris
Tallmaris

Reputation: 7590

Wild guess here but it may be because you are using a simple arrow instead of a fat arrow in coffeescript:

update: ->
  @title = $('#title').val()
  @survey_limit = $('#survey_limit').val()
  this.save()

You are getting into this method from an even, which means that this is scoped to the event trigger rather than the model. Use the fat arrow:

update: =>

And it should be fine...

Upvotes: 1

dylants
dylants

Reputation: 23340

Your problem may be within the update function of your model. I don't see a fetch() call to initially populate the model, so I'm guessing the data is populated on the client side only, and sent to the server side. If this is the case, you'll need to set this data within the model. You can do this prior to the save call:

this.model.set("title", $('#title').val());
this.model.set("survey_limit", $('#survey_limit').val());

Or you could do it within the save call directly:

this.model.save({
   title: $('#title').val(),
   survey_limit: $('#survey_limit').val()
});

You can do this within the model, but as you can see from the code above I'd recommend putting that logic in the view instead. This way the model doesn't have to understand what's on the view itself.

Upvotes: 0

Related Questions