rows().data( arr ).draw() updates only 1 time.

rows().data( arr ).draw() updates only 1 time.

minifiredragonminifiredragon Posts: 82Questions: 16Answers: 2
edited August 2016 in DataTables 1.10

I have been trying to get my live data to update itself. I am finding that it works once, and then never again (once per row) until I refresh the table. So I am not sure what I am doing wrong. Here is the code blocks for what is happening:

This is the table init:

$j('#allOrdersTable').DataTable(
        {
            data: o.single,
            paging: false,
            autoWidth: true,
            searching: true,
            language: {searchPlaceholder: "Please us scan field"},
            order: [[ 8, "asc" ]],
            initComplete: function(settings, json)
            {
                setRowSelection($j(this).attr('id'),0); //send table id
                initMailSelect('sl_ship');
                initWeightChange('t_wt');
                printSingleButton('btn_extra');
                initRemovButton('btn_remove');
                initChangeAddress('popAddress');
                $j('#sysBox').empty().hide().dialog('destroy');
                $j("#allOrdersTable_info").detach().prependTo('#allOrdersTable_wrapper');
                $j("#allOrdersTable_wrapper").prepend( $j('#selCount') );
                $j('#selCount').html('Total Selected: 0');
                $j('#btn_picklist').prop('disabled',false);
                getFulfilledOrders();
                //need to look for duplicate orderID's as these are multiples and hide them.
            },
            rowCallback: function( row, data )
            {
                if ( $j.inArray(data.DT_RowId, selected) !== -1 ) {
                    $j(row).addClass('selected');
                }
            },
            columnDefs:
            [
                { targets: 0, data:'orderID', render: function ( data, type, full, meta )
                    {
                        return '<input type="checkbox" name="chk_ship" id="allChk'+data+'" value="'+data+'" />' ;
                    }
                },
                { targets: 5, data:'orderID', render: function ( data, type, full, meta )
                    {
                        var opt = buildShipOptions(o.single[meta.row]);//build the shipping options list for the select.
                        var msg = '<select id="sl_ship'+data+'" name="sl_ship" data-sl_cost="'+full.amzInfo.mailing+'" data-sl_hot="'+full.amzInfo.hotMail+'" data-sl_wt="'+full.shipWt+'" data-speed="'+full.speed+'">'+opt+'</select>'
                        return msg ;
                    }
                },
                { targets: 6, data:'orderID', render: function ( data, type, full, meta )
                    {
                        var lb= parseInt(full.shipWt);
                        var oz= Math.ceil((full.shipWt - lb)* 16) ;         
                        
                        if( oz == 16 )
                        { 
                            lb++;
                            oz = 0;
                        }

                        var msg='<input type="text" id="t_lb'+data+'" name="t_wt" value="'+lb+'" data-type="lb"  data-orderid="'+data+'" data-row="'+meta.row+'" style="float:left; width:15px; clear:none;" /><label style="float:left; width:10px; font-weight:normal; font-size:10px; clear:none;">lb</label><input type="text" id="t_oz'+data+'" name="t_wt" value="'+oz+'" data-type="oz" data-orderid="'+data+'" size="1" style="float:left; width:15px; clear:none;" /><!-- <label style="float:left; width:10px; font-weight:normal; font-size:10px;">oz</label>-->'
                        return msg;
                    }
                },
                { targets: 10, data:'orderID', render: function ( data, type, full, meta )
                    {
                        return '<input type="button" name="btn_extra" id="chk'+data+'" value="Extra Labels" data-orderid="'+data+'" />' ;
                        //return 0;
                    }
                },
                { targets: 11, data:'orderID', render: function ( data, type, full, meta )
                    {
                        return '<input type="button" name="btn_remove" id="btn_rem'+data+'" value="Remove" data-orderid="'+data+'" />' ;
                        //return 0;
                    }
                },
            ],
            columns:
            [
                 null,
                {data:'qty'},
                {data:'prodName'},
                {data:'name', className:'popAddress'},
                {data:'state', className:'popAddress'},
                null,
                null,
                {data:'speed'},
                {data:'SellerSKU'},
                {data:'shipDateFormat'},
                null,
                null,
            ],

        });


