Link to home
Start Free TrialLog in
Avatar of Crazy Horse
Crazy HorseFlag for South Africa

asked on

How to send data array using jQuery and Ajax

How would I pass an array into the data property of an Ajax request?

I am getting data from a 3rd party API which has categories and sub categories. This is basically how I look at the data:

			jQuery.each(data.Body.Categories, function(index, value) {
				console.log('CategoryName: ', value.CategoryName);
				jQuery.each(value.SubCategories, function(key, val) {
					console.log('Sub-CategoryName: ', val.CategoryName);
				});
			});

Open in new window


I want to post that data to WooCommerce  

			jQuery.ajax({
				url: myData.root_url  + '/wp-json/wc/v3/products/categories/',
				type: 'POST',
  				beforeSend: (xhr) => {
					xhr.setRequestHeader('X-WP-Nonce', myData.nonce);
				},
				data: {
					name:  // need to send an array of values here eg:. cat1, cat2, cat3 and subcategories
				},
			})

Open in new window

Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Just put the array in to the value of the name property

jQuery.ajax({
            url: myData.root_url  + '/wp-json/wc/v3/products/categories/',
            type: 'POST',
              beforeSend: (xhr) => {
               xhr.setRequestHeader('X-WP-Nonce', myData.nonce);
            },
            data: {
               name: data
            },
         })

Open in new window


This will result in
{
  name: [... arrray data ...]
}

Open in new window

Avatar of Crazy Horse

ASKER

Hi Julian, thanks for that.

I tried it and get a 400 error: name is not of type string

I don't think I can just send 'data' because that itself is a massive array with all sorts of data in it. I just want to get the category name and any subcategory names. To get this from the array before I looped over them I did the below, just to illustrate how you have to dig to get the category names.


console.log(data.Body.Categories[0].CategoryName);
console.log(data.Body.Categories[0].SubCategories[0].CategoryName);

Open in new window

Please post an example of the object

You likely need to "map" of the catgegories
As text please. I am not going to OCR this ;)
Ah, sorry!

Is this okay?

Body:
   Categories: Array(7)
0:
   Behaviour: 0
CategoryId: 445
CategoryImageUrl: "http://"
CategoryImageUrl2x: "http://"
CategoryImageUrl3x: "http://"
CategoryName: "Brands"
FilterValueId: 7
ProductCount: 1174
RelativePosition: 1
SubCategories: Array(22)
0: {
   CategoryId: 1017,
   SubCategories: Array(0),
   CategoryName: "cat 1",
   RelativePosition: 1,
   Behaviour: 0,
   …
}
1: {
   CategoryId: 946,
   SubCategories: Array(0),
   CategoryName: "cat2",
   RelativePosition: 2,
   Behaviour: 0,
   …
}
2: {
   CategoryId: 947,
   SubCategories: Array(0),
   CategoryName: "cat3",
   RelativePosition: 3,
   Behaviour: 0,
   …
}

Open in new window

Does this work for you?

https://jsfiddle.net/mplungjan/hxwmpa9s/

let arr = data.Body.Categories.map(item => [item.CategoryName, ...item.SubCategories.map(subItem => subItem.CategoryId)]).flat();
console.log("arr", arr)

Open in new window


Please note I renamed the subItem to CategoryId because that was what I could see in your screen shot
Thanks, that is giving me a response but when I try to submit it I get a 400 error.

         jQuery.ajax({
            url: myData.root_url  + '/wp-json/wc/v3/products/categories/',
            type: 'POST',
              beforeSend: (xhr) => {
               xhr.setRequestHeader('X-WP-Nonce', myData.nonce);
            },
            data: {
               name:  data.Body.Categories.map(item => [item.CategoryName, ...item.SubCategories.map(subItem => subItem.CategoryId)]).flat()
            },
         })

Open in new window

Getting an error back after trying that. Not super specific though

{"code":"db_insert_error","message":"Could not insert term into the database.","data":{"status":400}}

Open in new window

Better to do it outside



let arr = data.Body.Categories.map( item => 
  [item.CategoryName,...item.SubCategories.map(subItem => subItem.CategoryName)]
);
console.log("arr",arr)

$.ajax(


    data: { name : arr},

Open in new window



Perhaps you need to stringify it and use dataType: 'json',
Can you try by hand?

data: {  name:  ["cat1","cat2","cat3"] },

Open in new window

Sorry, I saw you updated your answer. That gives me a new error. Will try by hand now..

"code":"rest_invalid_param","message":"Invalid parameter(s): name","data":{"status":400,"params":{"name":"name is not of type string."}}}

