Don’t use array as argument for AJAX call with Prototype

I’m using Prototype JavaScript library and today I have learned one thing. To make Your life easier do not use JavaScript Arrays as arguments for AJAX calls.

I’m talking about parameters option in Ajax objects (Ajax.Request, Ajax.Updater, etc). Let’s take simple HTML snippet (public/test.html):

<div id="out"></div>
<script src="/javascripts/prototype.js" type="text/javascript"></script>
<script type="text/javascript">
    addr = []
    addr[1] = 2
    new Ajax.Updater ("out", "/controllers/test", {parameters: addr })
</script>

Now simple Controller controller :)

class ControllersController < ApplicationController
  def test
    render :layout => false
  end
end

And test.html.erb:

<%= debug params %>

Simple, isn’t it? What do You expect to be displayed when You point Your browser to /test? Something like:

--- !map:HashWithIndifferentAccess 
action: test
"1": "2"
controller: controllers

Wrong!

Real output is like:

--- !map:HashWithIndifferentAccess 
uniq: |-
  function (sorted) {
      return this.inject([], function (array, value, index) {if (0 == index || (sorted ? array.last() != value : !array.include(value))) {array.push(value);}return array;});
  }
without: |-
  function () {
      var values = $A(arguments);
      return this.select(function (value) {return !values.include(value);});
  }
size: |-
  function () {
      return this.length;
  }
zip: |-
  function () {
      var iterator = Prototype.K, args = $A(arguments);
      if (Object.isFunction(args.last())) {
          iterator = args.pop();
      }
      var collections = [this].concat(args).map($A);
      return this.map(function (value, index) {return iterator(collections.pluck(index));});
  }
toArray: |-
  function () {
      return [].concat(this);
  }
findAll: |-
  function (iterator, context) {
      iterator = iterator.bind(context);
      var results = [];
      this.each(function (value, index) {if (iterator(value, index)) {results.push(value);}});
      return results;
  }

[CUT]

What is going on?

It seems that it is some bug with serialization of Arrays. Prototype does iterate through all properties, and dumps them not matter if it property is function or not (maybe Prototype has own reasons for that behavior). So how to get output like in the first dump? Use Hash, Luke:

//    addr = []
    addr = {}

Does work as expected.

3 thoughts on “Don’t use array as argument for AJAX call with Prototype

  1. Pingback: Nabble - RubyOnRails Fans - passing an array of javascript objects to server?

  2. I’ve had a few issues with this solutions. When I tried your suggestion and declared the array as:

    var something = {};

    It came through as [object Object]. I found that the complete solution was the following:

    var something = [];
    something[0] = “bimmer”;
    something[1] = “empire”;
    Ajax.Request(‘process.php’, { method:’post’, parameters: { ‘something[]’:something } });

    This actually results in PHP having an associative array with proper structure/etc.

    Sorry if this isn’t completely related to your example above. I was simply trying to pass a js array through Prototype’s Ajax.Request()|Updater()

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.