This is the function that I am having problems with. It works once per, and all most console logs fire every time I use it.
Please note that I am using rows() because row() would simply crash whenever I passed the data to it. And I was copying the data from the row, updating it, and copying it back, just as I am doing now. I tried both an object and an array[0] thinking it needed it in an array.

function initWeightChange(n)
{
    $j('[name="'+n+'"]').each(function()
    {
        $j(this).click(function(){return false;})
        .change(function()
        {
console.log('changing');
            var table = $j('#allOrdersTable').DataTable();
            var ar = new Array();
            var data = table.row( $j(this).parents('tr') ).data();
console.log(data);
            ar.push( data );
            var oID = $j(this).data('orderid');
            var nWt = 0;
            //check if if lbs are 0, if they are, send ounces only
            //if lb > 0 and oz > 0, inc wt + 2, else send just wt + 1;
            if( $j('#t_lb'+oID).val() == 0 )
            {
                if(  $j('#t_oz'+oID).val() > 15 )
                {
                    var nWt = parseFloat($j('#t_oz'+oID).val());
                    nWt = Math.ceil(nWt/16)
                    $j('#t_oz'+oID).val('0');
                    $j('#t_lb'+oID).val(nWt);
                }
                else
                {
                    var nWt = parseFloat($j('#t_oz'+oID).val());
                    nWt = nWt/16;
                }
            }
            else
            {
                if( $j('#t_oz'+oID).val() == 0 ) nWt = parseFloat($j('#t_lb'+oID).val());
                else
                {
                    var oz = parseFloat($j('#t_oz'+oID).val());
                    oz = Math.ceil(oz/16);
                    var nWt = parseFloat($j('#t_lb'+oID).val()) + oz;
                }
            }
            //send data to getRatesV2 as an array[0]
            ar[0].shipWt = nWt;
            table.rows( $j(this).parents('tr') ).data( ar ).draw();
            if( _uspsRateLocal == 1 )
            {
                buildShippingRates(ar)
            }
            else
            {
                pCFC.setSyncMode();
                pCFC.getRatesV2( ar[0] );   //may need to turn this into an array, similar to _uspsRateLocal
            }   

console.log( table.rows($j(this).parents('tr')).data() );
console.log( 'ar');
console.log( ar );

            var opt = buildShipOptions( ar[0] );

console.log('opt');
console.log(opt);

            $j('#sl_ship'+oID).find('option').remove().end().append(opt);
            //table.row( $j(this).data('row') ).data( d ).draw( false );
            
            return false;
        });
});

}

This question has accepted answers - jump to:

