Disappearing table row. Inline Editor

Disappearing table row. Inline Editor

chrisg123chrisg123 Posts: 9Questions: 4Answers: 0

File: Editor-PHP-1.5.1\js\dataTables.editor.js

Line: 5855:34

Problem: return rowId === idFn( rowData );

Possible Fix: return rowId == idFn( rowData );

Explanation:

The use of === will not match when idFn() returns a string representation of a number. This causes the following to miss getting called:

Line 5859
            if ( row.any() ) {
                row.data( data );
                __dtHighlight( row.node() );

                // Remove the item from the list of indexes now that is has been
                // updated
                var idx = $.inArray( rowId, store.rowIds );
                store.rowIds.splice( idx, 1 );
            }

Resulting in the removal of the row when commit is called

Line 5895

        // On edit, if there are any rows left in the `store.rowIds`, then they
        // were not returned by the server and should be removed (they might not
        // meet filtering requirements any more for example)
        if ( action === 'edit' && store.rowIds.length ) {
            var ids = store.rowIds;
            var idFn = DataTable.ext.oApi._fnGetObjectDataFn( this.s.idSrc );
            var row;

            for ( var i=0, ien=ids.length ; i<ien ; i++ ) {
                // Find the row to edit - attempt to do an id look up first for speed
                row = dt.row( '#'+ids[i] );

                // If not found, then we need to do it the slow way
                if ( ! row.any() ) {
                    row = dt.row( function ( rowIdx, rowData, rowNode ) {
                        return ids[i] === idFn( rowData );
                    } );
                }

                if ( row.any() ) {
                    row.remove();
                }
            }
        }

Replies

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    Hi - thanks for posting this. Are you using numbers as the id's? Are they being read from the DOM? I'm just wondering why there is the need for a weak comparison rather than strong one (or perhaps more specifically, why one representation is a string and another is a number).

    Regards,
    Allan

  • chrisg123chrisg123 Posts: 9Questions: 4Answers: 0
    edited October 2015

    Yes I am using numbers as id's. and no they are not being read from the DOM. (I don't really want database Id info in the DOM)

    I am using the Symfony Framework with Doctrine ORM on the server side with a custom DQL query (doctrine query language) to grab a bunch of rows.

    It seems to return all values as strings. I could of course solve that issue on the server side (which I've added to my TODO's) but I can't think of a case where the desired behavior of a comparison such as 5996 compared to the string "5996" would be to return false.

    If a strict comparison is really necessary then maybe a warning or notice? It took me all day to figure out why my rows were disappearing.

    Some of my server side code for better understanding:

    /*
    * Method to grab rows using Doctrine query language (DQL) 
    * Return value is converted using json_encode method before returning to client
    */
    public function findByAccountId($id,$order=0,$pastLimit=12)
        {
            $chronology = $order==0 ? "ASC":"DESC";
            //This is 10x faster than hydrating and serializing with JMSserializer
             //TODO: Integers are returned as strings - 17/10/2015                                                   
            $query = $this->getEntityManager()->createQuery(
                "SELECT t.id, t.amount as amount,
                 SUBSTRING(t.date,1,10) as date,
                 t.description,
                 c.name as category FROM AppBundle\Entity\Transaction\Transaction t
                 left JOIN t.category c WHERE t.account =$id
                 AND t.date >= DATE_SUB(CURRENT_DATE(),".$pastLimit.",'MONTH')
                 ORDER BY t.date ".$chronology
            );
    
            $transactions = $query->getScalarResult();
            return $transactions;
        }
    
    

    Results in the following returned to client:

    [{"id":"5307","amount":"3000","date":"2015-10-17","description":"","category":""},{"id":"5294","amount":"40000","date":"2015-01-20","description":"Something","category":"somecat"}]
    
  • tangerinetangerine Posts: 3,342Questions: 35Answers: 394

    I use MySQL rather than DQL, but MySQL also returns integers as strings.

    Is there anything you could do along the lines of (pseudo-code):

    transactions->id = (int) transactions->id ?

    i.e. before returning the result of your query ?

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    I default to strict comparisons in most of my code as I find it can save more bugs that it will trigger. It is unlikely that 5996 and "5996" would want to fail in the comparison, but I'd prefer to err on the side of caution since there would be no way to undo that change if I made it.

    Let me think about it a bit more, but my initial inclination is to keep the strict comparison.

    Allan

  • accminfotechaccminfotech Posts: 3Questions: 1Answers: 0

    Any idea how to resolve this? im also having the same issue with disappearing row after the table is updated successfully with inline editing

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    The way to resolve this is too ensure that the same data structure is used when the table is loaded and when the data is updated. The issue is because the value as a string and an integer don't match, which I think is the correct thing to do - the data structure should be modified so both use the same.

    Allan

  • accminfotechaccminfotech Posts: 3Questions: 1Answers: 0

    Thanks heaps Allan. That really helped understand. My issue was my datatable ajax for fetching the table was different to the post ajax that editor was using. I didnt realise you needed to have every field in the editor php data. I only had the single field i wanted to edit

This discussion has been closed.