Setting the search information for 1.10

Setting the search information for 1.10

mmillermmiller Posts: 13Questions: 2Answers: 0

I am using a 'createdRow': function populate my table dynamically. My <tbody> is empty on start.
I have complicated rows that have select-dropdowns and checkboxes that need setting up and data-* values attached. I can successfully render the rows. Here is an simplified example of what my createdRow function looks like:

        var TableRow    = function(row,data,index) {
            var td = $(row).find('td');
            $(td[0]).html('<a style="cursor:pointer" onclick="return openTab(\''+data[0].Id+',\''+Member Tab+'\')">'+data[0].Id+'</a>').addClass('text-center');
            $(td[1]).html(data[0].LastName);
            $(td[2]).html(data[0].FirstName); 
                            }

I have to add the data array to every column position for the table: (table instance is called memberListTable and is generated with capital 'D' constructor)

    for(var i = 0; i < MemberList.length; i++) {
    memberListTable.row.add([MemberList[i],MemberList[i],MemberList[i]]);
    }
        memberListTable.draw();

If I try to use a single Object instead of an array, I get a warning about technical note #4.

The table renders properly, but If I try to filter or search I always get zero rows returned:
memberListTable.search('any valid string in the table').draw(); always returns an empty results set
I tried injecting html 5 'data-search' into the td cells in the callback function, but I think it is probably too late in the process for the search feature to find it.
How can I set/update search / filter information with a complicated, dynamically generated data?

If I have to render rows differently or run functions on the data, I don't mind, I just need a way for the search to work and be able to dynamically generated complicated HTML rows.

Thanks.

This question has an accepted answers - jump to answer

