Search code examples
jqueryjsrenderjsviews

jsviews: How to trigger model data update on form submit instead of onkeydown


I recently came across jsrender/jsviews. In my first attempt I implemented a form using two way data linking/binding. This works but it immediately changes the model data as soon as the user types something into the input field.

The pattern I would like to implement is to update the model data on form submit allowing the user to easily cancel any edits they make.

Right now I've modified my form template to use one way binding and then I simply use jquery and pull the values out of the DOM and update the model data using $.observable(..).setProperty(...) when the user submits the form.

It works but it's terribly ugly. I assume there has to be a cleaner way that doesn't involve directly querying the DOM for the current values of the form elements.

Is there a clean way to trigger a model data update in an onsubmit handler in jsviews? Or what is the preferred way of implementing this usage pattern?

Basically I'm looking to achieve the same thing as is mentioned in this AngularJS question: Is there a pattern for dealing with "Cancel" in AngularJS modal dialogs? (i.e. something equivalent to ng-model-options="{ updateOn: 'submit' }" )


Solution

  • The two-way binding is to the View Model, not to the Model - so it is the data that corresponds to the View rendered to the user in the browser. The View may change, driven by View Model changes, without updating the Model on the server.

    You can bind to the Submit action of the form. <form data-link="{on 'submit' saveData}">: which will trigger the saveData method in which you can submit the appropriate current View Model data to the server where it will update the Model.

    But if you want to have an Undo feature you need to make a snapshot of the View Model when it is initialized or updated from the server, or when the saveData method was last called to save current View Model data back to the server. The Undo button will revert to the last snapshot.

    Compiled View Models provide features (map, merge and unmap) which make 'snapshooting' easy:

    undo: function() {
      this.merge(savedData); // Revert to previous savedData
      ...
    },
    saveData: function() {
      savedData = this.unmap(); // Save current data, for subsequent Undo behavior
      ...
    }
    

    Here are some JsFiddles, which show binding to the submit action, complete with an Undo button for reverting to the last saved state:

    • This one which uses plain JavaScript objects.
    • This one which uses compiled View Models
    • This one which is more advanced/complex - with multiple compiled View Models. (It will be a sample on jsviews.com at some point...)