32

I have the following code:

$.post('block_ajax.php'
    ,   {   'action': 'set_layout'
        ,   'listid': 123
        ,   'layout': []
        }
    ,   function(data) {
            // ...
        }
);

The recieving script (block_ajax.php) only recieves the "action" and "listid" parameters. When I inspect what is sent using Chrome, I see the "layout" parameter isn't even send to the backend script.

Since there is a difference between an empty array and the absence of an array, I'd like to have JQuery send the empty array. I can find some indications that JQuery (1.6.1) seems to do this, but not how to stop it from doing so. JSON format allows for empty arrays and empty objects, so I think it should be possible.

Does anybody know what to change so JQuery can send empty arrays?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Why send an empty parameter? If you want to set a flag or token or something, just do `layout: true`. – Bojangles Jul 08 '11 at 09:05
  • try `"[]"`. Should do the trick – eagor Oct 03 '16 at 14:46
  • This is called the [Null Object Pattern](https://en.wikipedia.org/wiki/Null_object_pattern) -- this prevents you from having to check whether the array is even present before attempting to e.g. iterate over it. – Charles Wood Oct 03 '19 at 20:17

7 Answers7

17

Our organization has two approaches to the problem:

  • Sending data as JSON as opposed to POST-data is a good all-purpose approach, though this is sometimes a little bit difficult to integrate with frameworks like Rails, because you may have to add explicit back-end calls to decode the JSON data.
  • [""] as noted by vinod will work well, as many frameworks (e.g. Rails) will often treat this as an empty array. (for the reason, see this Stack Overflow answer).
    • Note: This works when trying to integrate with some aspects of Rails, specifically when sending a list of ids of objects that are related by a has_many relationship. E.g. if you have a foos table and a bars table, and foos has_many :bars through :foo_bars, a way to remove all associations on a foo object is to pass foo: { bar_ids: [""] }.

Both approaches are hackier than desired, and I would be glad to discover a cleaner approach.

Community
  • 1
  • 1
Luke Knepper
  • 931
  • 8
  • 18
  • 1
    Good answer, but actually rails doesn't treat `['']` as an empty array: `[''].empty? # => false` `[''].blank? # => false` – Alter Lagos Nov 17 '16 at 15:37
  • @AlterLagos Correct, in the general case, but when received as POST-data, Rails seems to treat `['']` as an empty array. (E.g. in the example from my note, Rails doesn't create a relation mapping the specified `foo` to `bar_id: ""` -- it just deletes all foo/bar relations) – Luke Knepper Nov 17 '16 at 22:07
  • 1
    Oh nvm, I just realized about your note and, in fact, that should apply just for lists of ids. In my case it was a json field and because of that it was saved into the db like an array with an empty string. – Alter Lagos Nov 17 '16 at 23:56
4

2018, Sorry to answer old question, but here's a better answer IMHO:

var arr = [];

$.post('block_ajax.php', {
    'action': 'set_layout',
    'listid': 123,
    'layout': arr.toString() // It'll be empty string "" if array is empty, otherwise if array has value(s) it will be a string of comma-separated values
}, function(data) {
    // ...
});

Examples:

var layout = [].toString();// layout will be '' (empty string)
var layout = [1,2,3].toString();// layout will be string with comma-separated values '1,2,3' 

In back-end, whether it's empty string or comma-separated string, it will always be posted, just convert it to array.

Back-end (PHP example):

$layout = explode(',', $_POST['layout']);
evilReiko
  • 19,501
  • 24
  • 86
  • 102
  • The problem is that it only works for simple objects. If you have: `var arr=[{test:true}];` the `toString()` method will serialize the array to `[object Object]` – julodnik Nov 08 '18 at 11:01
1

i think json will help in such a case

encode the array in js and send the result then decode it in php

but this will take some resource

Robert
  • 2,342
  • 2
  • 24
  • 41
  • 1
    this works like a charm.. had some troubles since I use wordpress (need to apply unsplash on the json string) thank you! – Ido Cohen Jan 24 '21 at 11:57
0

Try this:

(isset($_POST['layout'])) ? $_POST['layout'] : array();

to get a new empty array if the passed array is empty, the "real" array with data otherwise.

akluth
  • 8,393
  • 5
  • 38
  • 42
  • 2
    This will work for simple cases, however it is still annoying –  Feb 07 '13 at 13:02
  • 3
    I know thi is a very, very, old answer, but I need to downvote this as it does not answer the question at all. You are merely 'fixing' the results of the bug, not the bug itself. The user does not want an empty array if he does not have any, the user wants to send empty arrays. There is a huge difference between A: A list that is empty, B: Nothing. – thisisboris Dec 21 '16 at 17:23
  • The very thing the OP wanted to avoid having to do. – Epirocks Jun 15 '18 at 15:41
0

I solved this the following way, which I feel is easiest to read. Supposing there's an array myArray which could be populated or empty:

'requestParam': myArray.length === 0 ? '' : myArray

Even when empty, jQuery will not omit the requestParam argument.

-1

I found a simple cheat that works

$.post('block_ajax.php'
    ,   {   'action': 'set_layout'
        ,   'listid': 123
        ,   'layout': [{}]
        }
    ,   function(data) {
            // ...
        }
);

Notice I defined the empty array as [{}]. The jQuery ajax command just sends an empty array without the empty object.

NOTE: [[]] does not work.

Justin Levene
  • 1,630
  • 19
  • 17
-4

EDIT: See Luke's answer for a better solution: https://stackoverflow.com/a/31996181/827437

I've left my previous answer specific to how Rails handles [""] below, as the link above explains.


Note: Rails-specific

I am not sure why you need to send a blank parameter. Merely checking the existence of the parameter in the PHP script should be enough. However, if you really want to do it, use 'layout': [""] instead of 'layout': []. The parameter should be sent.

(In addition, you might want to rename layout to layout[] to indicate it's an array, but this is unnecessary.)

vinod
  • 2,358
  • 19
  • 26
  • 1
    The code maintains a tree structure of containers with fields in them. The clientside script needs to communicate with the backend whether containers have been emptied (blank array) or are completely removed from the tree (no entry). – Martijn van der Lee Jul 11 '11 at 08:20
  • 1
    Consider that I have list `items` which user deletes in complex model. Normally i update only changed fields. If i get no param at all, field will not get updated and list of item will not get updated - but all items should be deleted when i set `items = array()` right? Or even `items = null`, but without any (post/get) info model is not aware if it should even touch `items` field! –  Feb 07 '13 at 13:01
  • PeterM did you find a solution to this? I'm experiencing exactly what you stated. If empty array is sent I want to remove all items, if an array has items I want to add the ones that aren't already there and remove the ones that should no longer be there. Finally, nothing or null should skip the check. – Autonomy Apr 19 '13 at 00:48
  • Blank parameters are used a lot, for example, we have a list of favorites on a page, this list uses the same endpoint as the overal entititieslist, with the addition that it sends along a 'filter' of ID's that is used as searchparam in our Solr. Sending NO list, equals no filters, equals retrieving ALL entities, an empty list however would render a result with 0 entities. There's your huge difference between no list and an empty list, and thus why you sometimes send blank parameters. – thisisboris Dec 21 '16 at 17:26
  • 2
    This isn't an answer -- now you're sending a non-empty array with a fake value that will cause more backend coding to interpret the situation. If we can't truly send an empty array, then a simple test on the back for the presence of the parm, which others probably have suggested, is much cleaner to deal with the overall issue. – grantwparks Jul 20 '18 at 15:35