Autocomplete with flexdatalist, id input search, init function

Autocomplete with flexdatalist, id input search, init function

Ludoludo75Ludoludo75 Posts: 41Questions: 8Answers: 0
edited November 2018 in Free community support

Hi,

I have a problem with DataTables,
I would like to add an autocomplete with the search box, my first problem is I can't assign an ID to the search input outside of the ".datatable" (I can, but always in the 'initComplete').

My second is when I assign an ID, then I add flexdatalist and refresh the "function" of "flexdatalist", it's fonctional but when I click in the search input my cursor/focus is off, and I must re-click to can type letters but it's always focus off (the search works but not the autocomplete and my letters disapear), the both (DataTables and flexdatalist) don't work correctly together ahaha
Also everytime I click on, my page returns to the top,

Maybe a solution ?

PS : flexdatalist works when I specify the code : <input id="ac-0083" class="flexdatalist">
outside of the datatables

Thanks

` $.extend( $.fn.dataTable.defaults, {

    "dom": '<"top"AfB>rt<"bottom"ip><"clear">',

    "language": {
        "url": "//cdn.datatables.net/plug-ins/1.10.16/i18n/French.json",
        "decimal": ",",
        "thousands": ".",
        "language": {
            alphabetSearch: {
                alphabet: '#ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                infoDisplay: 'Afficher :',
                infoAll: 'Tous'
            }
        }
    },

    "paging": true,
    "pagingType": "full_numbers",

    "ordering": true,

    "searching": true,

    "info": false,

    "pageLength": 25,

    fixedHeader: {
        header: true,
        footer: true
    },

     buttons: [
        {
            text: 'Réinitialiser',
            action: function ( e, dt, node, config ) {
                dt.search( '' ).draw();
            }
        }
    ],

   initComplete: function () { //WORK

        var idTable = this.attr('id'),
            idDataList = $("#" + idTable ).attr('data-id-ac');
            initDataList = $("#" + idTable ).attr('data-init');

        if ( idDataList != 0 && initDataList != 1 )
        {
            $("#" + idTable + "_filter input").attr('id', idDataList ).addClass('flexdatalist');
            $("#" + idTable ).attr('data-init','1');
            initialiseDatalist();
        }

    } */


} );

$('.table-liste').DataTable( {
} );

/* $("#table-liste-0083_filter input").attr('id', 'ac-0083' ).addClass('flexdatalist');
initialiseDatalist(); */ //DOESN'T WORK

$('#table-liste-0083').DataTable( {

    "pageLength": 35,

    "order": [[0, 'asc']],

    rowGroup: {
        dataSrc: 1
    },

    "dom": '<"top"Bf>rt<"bottom"ip><"clear">',

    alphabetSearch: {
        column: 1
    },

    "columnDefs": [
        {
            "type": 'natural',
            "targets": [ 0 ],
            "visible": false, 
            "searchable": false,
            "orderable": false
        },
        {
            "targets": [ 1 ],
            "visible": false, 
            "searchable": true,
            "orderable": false
        },
        {
            "targets": [ 2, 3 ],
            "visible": true, 
            "searchable": true,
            "orderable": false
        },
        {
            "targets": [ 4, 5, 6, 7 ],
            "visible": true, 
            "searchable": false,
            "orderable": false
        }
    ]

} );

function initialiseDatalist(){

var idDataList = $('.flexdatalist').attr('id');
$('.flexdatalist').attr('list', idDataList + '-datalist')

$('.flexdatalist').flexdatalist({
    minLength: 2,
    searchByWord: true,
    searchContain: false,
    maxShownResults: 5,
    noResultsText: 'Aucun résultat pour "{keyword}"',
    normalizeString: function (string) {
        return latinize(string);
    }
});

}

initialiseDatalist();`