Answers

  • allanallan Posts: 63,692Questions: 1Answers: 10,500 Site admin

    Are you using Editor at all for the editing? I don't actually see where the editing is happening in the above?

    Allan

  • minifiredragonminifiredragon Posts: 82Questions: 16Answers: 2

    No, the editor is not connected. I have my own text boxes, which are initialized after the table loads.

    I change the text value in the box and when the change occurs, jquery does some checks and computations and hands it back to the table to add the updates to the row data. I can modify the row data once and only once per row, so it does work 1 time per row. Afterwards, the data is never updated even though the steps are taken (I can see this via the console.log output) thru the script which continue to work after the data update and draw().

  • allanallan Posts: 63,692Questions: 1Answers: 10,500 Site admin

    I think what is happening is that there the event handlers (click and change) are being attached to the element as static events, so they work until that element is replaced. That would explain why it works once. On the second time is it interacting with a node that doesn't have an event handler assigned to it.

    I would suggest using delegated events rather than static events to prevent that issue.

    Allan

  • minifiredragonminifiredragon Posts: 82Questions: 16Answers: 2

    The element is never replaced unless the draw() function replaces them? The problem I see is when I pass the data() back into the row() is only updated once. I can continue to change the numbers over and over and over again after the 1st time, without leaving the text field and never again is the data chain updated.

    Does the draw() function change the rowID? If so, how would I acquire the new ID so I can reinitialize the special fields I have?

    I have another datatable I made that when a row is added, the buttons do not work, so maybe I am placing my initialize in the wrong place?

  • minifiredragonminifiredragon Posts: 82Questions: 16Answers: 2

    I have sent you the link to a test site.

  • allanallan Posts: 63,692Questions: 1Answers: 10,500 Site admin
    Answer ✓

    I perhaps explained myself poorly. I've put this little example together (no DataTables) to show what is happening: http://live.datatables.net/nubikove/1/edit .

    Note how the click event handler is attached to the button when the page is loaded. When you click the button a new button element is created, replacing the old one, and this new one doesn't have an event handler attached to it, this it appears not to work the second time.

    The issue with the code above appears to be exactly the same. You have:

     $j(this).click(function(){return false;})
            .change(function()
    

    which is being attached to the input elements inside the cells, only once. When the cell's data is replaced, they no longer have an event attached to them.

    As I say, using a delegated event handler is the way to handle this (its also a lot more performant). See the jQuery documentation for how to use event handlers.

    Allan

  • minifiredragonminifiredragon Posts: 82Questions: 16Answers: 2

    Thank you,

    That explains why when I add a new row to a table it never sets the buttons up correctly, as well as with a draw() on a row() some things disconnect.

  • minifiredragonminifiredragon Posts: 82Questions: 16Answers: 2

    I have gotten around to redoing the connector and delagating the operation is not working. Here is the code used:

        $j('#allOrdersTable tbody').on('click', 'tr', function()
            {
                $j(this).find('[name="t_wt"]').each(function()
                {
                    $j(this)
                    .click(function(){ return false;})
                    .change(function()
                    {
    console.log('changing');
                        var table = $j('#allOrdersTable').DataTable();
                        var ar = new Array();
                        var data = table.row( $j(this).parents('tr') ).data();
    console.log(data);
                        ar.push( data );
                        var oID = $j(this).data('orderid');
                        var nWt = 0;
                        //check if if lbs are 0, if they are, send ounces only
                        //if lb > 0 and oz > 0, inc wt + 2, else send just wt + 1;
                        if( $j('#t_lb'+oID).val() == 0 )
                        {
                            if(  $j('#t_oz'+oID).val() > 15 )
                            {
                                var nWt = parseFloat($j('#t_oz'+oID).val());
                                nWt = Math.ceil(nWt/16)
                                $j('#t_oz'+oID).val('0');
                                $j('#t_lb'+oID).val(nWt);
                            }
                            else
                            {
                                var nWt = parseFloat($j('#t_oz'+oID).val());
                                nWt = nWt/16;
                            }
                        }
                        else
                        {
                            if( $j('#t_oz'+oID).val() == 0 ) nWt = parseFloat($j('#t_lb'+oID).val());
                            else
                            {
                                var oz = parseFloat($j('#t_oz'+oID).val());
                                oz = Math.ceil(oz/16);
                                var nWt = parseFloat($j('#t_lb'+oID).val()) + oz;
                            }
                        }
                        //send data to getRatesV2 as an array[0]
                        ar[0].shipWt = nWt;
                        table.rows( $j(this).parents('tr') ).data( ar ).draw();
                        if( _uspsRateLocal == 1 )
                        {
                            buildShippingRates(ar)
                        }
                        else
                        {
                            pCFC.setSyncMode();
                            pCFC.getRatesV2( ar[0] );   //may need to turn this into an array, similar to _uspsRateLocal
                        }   
                    
    console.log( table.rows($j(this).parents('tr')).data() );
    console.log( 'ar');
    console.log( ar );
                    
                        var opt = buildShipOptions( ar[0] );
                    
    console.log('opt');
    console.log(opt);
                    
                        $j('#sl_ship'+oID).find('option').remove().end().append(opt);
                        //table.row( $j(this).data('row') ).data( d ).draw( false );
                        
                        return false;   
                    }); 
                }); 
            });
    
  • minifiredragonminifiredragon Posts: 82Questions: 16Answers: 2
    Answer ✓

    Ok, I have it solved. I was being a bit too hasty in my examination of the data. After a few seconds passed, the data actually updated to the current information.

This discussion has been closed.