Render and data type strangeness

Render and data type strangeness

johnblythejohnblythe Posts: 92Questions: 21Answers: 2

Hey Alan,

I have a monetary field in my Editor/DT. I am printing out the data on page load as a number and then, when Datatables initializes, rendering the field with a prepended "$" like so:

if (fields[i].name == 'offerPriceUom' || fields[i].name == 'projectedSpend') {
            dtfield.render = function ( data, type, row ) {
                var num = parseFloat(data);
                // It must be the string w prepended "$", remove it
                if (isNaN(data)) {
                    num = parseFloat(data.split("$")[1]);
                }
                if (!isNaN(num)) {
                    return '$'+num;
                } else {
                    return '';
                }
            }
        }

When you initially edit the field it simply shows the numeric value, 285 for instance, after having rendered appropriately ('$285'). It saves correctly, all is well. But if you go back to the same field and click to edit (this is inline, btw), the value is now $290.00 and thus when you save it throws an error as it's attempting to save a float value and not a string.

I've patched it for now via the backend code, but am curious as to why the rendering/editing changes after the first edit. I guess I could also patch by way of manipulating the data before sending with the preSubmit() event.

Thanks for any clarity-

Answers

  • allanallan Posts: 63,302Questions: 1Answers: 10,431 Site admin

    When the data is returned from the server for the edited row, is it prefixed? Are you able to give me a link to the page?

    Thanks,
    Allan

  • johnblythejohnblythe Posts: 92Questions: 21Answers: 2

    Can't link up, unfortunately. Can setup a faker if it comes to it, though. The data comes back as a float, not a string. That's what's left me scratching my head :\ And if it didn't, it would be taken care of by the logic above, no?

  • allanallan Posts: 63,302Questions: 1Answers: 10,431 Site admin

    What is a faker? :-) I'm not sure I want to know...!

    The render function should make no difference to the underlying data. Could you show me your full code?

    Allan

  • johnblythejohnblythe Posts: 92Questions: 21Answers: 2

    Ha. I mean a faux account on a dev instance. Lots of sensitive user information floating about.

    Hmm, that's what I thought. I'll piece things together instead of dumping the entirety cause it's lengthy:

    // Setup our fields
    var fields = [
            {
                label: "Checkbox",
                name: "checkbox",
                type: 'readonly',
                className: 'readonly narrow'
            },
            {
                label: "Details",
                name: "details",
                type: "readonly",
                className: 'readonly narrow details-control'
            },
           ....
           {
                label: "Offer Price per UoM",
                name: "offerPriceUom",
                className: "offerPriceUom"
            },
    ];
    
    // Kick off the new Editor instance
        editor = new $.fn.dataTable.Editor( {
            ajax: config.base + '/pipeline/editLineItem',
            table: document.getElementById(id),
            fields: fields
        } );
    
    ...
    .on('preEdit', function(e, json, data) {
                data.offerItem        = json.OfferVenIt;
                data.offerDescription = json.OfferItDesc;
                data.offerUom         = json.OfferUOM;
                console.log("DAFUQ");
                console.log(typeof json.OfferPricePerUOM);
                console.log(json.OfferPricePerUOM);
                data.offerPriceUom    = json.OfferPricePerUOM;
                console.log(typeof data.offerPriceUom);
                console.log(data.offerPriceUom);
                console.log('sup');
                data.offerConversion  = json.OfferUOMConv;
    })
    

    both batches of log() return the correct number and a typeof number. i've gone through to make sure i'm not modifying that value directly in datatables or anything and it's not showing up anywhere else except for one line where i set it to a data- attribute on the row for ancillary purposes, so no modification to it before saving. is there somewhere between preEdit and postEdit that it could be going wrong?

  • johnblythejohnblythe Posts: 92Questions: 21Answers: 2

    Noticing something weird that I think is the problem. When I try to log something when the render function is to be called it only is called on the initiation of the DataTable, not each subsequent render (due to editing). Does the render persists like it seems?

    The reason it seems so is the second odd thing: the things I'm asking to be logged when performing the render are logged 10 times

    Hopefully this helps provide some clues!

  • allanallan Posts: 63,302Questions: 1Answers: 10,431 Site admin

    Does the render persists like it seems?

    Yes, but only until the data in replaced or invalidated. On edit, the data should be replaced. The render function should be executed immediately after the row has been updated (right after preEdit).

    Could you show me the code for where you assign dtfield.render? It looks a little odd (for lack of a better word) as it is based on an Editor field name. Unless this is part of a generic setup that you are using to build the Editor and DataTables objects perhaps?

    Allan

  • johnblythejohnblythe Posts: 92Questions: 21Answers: 2

    Sure thing. So I set the fields above in the fields[] array. Then loop through to create the DT fields before passing in to the columns option:

    var dtfields = [];
        for (i =0; i<fields.length;i++) {
            var dtfield = {data: fields[i].name, className: fields[i].className};
    
            // apply money formatting
            if (fields[i].name == 'offerPriceUom' || (fields[i].name == 'projectedSpend' && checkPremiumOffer(offerId) != -1)) {
                dtfield.render = function ( data, type, row ) {
                    var num = parseFloat(data);
                    if (!isNaN(num)) {
                        return '$'+(parseFloat(data).toFixed(2));
                    } else {
                        return '';
                    }
                }
            }
    if (fields[i].type == 'readonly') {
                dtfield.className = 'readonly';
            }
    
            dtfields.push(dtfield);
    
  • allanallan Posts: 63,302Questions: 1Answers: 10,431 Site admin

    Great - thanks!

    I must confess, I don't see any reason why that wouldn't work. Can you show me the JSON data that is being returned from the server on edit?

    Allan

  • johnblythejohnblythe Posts: 92Questions: 21Answers: 2

    You bet!

    I was in the middle of some migrations on the feature branch in which I'd found the bug which caused everything to error out until new column names, etc. had been resolved. So I swapped over to the master branch real quick and saw two things:
    1) the json returns a string for the value in this branch as opposed to the float in my feature branch
    2) (as a result?) it doesn't throw the error.

    Here's the render function in this branch:

    dtfield.render = function ( data, type, row ) {
                    var num = parseFloat(data);
                    if (!isNaN(num)) {
                        return '$'+(parseFloat(data).toFixed(2));
                    } else {
                        return '';
                    }
                }
    

    The logic here is less thorough but hardly different ultimately than the above. I'll look into it some more and report back

  • johnblythejohnblythe Posts: 92Questions: 21Answers: 2

    Even w the copied-over code things were fkn up. Decided to stop fooling with it and simply throw two lines in the PHP to accommodate a currency string coming through. The mystery will remain unsolved for the time being :\

  • allanallan Posts: 63,302Questions: 1Answers: 10,431 Site admin

    Very odd! If you are interested, I'd still be happy to take a look into it if you could send over the JSON at some point.

    But good ot hear you have a workaround now!

    Allan

  • johnblythejohnblythe Posts: 92Questions: 21Answers: 2

    There was one difference worth noting. While I'm not at a place where I can grab the JSON directly, I had in fact checked to make sure the value was being returned.

    In the working case (master branch), it came back as a string:

    {
    ...
    OfferPricePerUOM: "25.00"
    ...
    }
    

    while in the feature branch's error'ing version it was sent back as a number:

    {
    ...
    OfferPricePerUOM: 25
    ...
    }
    

    Part of my attempt to reconcile the two was not to merely copy the master's .js but also to remove the doubleval() or floatval() (can't remember which at the moment) from the PHP before sending off the payload. That didn't have any effect, unfortunately, so I'm guessing there is something else located somewhere in the processing that is throwing things off. I grep'd through the .js file for every occurrence of that variable to make sure it wasn't being passed off, received, or otherwise manipulated anywhere else and came up with nothing.

    Still scratching my head :p

This discussion has been closed.