Answers

  • mrd05dmrd05d Posts: 45Questions: 6Answers: 3

    I am having trouble following what you are explaining. Can you link to your example?

    You will be much more likely to get help. If you cant link to your example what about creating a http://live.datatables.net/ version?

    And if that is not possibly you will likely have to try to explain more clearly what it is you are trying to accomplish.

  • mmillermmiller Posts: 13Questions: 2Answers: 0

    I really can't link because it is part of a bunch of other code which would be even more confusing. I wrote that at the end of a long day. Allow me to try again :)

    I have multiple tables on a page, but will show only one instance here to illustrate the problem. The other tables have different data sources but are initialized and create complex HTML rows like the example I will show. This is a simplified reconstruction of the actual code, so If there are case-sensitivity issues with variable or function names or quotes don't match up in the example that is definitely not the problem.

    Here is the initialization of the table:

                if (!$.fn.DataTable.isDataTable('#aTable')) {
                    var aTable = $('#aTable').DataTable({
                        'autoWidth': true,
                        'lengthMenu': [[25, 50, 75, 100, -1], [25, 50, 75, 100, 'All']],
                        'createdRow':  aTableRow,
                        'oLanguage': {
                            'sSearch': '',
                        },
                        'columns': [
                            {'width':'75px','sortable':true},
                            {'width':'165px'},
                            {'width':'165px'}
                            ],
                        'dom': '<l><t><i><p>'
                    });
                }
    

    here is a simplied version of the HTML (without classes applied to the elements)

    <table>
    <thead>
    <tr><th>Open Tab</th><th>First Name</th><th>Last Name</th></tr>
    </thead>
    <tbody> <!-- note: empty tbody on initial page render -->
    </tbody>
    </table>
    

    The createdRow function, aTableRow, is defined as:

                var aTableRow   = function(row,data,index) {
                    var td = $(row).find('td');
                    $(td[0]).html('<a style="cursor:pointer" onclick="return openTab('+data[0].Id+')">'+data[0].Id+'</a>');
                    $(td[1]).html(data[0].FirstName);
                    $(td[2]).html(data[0].LastName);
                    }
    

    In the real function, I have some select dropdowns and checkbox inputs and have about ten columns, but to illustrate the issue, this should be enough.

    So to populate the empty table. I have an array of objects which has N items. Let's call it MemberList.

    MemberList[0] = {Id:1,FirstName:'Bob',LastName:'Smith'};
    MemberList[1] = {Id:2,FirstName:'John',LastName:'Doe'};
    .... for up to N items.
    

    Now to populate the table I do the following:

    for(var i = 0; i < MemberList.length; i++) {
        aTable.row.add([MemberList[i],MemberList[i],MemberList[i]]);
    }
    aTable.draw();
    

    Here is what the manual says about row.add()

    http://datatables.net/reference/api/row.add():
    
    function row.add( data )
    Description:
    Add a new row to the table using the given data
    Parameters:
    Name    Type    Optional
    1   data    
    arrayJS, objectJS
    No
    Data to use for the new row. This may be an array, object or Javascript object instance, but must be in the same format as the other data in the table (i.e. if your table uses objects, pass in an object here!).
    Returns:
    DataTables.ApiDT
    DataTables API instance with the newly added row in its result set.
    

    If I try to add an object, it gives be technical note 4 (tn4) warning. So I have to add the object in the array for each column. I think because it is an object and not a simple value, it doesn't know how to read the object to get the searchable/sortable data.

    I think by the time it gets to the createdRow function, the data is supposed to already ingested for processing purposes. I need to create HTML data-* elements in the createdRow function,so the object passed for each row has meta-data that will not be displayed in the table, but needs to be part of the tr and some td tags as data-* parameters and needs to be in the createdRow call.

    if I do:

    aTable.search('any valid string in the table').draw() it returns 0 of 0 filtered of N. 
    
    This returns every row:  aTable.search('').draw();
    

    Some how I need to tell DataTables what data that is searchable/sortable on a row by row basis. This is where I am failing.

  • mrd05dmrd05d Posts: 45Questions: 6Answers: 3

    So without a live example its going to be difficult for me to help with this one.

    If you use http://live.datatables.net/ and create something similar to what you are doing that will generate the same issues that would make it that much easier to understand what the issue may be.

  • mrd05dmrd05d Posts: 45Questions: 6Answers: 3

    I have recreated what you have given me in the smaller example and it seems to work just fine.

    http://live.datatables.net/xidifati/1/edit?html,css,js,console,output

  • mmillermmiller Posts: 13Questions: 2Answers: 0

    I appreciate your input mrd05d.

    From your live.datatables.net example, you are inserting rows into aTable using:

    atable.row.add([MemberList[i]['Id'],MemberList[i]['FirstName'],MemberList[i]['LastName']]);
    

    I am not putting in the field name.

    aTable.row.add([MemberList[i],MemberList[i],MemberList[i]]);
    

    That is not the issue, I need additional data available for searching/sorting/filtering that isn't data displayed in its own column.

    Let's expand the original MemberList object array and add a field called NewMember which has a value of true/false. Now let's put a star after each new member's Last name if they are a new member (whatever criteria that is: less than year, a month, etc. True in that field means they meet the criteria of the new member, false means they don't).

    This would render the LastName column correctly with the star placed appropriately:

    $(td[2]).html(data[0].LastName+(data[0].NewMember ? '<img src="/path/to/star.jpg" />' : ''));
    

    With your row.add approach, the NewMember field wouldn't be sent at all. The way I send the whole object, that value is available. For visual reasons, I can't have the star in its own column.

    Say I want to create filter/search that only shows new members, a checkbox at the top of table that toggles that filter: show new members only. How can I tell Datatables which row is the new member for searching/sorting/filtering? There could be additional fields in the object represented visually by icons, for example: PremiumMember: true/false, DuesPaid: true/false.

    A member could have three icons after their last name: new member who is a premium member who still needs to pay their dues. So in the last name column, there are four pieces of information to search/sort/filter: The last name (search/sort), new member (filter/sort), premium member (filter/sort) and dues paid (filter/sort).

    When I send the full object in the row.add, internally I am guessing it is seeing [object] [object] as the data and obviously can't search that. I am looking for a way to tell Datatables on a given row (and sometimes column) this is the data you need to search/sort/filter.

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Answer ✓

    DataTables' built in search will only apply to data that is in a column (it can be in a hidden column - but it needs to be in a column).

    If you want to search on non-column data, you would need to use a custom search plug-in.

    Allan

  • mmillermmiller Posts: 13Questions: 2Answers: 0

    Thanks for your answer Allan. Can the custom search plugin be applied to specific tables?
    In other words, if I have multiple tables on the page, can I have custom search plug-ins apply to specific tables? It appears adding the plugin(s) is global to the Datatables object, and if it does, can I get the table instance from the plugin to use some logic in the plugin?

    The custom search plugin is initialize by: $.fn.dataTable.ext.search, do I need to make that $.fn.DataTable.ext.search if I am using DataTables (1.10+)?

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin

    Can the custom search plugin be applied to specific tables?

    Sort of. It is executed for every table, but you can easily check if it is the table you want to operate on using the table's ID which you can get using settings.nTable.id (where settings is the first parameter passed into the function).

    It is a little awkward! But is should work. v1.11 is going to see an improvement there...

    Allan

  • mmillermmiller Posts: 13Questions: 2Answers: 0

    Thanks again. So in the definition of search plugin:
    $.fn.dataTable.ext.search.push( function( settings, searchData, index, rowData, counter ) ....
    Would the rowData be that entire object I sent in my example above (shown below)?

    aTable.row.add([MemberList[i],MemberList[i],MemberList[i]]);

    Also, how do I selectively choose the filter I want? Say I have four filters on the table, I want to activate specific ones via checkboxes. Do I use jquery to check the value of the checkbox and have one filter that uses the checkbox states or can I selectively use filters.

    It appears you are pushing them into an array and they are checked in some insert order.

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin

    Would the rowData be that entire object I sent in my example above (shown below)?

    Yes, as the documentation says:

    4) The original data source for the row. This will be the array or object that was given to DataTables as the data source for the row.

    Also, how do I selectively choose the filter I want? Say I have four filters on the table, I want to activate specific ones via checkboxes. Do I use jquery to check the value of the checkbox and have one filter that uses the checkbox states or can I selectively use filters.

    Yes - you are in control of the filter, so it is up to you if it is applied or not. A check on a variable or element would do it.

    Allan

  • mmillermmiller Posts: 13Questions: 2Answers: 0

    Allan and mrd05d thank you for your responses. By creating hidden columns I was able to use the best of both worlds. For example, I want the first and last name searchable/orderable plus the entire row data object for manipulating the html of the table.

    I make column 0 hidden and not searchable/orderable and pass the row data object in the row.add() in column 0. Columns 1 and 2 would have the simple text for first name and last name.

    The search/filter/order engine can get plain text for searching/sorting on the first/last name and I can get the full data object in data[0] for the createRow function. The filters and searching work awesomely doing that.

    Now another similar question. Let's say I want to have a status column that has a link that lets you change its value. You click on the link and a popup comes up to let you change the data. How can I update the search/order data in the cell and also update the HTML?

    Allow me to explain this with an example. Expanding on the Memberlist example in this thread. Each member can have a membership status of bronze, silver or gold. Let's say we want to be able to change the status column in any given row.

    I click on the cell that says bronze as the status (the cell has a html link). Now I am presented with a popup that let's me change it to silver or gold. I change the status to gold. Now I want to replace the cell data with a gold link and also if I search/filter/order on gold, I want it to show up as gold, not the original bronze.

    I need to do two things: update the search/filter/order data from bronze to gold and I want to have the link now say gold and can handle additional changes. This would be done by manipulating the HTML for the cell.

    Is there a direct way to get the cell coordinates from the table (row, column) and update the data for searching/ordering and also update the HTML for the cell? A refresh of the table will show the changed status/html, but I would prefer not having to refresh the table every time I change the status of a member.

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin

    Hi,

    Sorry for the massive delay in replying to this - I completely lost track of the thread. You've probably moved on from this now, but:

    Is there a direct way to get the cell coordinates from the table (row, column) and update the data for searching/ordering and also update the HTML for the cell?

    cell().data() will let you get and set the data for a single cell. The data that is set will be used for the HTML output as well as search and ordering in the table. Orthogonal data can be used if you want to have different forms of the data used for each of these operations.

    Allan

This discussion has been closed.