QTable question: Sort by selected/deselected rows

  • @metalsadman effectively it could be handled by some kind of computed/virtual table column.

  • @qyloxe - do you mean it could be handled in that way not changing Quasar code? If yes, could you elaborate a bit how this could be done? My guess is that somehow you would customize the header slot for that first “checkbox” column, which is Quasar generated, but I would need some sample code to start with.

  • @Mickey58

    this is actual column definition:

        // unique id (used by row-key, pagination.sortBy, ...)
        name: 'desc',
        // label for header
        label: 'Dessert (100g serving)',
        // row Object property to determine value for this column
        field: 'name',
        // OR field: row => row.some.nested.prop
        // (optional) if we use visible-columns, this col will always be visible
        required: true,
        // (optional) alignment
        align: 'left',
        // (optional) tell QTable you want this column sortable
        sortable: true,
        // (optional) compare function if you have
        // some custom data or want a specific way to compare two rows
        sort: (a, b, rowA, rowB) => parseInt(a, 10) - parseInt(b, 10),
        // function return value:
        //   * is less than 0 then sort a to an index lower than b, i.e. a comes first
        //   * is 0 then leave a and b unchanged with respect to each other, but sorted with respect to all different elements
        //   * is greater than 0 then sort b to an index lower than a, i.e. b comes first
        // (optional) you can format the data with a function
        format: (val, row) => `${val}%`,
        style: 'width: 500px',
        classes: 'my-special-class'

    If you could define “virtual” columns, then you could sort/filter/select them also. In example:

        // unique id (used by row-key, pagination.sortBy, ...)
        name: 'desc',
        // label for header
        label: 'Dessert (100g serving)',
        // (optional) alignment
        align: 'left',
        // (optional) tell QTable you want this column sortable
        sortable: true,
        value: (col, row) => this.selected.includes(row.id)

    the new column attribute “value” could be a “virtual”/“computed” column with parameters:
    col - this col definition
    row - actual row - based on other row values “value” function returns proper computed value

    It would solve your problem and many others.

  • @qyloxe: Thanks, this looks promising, but I’m still unsure how I would insert this “virtual column” into the first column, especially in the upper left cell of the header of the q-table.

    I see various slots in the q-table API for it, q-header, q-header-cell, q-header-cell[-name], q-th - not sure how to use them… Do you have a sample that manipulates the q-table header slots?

    Maybe I still misunderstand it, and you mean I should insert a new, second “virtual” column (after the first column that has the Quasar generated checkboxes for row selection) just for sorting of the first column, with that little up/down arrow in the header?

  • @metalsadman and @qyloxe:

    I forked a q-table codepen from @metalsadman that happens to customize the q-table header: [https://codepen.io/mickey58/pen/XWWVEEN]

    This is what I changed:

    • I added a “selection=‘multiple’” to the q-table, which auto-generates checkboxes in the first column.
    • I added two so far empty <q-th> </q-th> elements to get proper alignment of the table columns.

    I’m unsure how I could get that additional checkbox for selecting/unselecting all rows in the upper left corner cell (which is normally generated by Quasar in case of selection=“multiple”) and how to get to my end goal of getting sorting on it.

    Maybe you can have a look at my codepen and have a suggestion?

  • I was able to add the checkbox for selecting/unselecting all rows in the upper left corner cell (which is normally generated by Quasar in case of selection=“multiple”) in the codepen at [https://codepen.io/mickey58/pen/XWWVEEN].

    And I looked up the Quasar q-table source code to see how it handles the sorting of columns. The little “up/down” arrow icons that trigger the sorting are generated through very specific CSS, not through regular q-buttons. So it would require complicated CSS on the html table element for the first column/second header row, to get those arrows into the custom header in the codepen. That goes, at the moment, a bit too far in terms of customizing q-table.

    What remains to be looked at as an alternative is @qyloxe’ suggestion to implement sorting on the checkbox column (which has v-model=“props.selected”) through an (additional?) virtual column on props.selected. If triggering that sorting directly through an icon in the column header is difficult, it could still be triggered through a button outside of the q-table.

  • Like i said, you can issue a feature request for this, since those controls are internal, maybe just a scope slot for the multi selection th column so that you can customize it, relative props should also be exposed along with the functions that make the deselection/selection of all visible rows. And imo it look like a valid feature that can prove to be useful for others too. maybe @qyloxe can provide you a pen with his idea how to do it. Was trying it earlier, but you’ll have to reinvent how the selection/deselection function works, the sorting is not the problem.

  • @metalsadman @Mickey58
    Well, I have a mixed feelings about incorporating virtual columns into q-table. This is obviously the preferred way for presentation of computed (on the client side) values - in this example it is the “is selected” column but it could be anything - the sum of two other columns, the abstract of the long text, the amount with added local tax etc.

    IMHO the real problem is a concept of “data model”. Of course we could extend the q-table capabilities, BUT very similar capabilities should be possible for other components - list, tree etc. I consider it a bad design if every component would have his own “rules” and separate “data model” to deal with.

    I think, that at this moment Quasar is in need of a separate non-visual component for data modelling. There should be column definitions (also virtual/computed), pagination, sorting, filtering, querying, events for data loading, server synchronization etc. This non-visual component (or maybe class?) should be attached by composition to visual components like q-table, q-list, q-tree etc.

    So, I am sure, the computed/virtual columns are the way to go, but I’m not so sure, it should be implemented exactly into the q-table.

  • @metalsadman and @qyloxe - thanks for your thoughts. I agree that this stretches the customization of q-table quite far, and I also agree with @qyloxe that putting it into Quasar has also its downsides. The more such extras you put in, the more complex and heavyweight the components and their interfaces get - keeping a clean outside and inside design is important.

    Nevertheless, I now managed to put this extra sorting capability on selected/deselected columns in through customization - it is in this codepen derived from another QTable sample from @metalsadman : https://codepen.io/mickey58/pen/XWWVEEN

    Could you please have a quick look at the script section? Unfortunately I did not succeed in doing the computation of whether a row is selected into a computed: function. It is in a method currently, because it needs the row as a parameter. And I have “stolen” the sort function for Booleans from some other forum post.

    I’d appreciate if you have a quick look and comment whether it could be done better. Thanks.

  • @qyloxe i agree, thats why the composition api is coming to vue 3 for such cases. Like i was saying, this could be exposed by a scope slot as of now imo. @Mickey58 sry cant test this as of now (im at mobile atm, will take a look asap), like i said above the sorting is not the problem, but the deselection/selection, can be done but its reinvention, when its already in there internally just not exposed at current api.

Log in to reply