<table id="table-liste-0083" data-id-ac="ac-0083" class="display" width="100%">

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 20,144Questions: 26Answers: 4,736

    Thats a lot of code to look through. Maybe you can provide a test case example so we can take a look at how flexdatalist interacts with Datatables.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Kevin

  • Ludoludo75Ludoludo75 Posts: 41Questions: 8Answers: 0
    edited November 2018

    Thank you,

    So : http://live.datatables.net/tugocibo/1/edit?html,output

    But i can't add
    https://github.com/sergiodlopes/jquery-flexdatalist
    and https://github.com/dundalek/latinize

    with scripts and css because i don't have any direct links to .js and .css

    EDIT : I think flexdatalist doesn't output "value" in the input, really weird, it's like value doesn't exist (because I tested with flexdatalist and outside datatable to catch "value" but it's doesn't display)

  • Ludoludo75Ludoludo75 Posts: 41Questions: 8Answers: 0
    edited November 2018

    **EDIT : **

    I could add script : http://live.datatables.net/tugocibo/2/

    So, you can see the problem (it's like datatable works but on the bottom or on the top of flexdatalist)

  • kthorngrenkthorngren Posts: 20,144Questions: 26Answers: 4,736
    Answer ✓

    I created a quick example. Copied the flexdatalist JS and CSS code. I would recommend not using the built-in search input but create your own. Here is my example:
    http://live.datatables.net/wocitepu/1/edit

    Note that I had to place the $('input.global_filter').on( 'keyup', function () { event code after the $('.flexdatalist').flexdatalist({ init code. If it came first the event wouldn't fire.

    Hope this gets you started. Looks like an interesting library.

    Kevin

  • Ludoludo75Ludoludo75 Posts: 41Questions: 8Answers: 0

    Ohh okay,

    I check that, thank you, I've tried but I think I placed the code first aahah

  • Ludoludo75Ludoludo75 Posts: 41Questions: 8Answers: 0

    Thanks, it's functionally

    I just changed "keyup" to "change"
    Because, when you click on the suggest, with keyup the search doesn't catch the words

    Thank you :D

  • ecooney007ecooney007 Posts: 1Questions: 0Answers: 0

    I don't know if anyone ran into this problem;

    I have a datatable I want to load with data from an ajax call to the server. For One of the column values in the rows of data, I want to allow the user to select a value using Flexdatalist, and I also want to pre-select the value from the flexdatalist when the Datatable is created. But the pre-select did not work no matter how I structured the ajax call inside the datatable. Keep in mind the ajax call works fine and is successfully made, but because of the timing of the operations 1) Create Datatable, 2) Create Flexdatalist, 3) Make ajax async call), the Flexdatalist will not pre-select the value.

    What I mean is that, for the ITEM column I want to show the Description from the Flexdatalist source file which is retrieved by the ITEM_ID, I don't want to display ITEM_ID - Flexdatalist allows you to pre-select and show the description or any value for that ITEM you want as long as its in the source file it pulls from. But whenever I create the datatable via the recommended ajax convention, it never pre-selects the Description, and only ever shows the ITEM_ID.

    1) I tried using an ajax call built-in to the Datatable creation with dataSrc, and this does load the data in the datatable, but this did not work for flexdatalist pre-select;

    "ajax": {
                    type: "GET",
                    "url": `${window.origin}/get_order_by_id/${OrderId}`,
                    "dataSrc": function (json) {
                         // this is the returned data from the call
                         console.log(`data: ${JSON.stringify(json.data)}`)
                         return json.data;
                    }
         },
    

    2) I tried again using an ajax call inside a function, which then uses a callback to return the data to load it in the datatable, and while the data does load properly in the datatable, it still does not pre-select the flexdatalist value;

     "ajax": function (data, callback, settings) {
                         $.ajax({
                             type: "GET",
                             url: `${window.origin}/get_order_by_id/${OrderId}`,
    
                         }).then(function (json) {
                             console.log(`json: ${JSON.stringify(json)}`);
                             console.log(`data: ${JSON.stringify(json.data)}`);
    
                             callback({ "data": json.data });
                        }).fail(function (xhr) {
                             console.log('error:' + xhr.statusText);
                         });
                     },
    
                 },
    

    It seems like Flexdatalist needs the data to already be rendered in the Datatable to work for pre-select, so when I wrapped both Datatable and Flexdatalist object creation inside an ajax call only when its a successful ajax call, and then inject the data returned directly into the Datatable, this is only way I was able to get the column to pre-select the Flexdatalist value properly;

    3) WORKAROUND - Datatable and Flexdatalist wrapped in an ajax call, then inject the data into the Datatable;

    $.ajax({
            url: `${window.origin}/get_order_by_id/${OrderId}`,
            method: 'GET',
            dataType: 'json',
            success: function (results) {
    
                console.log(`results: ${results}`);
                data = JSON.stringify(results.data);
    
       // Get the data from the ajax results response, this will be the data we inject to the Datatable
    
                data = results.data;
                console.log(`data: ${data}`);
                console.log(`data: ${JSON.stringify(data)}`);
             
                $('#msItems').DataTable({
                    "data": data,
    
                    // WORKS - Directly hardcoding/injecting in the "data" to the Datatable this way (below), works fine, will trigger flexdatalist code CORRECTLY and creat ethe flexdatalist object
    
                    // "data": [{
                    //     "asset_no": "BA-010",
                    //     "comment": "Wires were rusted through, had to replace copper leads and wires, and strip them down.",
                    //     "item_id": 1, "model_no": "jkl-4739729",
                    //     "serial_no": "109-840293000-001",
                    //     "order_id": 1,
                    //     "order_item_id": 1,
                    //     "order_item_subitems": [{ "item_id": 200, "quantity": "2.00", "unit_of_measure": null, "order_item_id": 1, "order_item_subitem_id": 1 }]
                    // }],
    
    // DOES NOT WORK - Rendering Data this way (below) with ajax and a callback for the data, will NOT trigger flexdatalist code CORRECTLY and create the flexdatalist object
    
                    // "ajax": function (data, callback, settings) {
                    //     $.ajax({
                    //         type: "GET",
                    //         url: `${window.origin}/get_wo_by_id/${OrderId}`,
    
                    //     }).then(function (json) {
                    //         console.log(`json: ${JSON.stringify(json)}`);
                    //         console.log(`data: ${JSON.stringify(json.data)}`);
    
                    //         callback({ "data": json.data });
                    //     }).fail(function (xhr) {
                    //         console.log('error:' + xhr.statusText);
                    //     });
                    // },
    
                    // },
    
    // DOES NOT WORK - Rendering Data this way (below) with ajax and a dataSrc function for the json data returned, will NOT trigger flexdatalist code CORRECTLY and create the flexdatalist object
    
                    // "ajax": {
                    //     type: "GET",
                    //     "url": `${window.origin}/get_wo_by_id/${workOrderId}`,
                    //     "dataSrc": function (json) {
                    //         // this is the returned data from the call
                    //         console.log(`data: ${JSON.stringify(json.data)}`)
                    //         return json.data;
                    //     }
                    // },
    
                    paging: false,
                    columns: [{
                        className: 'term-details-control',
                        orderable: false,
                        data: null,
                        defaultContent: `<img src="http://i.imgur.com/SD7Dz.png">`
                    }, {
                        data: null
                    }, {
                        data: "item_id"
                    }, {
                        data: "model_no"
                    }, {
                        data: "serial_no"
                    }, {
                        data: "asset_no"
                    }, {
                        data: "comment"
                    }
                    ],
                    "columnDefs": [
    
                        {
                            "targets": 2,
                            "data": 'item_id',
                            "render": function (data, type, row, meta) {
                                
                                /**
                                 * To pre-select the an <option... in the datalist (list=items_list)
                                 * set the flexdatalist 'value' attribute to the incoming 'data' parameter;
                                 *
                                 * value='${data}'
                                 *
                                 * The data is not the row, but the actual piece of data, the row
                                 * actually has all the pieces of data so you can perform functions on them
                                 * if needed.
                                 *
                                 * Also, the data type of the 'value' attribute must be the same as that in the json file.
                                 * If its a string in the json file, then it must be a string for the 'value' attribute;
                                 * html field=value=... "${data}" ...
                                 * json file=[{"item_id": "1", ...
                                 *
                                 *
                                 * This code assumes the the incoming options have 'value' as an attribute like so;
                                 *
                                 * <option value="1" lable="#20 DC SHUNT - #20DCSHUNT">#20 DC SHUNT - #20DCSHUNT</option>
                                 *
                                 * Here were are using value as the 'id' in the datasource for this item.
                                 */
    
                                return `<input type='text'
                                value=${item_id}
                                placeholder='Find item'
                                class='flexdatalist'
                                data-data='${window.origin}/static/data/items.json'
                                data-search-in='part_no'
                                data-visible-properties='["item_id","part_no","description"]'
                                data-selection-required='true'
                                data-value-property='item_id'
                                data-text-property='{item_id}, {description}, {part_no}'
                                data-min-length='1'
                                name='item_id_suggestion'>`;
                            }
                        }],
                    order: [
                        [2, 'asc']
                    ]
                });
    
                $('.flexdatalist').flexdatalist({
                    minLength: 1,
                    textProperty: '{item_id}, {description}, {part_no}',
                    valueProperty: 'item_id',
                    searchIn: 'part_no',
                    selectionRequired: true,
                    visibleProperties: ["item_id", "part_no", "description"],
                    data: `${window.origin}/static/data/items.json`
                });
    
            }
        }); 
    

    If anyone found a way to use Flexdatalist pre-select by making an ajax call inside the Datatable, I'd be interested in how you did that, could you please post?

  • kthorngrenkthorngren Posts: 20,144Questions: 26Answers: 4,736

    @ecooney007 You are correct the problem of initializing Flexdatalist in each row is due to the async nature of Ajax. I think you will find that using data: data is not a complete solution as the init code will only run against the page being shown. That is the only page in the DOM.

    Placing the Flexdatalist init code in either drawCallback or draw (essentially the same thing) will cause the init code to be applied to the inputs on the current page after it is drawn.

    You have data-data='${window.origin}/static/data/items.json' in the rendered input. If you monitor the Developer Tools > Network tool I think you will find the JSON file is fetched quite often. Probably more than you want. I would consider performing an Ajax request for the JSON file before initializing Datatables and assigning the JSON string to a global variable. Then use that global variable to assign data-data=(JSON) and the data (JS Object) option in the Flexdatalist init code.

    Hope this gets you going.

    Kevin

This discussion has been closed.