quirkey / sammy

Sammy is a tiny javascript framework built on top of jQuery, It's RESTful Evented Javascript.
http://sammyjs.org
MIT License
2.99k stars 384 forks source link

POST calls do not change URL #243

Open legacybass opened 9 years ago

legacybass commented 9 years ago

Given a series of pages in an SPA, if one of them tries to POST data to another page, the URL doesn't change. For example, if I am currently on /MyApp/#/Login and try to post the user data to /MyApp/#/OtherPage, the url will remain as /MyApp/#/Login. The page will correctly change, the route handlers are correctly called, and the login data is correctly passed, but the url remains the same.

Here's a jsfiddle that demonstrates the problem: http://jsfiddle.net/legacybass/25u8ye83/

aplicacionamedida commented 7 years ago

This strange behaviour only happens with verbs different to GET.

I think that this behaviour is a feature for these reasons:

I want to explain this behaviour: Short answer:

 setLocation() is not called for verbs different than GET.

Long answer: The function Sammy.Application.run() has these lines of code (line numbers 996-1001):

      // bind to submit to capture post/put/delete routes
      this.bind('submit', function(e) {
        if ( !Sammy.targetIsThisWindow(e, 'form') ) { return true; }
        var returned = app._checkFormSubmission($(e.target).closest('form'));
        return (returned === false) ? e.preventDefault() : false;
      });

They are binding all submit events to an anonymous function. Observe that this anonymous function has a call to this other function:

Sammy.Application._checkFormSubmission()

This function is the responsible of this behaviour:

    _checkFormSubmission: function(form) {
      var $form, path, verb, params, returned;
      this.trigger('check-form-submission', {form: form});
      $form = $(form);
      path  = $form.attr('action') || '';
      verb  = this._getFormVerb($form);

      if (this.debug) {
        this.log('_checkFormSubmission', $form, path, verb);
      }

      if (verb === 'get') {
        params = this._serializeFormParams($form);
        if (params !== '') { path += '?' + params; }
        this.setLocation(path);
        returned = false;
      } else {
        params = $.extend({}, this._parseFormParams($form));
        returned = this.runRoute(verb, path, params, form.get(0));
      }
      return (typeof returned == 'undefined') ? false : returned;
    },

These are the important lines:

      if (verb === 'get') {
        params = this._serializeFormParams($form);
        if (params !== '') { path += '?' + params; }
        this.setLocation(path);
        returned = false;
      } else {
        params = $.extend({}, this._parseFormParams($form));
        returned = this.runRoute(verb, path, params, form.get(0));
      }
      return (typeof returned == 'undefined') ? false : returned;

If verb is "get" then _checkFormSubmission() change the location:

this.setLocation(path);

If verb is not "get" ,the the location is not changed. (runRoute() doesn't change the location.)