Header and body column order mismatched when using exportOptions columns for print button

Header and body column order mismatched when using exportOptions columns for print button

stokes_dkstokes_dk Posts: 6Questions: 0Answers: 0

Link to test case: https://codepen.io/stokes_dk/pen/yyBYXYV
Debugger code (debug.datatables.net): opovot
Error messages shown:
Description of problem:
Use column visibility to hide the Position column then press the print button. In the output, the order of the header is Name, Position, ... Salary; the order of the body rows is Name, Office, ... Position.

Name Position Office Age Start date Salary
Ashton Cox San Francisco 66 2009-01-12 $86,000 Junior Technical Author
Cedric Kelly Edinburgh 22 2012-03-29 $433,060.00 Senior Javascript Developer

This happens when exportOptions for the print button are specified as:

exportOptions: {
    columns : [ ':visible', '.always-print' ]
}

and there is a hidden table column with the class 'always-print', e.g.:

<thead>
        <tr>
            <th>Name</th>
            <th class="always-print">Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
        </tr>
</thead>

What I expected is that it would print only the visible columns but always include the Position column regardless of its visibility; in other words, :visible OR .always-print. What happens is that Position is always included but its placement in the header does not match its placement in the body rows.

Everything works as expected when the Position column is visible. When the Position column is hidden, this problem occurs.

I couldn't find anything in the docs for column-selector that says explicitly what should happen when ':visible' is used with a selector like '.always-print'. Some clarification in the docs would be helpful but presumably it is not intended to operate one way for the header and a different way for the body rows.

The same problem occurs with the csv export button.

Replies

  • allanallan Posts: 64,010Questions: 1Answers: 10,554 Site admin

    I believe this commit from October should fix this. I haven't released that yet, but will be doing so soon.

    With the nightly version it works as expected.

    Allan

  • stokes_dkstokes_dk Posts: 6Questions: 0Answers: 0

    Has this fix made it into a release yet?

  • kthorngrenkthorngren Posts: 21,670Questions: 26Answers: 5,017

    It looks like the fix was incorporated into DT 2.2.0. From the Release Notes:

    When using a CSS selector for the column selector (columns()) the order is now guaranteed to be in column index order.

    DT 2.2.2 is available from the Download Builder.

    Kevin

  • stokes_dkstokes_dk Posts: 6Questions: 0Answers: 0

    I still see the same problem: https://codepen.io/stokes_dk/pen/yyBYXYV

  • kthorngrenkthorngren Posts: 21,670Questions: 26Answers: 5,017

    The test case you just posted with 2.2.2 seems to work. For example hiding Position and Office:

    Results in this Print export:

    Are you expecting something different?

    Or can you provide the steps to show the issue you are seeing?

    Kevin

  • stokes_dkstokes_dk Posts: 6Questions: 0Answers: 0

    Yes. Look again at your screen capture. Under the Position heading is the age data.

  • kthorngrenkthorngren Posts: 21,670Questions: 26Answers: 5,017

    Look again at your screen capture. Under the Position heading is the age data.

    Yo have better vision than I :smile:

    @allan will need to take a look. Thanks for the additional info.

    Kevin

  • allanallan Posts: 64,010Questions: 1Answers: 10,554 Site admin

    Hi,

    It looks like my previous fix doesn't handle the case of using multiple selectors in an array unfortunately. However, there is a simple workaround. Combine your selector into one:

    columns : [ ':visible,.always-print' ]
    

    https://codepen.io/DataTables/pen/emYNYrY

    I'll look into address the array selector issue - thanks for brining it to my attention.

    Allan

  • allanallan Posts: 64,010Questions: 1Answers: 10,554 Site admin

    I've been mulling this over a bit and I'm a little weary of making a change for this. Consider the case where you specify columns [0, 8, 1], you would probably expect them to come back in the order specified. That is currently the case. A single selector will sort them, but an array will return in the array order.

    My current thinking is that should be defined as correct and documented as such.

    I'd welcome feedback on that thought process though!

    If I were to change it, it could be a breaking change and would be retained, probably until DataTables 3 (who knows when that will be!).

    Allan

  • stokes_dkstokes_dk Posts: 6Questions: 0Answers: 0

    Just to be clear, I'm not concerned about what order the columns are output, I'm saying that the order has to be consistent in the output header and body. If the output header columns are ordered A, B, C and the output body columns are A, C, B then that's a bug.

    In the screen capture above from Kevin the second column says Position in the header but contains cells from the Age column in the body.

    It looks to me like the header columns occur in the original sequence of the table but the body columns occur in the order specified in the array so the output is scrambled. I'm not sure why the code would use two different algorithms to determine the column sequence for the header and body but that appears to be what's happening.

    I can avoid this bug if I use a single string rather than an array of selectors, so that helps and I think I can do that in most of my cases. But for other people who need to use an array there's still a bug, right?

    -Dave.

  • allanallan Posts: 64,010Questions: 1Answers: 10,554 Site admin

    Hi Dave,

    I agree that there is an inconsistency between the header and the body - that is something I most certainly need to look at!

    Allan

  • allanallan Posts: 64,010Questions: 1Answers: 10,554 Site admin

    Following up on this to say that I've committed a fix to address the issue. I've also defined in the documentation what the behaviour should be and added tests to make sure it stays that way.

    Thanks,
    Allan

  • stokes_dkstokes_dk Posts: 6Questions: 0Answers: 0
    edited February 19

    Hi Allan, Thanks for the update on this. Documenting the behaviour would be helpful. Are you updating column-selector or another page? I think it's most important to be clear about which columns are included in the output; the order of the columns is less important but it's good to mention what the behaviour is rather than leave it unstated. It should be clear that the result is a union of the columns specified by the array.

    You had asked for thoughts on the column order of the output. I think it's probably best to stick with the order of columns as defined by the original table. Sometimes columns really should be next to each other like "First Name" and "Last Name", "Street Address" and "City", or "Start Date" and "End Date". I understand what you're saying, that if the user specifies columns [ 0, 8, 1 ] for export then they might expect the output to occur in that order but I don't think you can extend that logic to the general case. The array may contain a mix of things like [ 0, 8, 1, ':visible, .always-print' ]. I don't think it's the user's intent that the columns should be re-ordered so that visible columns occur after indexed columns; I think the intent is just to get the right set of columns. If the user really needs two columns to be adjacent but has to specify a mixed array for export then getting the right order becomes increasingly difficult (maybe impossible?). So I think it's best to stick with the original column order of the table.

    -Dave.

  • allanallan Posts: 64,010Questions: 1Answers: 10,554 Site admin

    Hi Dave,

    Yes, the column-selector is where I've added clarification on that. This is the specific bit.

    Many thanks for your thoughts! I've been continuing to ponder this, and I think if you explicitly ask for columns in a particular order, then they should be given back in that order. I accept that it might not always be what is needed - for such cases you could use columns().indexes() and then sort the indexes and reuse them as a new selector. More complex selectors or adding another class (e.g. the always-print one from your example) could also be an option.

    Not perfect, but I think always doing column order might be a limitation for some uses of the API.

    Allan

Sign In or Register to comment.