marioizquierdo / jquery.serializeJSON

Serialize an HTML Form to a JavaScript Object, supporting nested attributes and arrays.
MIT License
1.71k stars 433 forks source link

Provide dom element into custom type function #109

Closed v-braun closed 3 years ago

v-braun commented 3 years ago

The customType function receives only the raw string value, it would be helpful to get the dom element as an additional parameter.

I am using Autonumeric for masked inputs and these plugin add's a currency symbol, so the JSON value is than a string instead of a number.

I think this is not only an autonumeric issue, the possibility to have access to the dom element themself would make this plugin more compatible with other plugins.

marioizquierdo commented 3 years ago

Interesting proposal. Could you provide an example of such integration with another plugin?

v-braun commented 3 years ago

sure!

example given this html:

<input type="text" id="price" />

and these js:

// init autonumeric, will set a mask with the € sign on the input
let numericInput = new AutoNumeric('#price', 'euro');

// store the numericInput within the jquery object
$('#price').data('autonumeric', numericInput);

getting the value from '#price' would return a string like '10,00 €' wich has to be converted into a number manual before sending it to an API.

It would be cool to have something like this:

add custom type

<input type="text" id="price" data-value-type="autonumeric" />

and JS

$('form').serializeJSON({
  customTypes: {
    // see 2nd argument wich is the dom element
    autonumeric: (str, el) => { 
       // str is here "10,00 €"'
       let numericWraper = el.data('autonumeric');
       let val = numericWraper.getNumber();

       // val is now 10.00 (and typeof val === 'number')
       return val; 
    },
  }
});

Hope that helps 😊

Implementation proposal

I think it would be good if the function 'attrFromInputWithName' could return also the element and not only the attribute:

        attrFromInputWithName: function($form, name, attrName) {
            var escapedName = name.replace(/(:|\.|\[|\]|\s)/g, "\\$1"); // every non-standard character need to be escaped by \\
            var selector = "[name=\"" + escapedName + "\"]";
            var $input = $form.find(selector).add($form.filter(selector)); // NOTE: this returns only the first $input element if multiple are matched with the same name (i.e. an "array[]"). So, arrays with different element types specified through the data-value-type attr is not supported.
            return {
                attr: $input.attr(attrName),
                element: $input,
            };
        }

This should be handled in this and this line. But can be passed into the type function within this line.

marioizquierdo commented 3 years ago

Nice example! It is a lot more clear now.

The attrFromInputWithName method would also need to account for multiple elements having the same name, which happens on arrays defined like attrname[]. So far I only used it for data-value-type which usually have the same type on all array elements, but this would have to find every element so it is properly passed into the customType function. I think it is possible by returning an array instead of a single element. I'll look into this soon, thanks!

v-braun commented 3 years ago

Good point!

marioizquierdo commented 3 years ago

This was implemented on #115 and released on version 3.2.0