Automatically extracting data from form
Hi,
When developing a theme, you cannot know in advance which properties a product have. As a consequence, this:
CartJS.addItem(12345678, 3, {
"size": "XL"
});
Is not possible because we cannot know that it will have the "size" property. The problem is that jQuery does not have any nice built-in function to extract the data from a form in a way that is easily consumed by CartJS. Here is the boilerplate code I've been doing:
var formData = this.serializeForm(this.element.find('.product__form'));
CartJS.addItem(formData['id'], formData['quantity'], formData['properties'], {});
where serializeForm is as follow:
Plugin.prototype.serializeForm = function(form) {
var hash = {};
function stringKey(key, value) {
var beginBracket = key.lastIndexOf('[');
if (beginBracket == -1) {
var hash = {};
hash[key] = value;
return hash;
}
var newKey = key.substr(0, beginBracket),
newValue = {};
newValue[key.substring(beginBracket + 1, key.length - 1)] = value;
return stringKey(newKey, newValue);
}
var els = form.find(':input').get();
$.each(els, function() {
if (this.name && !this.disabled && (this.checked || /select|textarea/i.test(this.nodeName) || /hidden|text|search|tel|url|email|password|datetime|date|month|week|time|datetime-local|number|range|color/i.test(this.type))) {
var val = $(this).val();
$.extend(true, hash, stringKey(this.name, val));
}
});
return hash;
},
I'm not the author of this complicated code, but basically, it allows to parse the keys (such as "properties[foo]") and returns something like:
{
"id": 123,
"quantity": 1,
"properties": {
"size": "XL",
"other": "foo"
}
}
This boilerplate code is required all the time in themes. Therefore, it would be nice to have a "addItemFromForm" method that would accept any jQuery object representing a form, and do this logic internally.
I'd be happy to contribute for that, I just want to be sure you don't have a better idea for that first ;).
Bye!
Is there any reason adding a data-cart-submit attribute to the form in question wouldn't work for this use case? (Docs).
Actually I often need to do more than just submitting, like changing the button of the add to cart button, displaying "success" message... The data-cart-submit does not offer this flexibility.
Okay, fair enough. There is already the required logic inside the data-cart-submit functionality, I can look to pull it out and make it publicly accessible.
@bakura10 I have a branch to resolve this: https://github.com/discolabs/cartjs/tree/36_form.
It will add two public methods:
/**
* Expect a DOM form object.
* Returns an array of [id, quantity, properties] extracted from the form.
*/
CartJS.extractItemFromForm(form) {
...
}
/**
* Expect a DOM form object.
* Uses extractItemFromForm() to attempt to parse an item to add from the form and then adds it.
*/
CartJS.addItemFromForm(form) {
...
}
Does this look like it would solve your use case?
Perfect, that would solve it like a charm!
OK, great. I'll try to find some time to add tests and then merge.
Any news about tagging this? :)
Unfortunately I haven't had much time to work on Cart.js of late. That'll hopefully change later in the year.
In the meantime, if this is something you really need, happy to look at any PR adding tests to the above branch.