When searchpanes are opened by button, there seems to be a rendering issue

When searchpanes are opened by button, there seems to be a rendering issue

BjornHaBjornHa Posts: 54Questions: 8Answers: 0
edited May 17 in SearchPanes

If no value has been selected in any of the available panes, it seems like rendering of the columns in the panes are not completed.
I have attached two images showing the difference between when a selection is made and when it is not.

The rendering of the column in the actual table is done using a processing trigger at the end:

            $('#resultTable').on('processing.dt', function (e, settings, data) {
                setTimeout(function(){
                    $(".rating").rating({theme:'krajee-svg', min:0, max:5, step:.5, displayOnly:!0, showCaption:!1, showClear:!1, showCaptionAsTitle:!1, size:'sm'});
                    $('#resultTable').DataTable().columns.adjust().draw();
                }, 500);
            } );

Without select

With select

The actual column is as displayed rendered in both cases.

KR,
Björn Hasselberg

This question has accepted answers - jump to:

Answers

  • kthorngrenkthorngren Posts: 22,015Questions: 26Answers: 5,081

    I think you will want to use columns.render to render the HTML. See this example.

    Use orthogonal data to render the HTMLl for the display operation like this example. I combined the two examples to show how this works with searchPanes:
    https://live.datatables.net/neluwoqa/1/edit

    If you still have difficulties then please update my example with your code for the star input so we can help debug. Or provide a link to a running test case showing the issue.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Kevin

  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0
    edited May 19

    Thanks a lot for the input here. My question though was why the SearchPane is rendered when a value is selected in any of the SearchPanes, but not when no value is selected.
    For me this is an inconsistent behaviour and internal to SearchPanes.
    So, if I understand your answer correctly, using the "render:" function on column level for the rating would solve the issue. This is for me a workaround for the behaviour, but not an answer.
    I could try the column render function, if you could point me how to use a jQuery version of the field in the rendering function on column level, as the rating function is only working if that is the case, i.e. "jQuery object identified by id or class".rating().
    I tried to use the HTML 5 usage as described here in 2b: https://plugins.krajee.com/star-rating#usage
    but no success, the rendering does not take place.

    Code in use when using processing trigger:

                        {
                            "data": null,
                            "render": function (data, type, row) {
                                return '<input id="rating' + data.ID + data.applicationID + '" name="rating' + data.ID + data.applicationID + '" class="myrating" type="text" value="' + data.rating + '" /><div style="display:none">' + data.rating + '</div>'
                            }
                        },
    
                $('#searchAppTable').on('processing.dt', function (e, settings, data) {
                    setTimeout(function(){
                        $(".myrating").rating({theme:'krajee-svg', min:0, max:5, step:.5, displayOnly:!0, showCaption:!1, showClear:!1, showCaptionAsTitle:!1, size:'sm'});
                        $('#searchAppTable').DataTable().columns.adjust().draw();
                    }, 500);
                } );
    
    

    Code when truing HTML 5 without trigger:

                        {
                            "data": null,
                            "render": function (data, type, row) {
                                return '<input id="rating' + data.ID + data.applicationID + '" name="rating' + data.ID + data.applicationID + '" class="rating" data-min="0" data-max="5" data-step="0.5" data-theme="krajee-svg" data-readonly="true" data-size="sm" type="text" value="' + data.rating + '" /><div style="display:none">' + data.rating + '</div>'
                            }
                        },
    
  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0
    edited May 19

    Maybe I should make it clearer that this is not an issue when panes are initated through "dom:", only when triggered by "buttons: extend:".

  • kthorngrenkthorngren Posts: 22,015Questions: 26Answers: 5,081
    edited May 19

    Since you haven't provided a test case to show the issue let me try to understand the issue more clearly.

    Are you trying to use the processing event to update the star rating display of the inputs in the searchPanes?

    Is the searchPanes display is only updated when you click on a searchPane row to execute a search? Not sure whether you are clicking the input in the main table or searchPane to affect this.

    If this is the case then the processing event won't fire when clicking the searchPanes button because it is applied only to the main table, ie, #resultTable. Clicking the button doesn't execute a search to invoke the processing. Possibly you can use the buttons-action to apply the rating to the panes when they are open. Something like this:

      table.on('buttons-action', function (e, buttonApi, dataTable, node, config) {
        if( buttonApi.text() === 'SearchPanes' ) {
          $(".rating").rating({theme:'krajee-svg', min:0, max:5, step:.5, displayOnly:!0, showCaption:!1, showClear:!1, showCaptionAsTitle:!1, size:'sm'});
            $('#resultTable').DataTable().columns.adjust().draw();
        }, 500);
    } );
        }
      });
    

    If this isn't the issue or you still need help then please provide a test case replicating the issue so we can get a better understanding of your solution.

    Kevin

  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0

    HI,

    I'll provide you with a login to site and URL in PM.

    Bjørn

  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0

    The "button action" idea provided by kthorngren works and is now implemented an solves my immediate problem when no value in pane is applied.

    However I disagree that this is a answer to my original question.
    The panes are rendered differently if you open them
    1. with a slected value in use
    2. without a selected value in use
    This is inconsistent behavior.

    The "button action" is only needed when the panes are opened without selection.
    With a selection it is redundant, not needed.

    Bjørn

  • kthorngrenkthorngren Posts: 22,015Questions: 26Answers: 5,081
    edited May 19

    Maybe this simple example will help explain:
    https://live.datatables.net/gonegehe/1/edit

    The processing event is applied to the main Datatable only. This is from the docs:

    This event is fired when DataTables is doing some kind of processing - be it, sorting, filtering or any other kind of data processing.

    The processing event code you have executes $(".rating").rating( .. ); which applies the rating formatting to both the main table and any open SearchPanes (SP).

    When the SP are opened via the button and there are no selected rows then SP does not execute a search. This means the processing event does not fire and the rating formatting is not applied. Thus the need for the buttons-action event to format the ratings when the button opens SP.

    When selecting something to search the processing event is fired which then formats the ratings in both the table and the SP tables.

    When the SP is closed with search term(s) selected then reopened SP executes the searches causing the processing event to fire.

    Open the console and try the above steps to see when the processing event fires.

    The above is expected behavior.

    Does this help?

    Kevin

  • kthorngrenkthorngren Posts: 22,015Questions: 26Answers: 5,081

    Looking at the test case a bit closer the if statement in the buttons-action will only execute the rating formatting code if the button's text is SearchPanes. If there is a SP search term then the button's text will be something like SearchPanes (1) and won't match the if statement. So the formatting code will then run from the processing event. It doesn't look like there is a case where it will run the formatting code twice.

    Kevin

  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0

    OK, accepting that premise, why does it work in "dom" and "layout"cases without a selected value?

    I am not questining the facts that your code works, it does.
    But I had to change the if statement as we do not use default texts.
    Also, depending on hardcoded text in comparisons is maybe a bit "uncertain", there are parameters here that needs to be inline, as well as multiple languages being used simoultanesly.
    For instance the "(1)" is there due to default configuration of texts.

    However, the rendering is the same for
    dom, any case
    layout, any case
    button, only if filter is selected

    This is my final post on the subject, I promise :)

    Bjørn H

  • kthorngrenkthorngren Posts: 22,015Questions: 26Answers: 5,081

    OK, accepting that premise, why does it work in "dom" and "layout"cases without a selected value?

    As you can see in the example the processing event runs when the Datatable is initialized. The dom or layout initialization of SearchPanes places the panes in the document at initialization. The .rating nodes in the searchPanes can be found when the processing runs at initialization.

    Also, depending on hardcoded text in comparisons is maybe a bit "uncertain", there are parameters here that needs to be inline, as well as multiple languages being used simoultanesly.

    Each solution has different requirements. The examples I provided are simply to provide a visual of what is happening with the goal that you can refactor the code for your specific requirements.

    You can use, for example, a variable instead of a hard coded string. If you are setting buttons.buttons.text via a parameter you might be able to use that same parameter for the if statement. Other options might be to set buttons.buttons.className and use button().node() to check the class name in the if statement. Or use button().index().

    Instead of using buttons-action you could create your own event handler specific to that button. This would eliminate any need to know the button's text to determine which Datatables button was clicked.

    Lots of options based on your specific requirements :smile:

    Kevin

  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0

    And there I was, happy with a workaround, but only until it was put in production... and did not work.
    So I am afraid there will be one more comment from me.

    I have now gone through a number of events setups to trigger the table draw on the table with the data according to your suggestions above. Same result for all of them.
    It will work in our test environment where we return ~100 rows but only the first time and the SearchPanes needs to be triggered with the button within a short timeframe (<3-5 seconds) from the underlying datatable rendering has ended.

    In our production environment where 5000 - 10000 rows are returned it does not work at all. The redraw of the table is not caught by the SearhPanes display at any time.

    I have also tried to use the searchPanes.rebuildPane() instead of redrawing the actual table, but to no avail.

    Kind regards,
    Bjørn H

  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0

    Kevin, my appologies on your account setup, it should be in order now if you want to try again.

    Bjørn h

  • kthorngrenkthorngren Posts: 22,015Questions: 26Answers: 5,081
    Answer ✓

    Sounds like the setTimeout timer is too short for the SearchPanes to be drawn. Maybe using the processing event isn't a good solution.

    Maybe another option is to use the new on option, introduced in Datatables 2.3.0, in the SearchPanes. Use the columns.searchPanes.dtOpts to define the on for specific column(s). I would first try the draw event. See this example:
    https://live.datatables.net/gibemege/1/edit

    Replace $('td span', table).addClass('green'); with:

    $(".rating", table).rating({theme:'krajee-svg', min:0, max:5, step:.5, displayOnly:!0, showCaption:!1, showClear:!1, showCaptionAsTitle:!1, size:'sm'});
    

    The example uses table().node() to reduce the $(".rating", table) selector to just the SearchPanes table. This should avoid applying the rating formatting to the main table.

    I would consider changing the processing event to the draw event for the main table. I would also remove the setTimeout and do the same table().node() to get that specific table.

    Kevin

  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0

    Thanks Kevin,

    This works for this, it seems to be working also in production.
    I'll mark it as answered.

    KR,
    Bjørn H

  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0

    Sorry, need to re-open this.
    The solution that I accepted was only valid when there is NO selected value in thwe panes. When a value (any value) is selectet, this is the outcome:

    Every value gets rendered twice...

    So I still think there is an inconsistency here....

    KR,
    Bjørn H

  • allanallan Posts: 64,519Questions: 1Answers: 10,664 Site admin
    Answer ✓

    I think it is going to be really tricky to get an external component rendering correctly in SearchPanes at the moment (as you are seeing :)).

    What you probably need to do is check if it has already been rendered in the cell:

    $(".rating", table).each(function () {
      if (! $('span.star', this).length) {
        $(this).rating({...});
      }
    });
    

    I don't have a running example to work with, so I can't try it, but that might help?

    Are the options in the pane not interactive though? I wonder if it might be a whole lot easier just passing in some custom options (along this sort of line) with the HTML for the stars. I think that would remove a lot of the complexity of the rating library needing to be initialised (at the cost of some extra work I do recognise).

    Allan

  • BjornHaBjornHa Posts: 54Questions: 8Answers: 0
    edited May 21

    Thanks for the input Allan.

    Found a workaround that fills my needs by defining my own search pane and handling rendering for that according to your example, Kevin.

    {
    extend: 'searchPanes',
    className: 'myAppPane btn-secondary',
    config: {
        columns: [3, 8, 10, 13],
        layout: 'columns-5',
        show: true,
        controls: false,
        dtOpts: {
            buttons: {
                buttons: [
                ]
            }
        },
        panes: [{
            header: 'Rating',
            options: [
                {
                    label: '<input type="text" class="rating" Value="0">',
                    value: function(rowData, rowIdx){
                        return rowData['rating'] === '0';
                    }
                },
                {
                    label: '<input type="text" class="rating" Value="1">',
                    value: function(rowData, rowIdx){
                        return rowData['rating'] === '1';
                    }
                },
                {
                    label: '<input type="text" class="rating" Value="2">',
                    value: function(rowData, rowIdx){
                        return rowData['rating'] === '2';
                    }
                },
                {
                    label: '<input type="text" class="rating" Value="3">',
                    value: function(rowData, rowIdx){
                        return rowData['rating'] === '3';
                    }
                },
                {
                    label: '<input type="text" class="rating" Value="4">',
                    value: function(rowData, rowIdx){
                        return rowData['rating'] === '4';
                    }
                },
                {
                    label: '<input type="text" class="rating" Value="5">',
                    value: function(rowData, rowIdx){
                        return rowData['rating'] === '5';
                    }
                }
            ],
            dtOpts: {
                on: {
                    draw: function(e, settings) {
                        // Get the SP table
                        var api = new DataTable.Api( settings );
                        var table = api.table().node();
                    
                        // Apply the class only to the SP table
                        $('.rating', table).rating({theme:'krajee-svg', min:0, max:5, step:1, displayOnly:!0, showCaption:!1, showClear:!1, showCaptionAsTitle:!1, size:'xs'});;
                    }
                }
            }
        }]
    }
    
    

    Marking the thread as answered :)

    Bjørn

  • allanallan Posts: 64,519Questions: 1Answers: 10,664 Site admin
    Answer ✓

    Awesome. More code, but it works reliably so its a win :).

    Allan

Sign In or Register to comment.