0

I have very complex forms in my application with update functionality where user may change only few fields click on save button to submit data to server. My application uses backbone, syphon, JQuery and underscoreJs.

What is the best way to control what fields can be sent to server using only with these libraries which can be used across several pages within my application? Something like reusable functionality will be helpful.

I have tried model.changedAttributes() function which doesn't seem to be working as expected. Most of the times, it is returning false. I have the following code where form data gets serialized using syphon then will be converted into my app specific format to send to API.

formSave: function(e) {
    var data = changeToWriteApiFormat(Backbone.Syphon.serialize($(e.currentTarget).closest('form.event_form')[0]));
    this.model.clear();
    this.model.id = this.parentObj.model.id;

    this.model.set(data);

    if (this.model.isValid(true)) {
      this.model.save(removeObjIndexCollection(data), {
          url: this.model.url().replace(gc.readApiUrl, gc.publishApiUrl),
          patch: true,
          beforeSend: ToolsHelper.setPublishHeader,
          success: function(model, response) {
            $('#event_success').show();
            $('#event_failure').hide();
          },
          error: function(model, response) {
            $('#event_failure').show();
            $('#event_success').hide();
          }

        }
      }
T J
  • 42,762
  • 13
  • 83
  • 138
user1614862
  • 3,701
  • 7
  • 29
  • 46
  • If you want to control what gets sent to server, best place would be to override the concerned method as `save` with your custom logic to detect the changed fields. – T J May 20 '16 at 11:29
  • I am looking for some inbuilt solution. – user1614862 May 20 '16 at 17:51

1 Answers1

0

model.changedAttributes() does only work if you had some attributes set before on this.model, but since you cleard them via this.model.clear(); it will return false.

Also "save" will only be executed if validate returns valid, you don't have to call isValid extra.

The "patch:true" attribute is correct, but will also work only if you have set the previous values.

try this:

formSave: function(e) {
    var data = changeToWriteApiFormat(Backbone.Syphon.serialize($(e.currentTarget).closest('form.event_form')[0]));

        this.parentObj.model.save(removeObjIndexCollection(data), {
           url: this.model.url().replace(gc.readApiUrl, gc.publishApiUrl),
           patch: true,
           beforeSend: ToolsHelper.setPublishHeader,
           success : function(model, response) {
               $('#event_success').show();
               $('#event_failure').hide();
           },
           error : function(model, response) {
               $('#event_failure').show();
               $('#event_success').hide();
           }

         }
}

Edit: here an example of changedAttributes:

var model = new Backbone.Model();

model.set({
    val1 : 'init',
    val2 : 'init'
});

// .. whatever

var newChangesFromForm = {
    val2 : "changed",
    val1 : 'init' // won't be set, because it's the same value
};
model.on('change', function() {
    var changes = model.changedAttributes();

    alert(JSON.stringify(changes));
});
model.set(newChangesFromForm);
zoggole
  • 46
  • 6
  • I tried calling model.changedAttributes() before clearing the model. It did not work. My model has initial attributes set at the time of initialization of the view. The only problem is cannot differentiate between these two sets of values when I call model.changedAttributes(). It is always returning false even without clear. – user1614862 May 20 '16 at 17:53
  • I added an example with .changedAttributes(), hope this works for you. – zoggole May 23 '16 at 11:21