Open in new window

Just tried by hand as well

{"code":"rest_invalid_param","message":"Invalid parameter(s): name","data":{"status":400,"params":{"name":"name is not of type string."}}}

Open in new window

The error is self explanatory - you are sending an array to a service that expects a string.
Your service won't accept this
{
   name: [a,b,c]
}

Open in new window

It is expecting this
{
    name: "string value"
}

Open in new window


The original question was how to send an array as part of an AJAX request - which has been answered - you just included it in the outgoing structure.

Your problem is slightly different - your service is expecting data in a particular form and you are not matching that so lets go back to the service and see what is expected there and decide if you need to change your service to accept an array or your request to send a string.
Quite right Julian, I thought that perhaps there was something wrong with the data but it just seems strange that woocommrece wouldn't accept an array of category names. So basically it wants you to only add one at a time then if it won't accept the array.

https://woocommerce.github.io/woocommerce-rest-api-docs/#create-a-product-category
Seems like I just needed to read a bit better. The title was update batches so I ignored it but after looking at it there is a way to create too

            data: {
               create: [{name: 'cat1'}, {name: 'cat2'}]
            },

Open in new window

Yup - the API document says on the input spec

namestringCategory name. 

It is expecting them one at a time.
Thanks Michel,

I am not getting any errors now but the categories are still empty which is weird. If I do it manually then it is populating categories so the format is correct now I think.

The array has data in it, so it's not that the data is empty.
Perhaps the issue is that I am meant to send an array with objects in it but I am sending multiple arrays now?

  1. 0: Array(1)

    Open in new window

    1. 0: {name: "Cat1"}

      Open in new window

    2. length: 1

      Open in new window

    3. __proto__: Array(0)

      Open in new window

  2. 1: Array(1)

    Open in new window

    1. 0: {name: "Cat2"}

      Open in new window

    2. length: 1

      Open in new window

    3. __proto__: Array(0)

      Open in new window


ASKER CERTIFIED SOLUTION
Avatar of Michel Plungjan
Michel Plungjan
Flag of Denmark image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Perhaps the issue is that I am meant to send an array with objects in it but I am sending multiple arrays now? 
If you are talking about the categories service then the API does not say anything about an array of objects.

Look at the codes samples provided - it is quite clear that Category is a string only
const data = {
  name: "Clothing",
  image: {
    src: "http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_2_front.jpg"
  }
};

WooCommerce.post("products/categories", data)
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.log(error.response.data);
  });


Open in new window



If you look at the batches then this works:

create: [{name: 'cat1'}, {name: 'cat2'}]

Open in new window


I tested this above and it works

https://woocommerce.github.io/woocommerce-rest-api-docs/?javascript#batch-update-product-categories


@Michel,
The good news is that your code is now inserting all the categories in WooCommerce! The bad news is that the categories aren't nested. I am guessing that is because you flattened them and/or WooCommerce API doesn't cater for inserting nested data, I am not sure. 
Ah - that is a different API - your question was about the categories API.
Yeah, from your initial question I gathered you wanted a flat array and not a nested one. I can nest it if you find out a way to send it
Hmm. Thanks Julian, looks like you have to do something like this:

I will try a hardcoded one... 

{ "product_category": { "name": "New Subcategory", "parent": 52 } }'
Okay, so this is getting confusing now, haha.

This creates a subcategory for the parent category with ID 574

 create: [{ "name": "New Subcategory", "parent": 574 } ]

Open in new window


So, somehow I would have to loop through categories and add them first and then add the subcategories. The thing is though, that parent category is a WooCommerce ID which won't be the same as the category ID from the API. Not sure that this is actually going to work..
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks Julian, think I am going to close this question off now so this doesn't get too long. I might ask again if I get to the point where you mentioned I should rather do this with php then trying to do it inside my Ajax request.

If it were up to me, I wouldn't even save the data into WooCommerce. I would just use a frontend framework/library to display the data directly from the API and then use a third party cart system to handle the checkout. Not sure if that would be possible but seems less long winded.

I understand the desire to store the data so that if the API goes down users can still browse the products from the WooCommerce database, but other than that it seems like a lot of unnecessary work. 


Thanks to both of your for you, your assistance is much appreciated.