Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Row selection via checkbox (FR: provide slot for this) #69

Closed
mesqueeb opened this issue Jul 17, 2021 · 7 comments
Closed

Row selection via checkbox (FR: provide slot for this) #69

mesqueeb opened this issue Jul 17, 2021 · 7 comments
Labels
help wanted Extra attention is needed

Comments

@mesqueeb
Copy link

I strongly believe that customisation of the table features that involves UI is best done by providing a slot for the developer!

For row selection: currently you allow selection of the row itself with customisation via a CSS class.

My requirement:

  • I want to add a checkbox as the first column of each row, so that you can click on that checkbox to select that row.
  • I want to add a checkbox in the first column's header to select all rows

I'm imagining the slot syntax could look something like this:

<template v-slot:header-selection="scope">
  <my-checkbox v-model="scope.selectedAll" /> 
</template>

<template v-slot:body-selection="scope">
  <my-checkbox v-model="scope.selectedRow" />
</template>

What do you think?

@tochoromero
Copy link
Owner

This is already possible, the <v-th> component has a slot you can use to add your checkbox and each row can have its own checkbox as well.

Now, honestly, once you add your own checkboxes it is better to handle the selected state outside of the plugin. So you can keep track of what is selected outside of the table plugin.

Please let me know if you need help implementing it.

@tochoromero tochoromero added the help wanted Extra attention is needed label Jul 17, 2021
@mesqueeb
Copy link
Author

mesqueeb commented Jul 18, 2021

@tochoromero thanks for your message!

Do you suggest something like this for the vue3 version?

<VTable
  ref="usersTable"
  :data="users"
  selectionMode="multiple"
  selectedClass="selected-row"
  @stateChanged="selectedRows = $event.selectedRows"
>
  <template #head>
    <th>
      <input
        type="checkbox"
        :value="selectedRows.length === users.length"
        @input="() => selectedRows.length === users.length ? $refs.usersTable.deselectAll() : $refs.usersTable.selectAll()"
      />
      Select all
    </th>
    <th>Name</th>
  </template>
  <template #body="{ rows }">
    <VTr
      v-for="row in rows"
      :key="row.guid"
      :row="row"
    >
      <td>
        <input
          type="checkbox"
          :value="selectedRows.find(_row => _row.id === row.id)"
          @input="() => selectedRows.find(_row => _row.id === row.id) ? $refs.usersTable.deselectRow(row) : $refs.usersTable.selectRow(row)"
        />
      </td>
      <td>{{ row.name }}</td>
    </VTr>
  </template>
</VTable>

My Questions

  1. Is this the implementation you envision as well?
  2. [edit, deleted question since I know now I've read your source code]
  3. [edit, see edit below] I'm confused about this part of the docs where you use a <VTh> in which you pass the table data and you access the selectAll function, while at the bottom of that page, the example uses a regular <th> instead.
    a. When using the ref of the table itself, does it not have the selectAll function?
    b. How do we decide if we need to use regular <th> vs <VTh>?
    c. In what case do you need to pass the table data array into the <VTh> as well as to the table?
    d. note: I feel that this snippet would be waaaay easier to understand if you also show the rest of the VTable and the rows in this example, because it's just too "cryptic" as the example is now. 😅

image

EDIT: I believe my note on VTh above might be invalid, in your docs you wrote VTh, but I think it might've been a typo and it was meant to be VTable in that section?

An alternate approach

I'm still learning about the Vue 3 syntax changes, but having used Vue ever since version one, I learned over the years that's it's way better to provide functionality to slot content via the v-bind on the slot. Because it's easier to track what inner functions you can rename that way and which are part of your public api.

Take your <VTr> as per an example. If you design the vue component like so (vue 2 syntax below, but just hypothetical to make my point :P )

<template>
  <tr>
    <slot :rowIsSelected="rowIsSelected" />
  </tr>
</template>
<script>
export default {
  name: 'VTr',
  data () {
    return { rowIsSelectedInner: false }
  },
  computed: {
    rowIsSelected: {
      get() {
        return this.rowIsSelectedInner
      },
      set() {
        // whatever logic you need to do
      },
    },
  }, 
}
</script>

Then you can make it (a) very easy for the user to programatically select or deselect a row, and (b) I feel it's cleaner and slightly safer than working with refs. (but that's more of a personal opinion)

The way the user could now select a single row, or even all rows would be:

<VTable>
  <VTh>
    <template v-slot="scope">
      <td>
        <input
          type="checkbox"
          v-model="scope.allRowsSelected"
        />
      </td>
      <td>{{ row.name }}</td>
    </template>
  </VTh>
  <VTr
    v-for="row in rows"
    :key="row.guid"
    :row="row"
  >
    <template v-slot="scope">
      <td>
        <input
          type="checkbox"
          v-model="scope.rowIsSelected"
        />
      </td>
      <td>{{ row.name }}</td>
    </template>
  </VTr>
</VTable>

If you understand what I mean? :O

  1. (so my last question) While it might be slightly different syntax for Vue 3, what do you think of this kind of API to expose some easy to use logic / state / methods to the dev via the VTh and VTr slots with v-bind on the slot?

EDIT: I've made a PR related to this down below.

@mesqueeb
Copy link
Author

For question 3 above, see this PR:
#70

@mesqueeb
Copy link
Author

Hey @tochoromero Here is an early PR with a slight change supporting my philosophy about using $ref less and using slot scope more:
#71

I would love to expand this PR to pass more focussed scope via the VTr default slot instead of to the VTable body slot. But tell me if you like this addition to your library.
If you don't I won't bother expanding on this.

@tochoromero
Copy link
Owner

Hey @mesqueeb I just published a new version with new support slots for row selection. Please take a look:

https://vue-smart-table.netlify.app/selection.html#advanced-selection

@mesqueeb
Copy link
Author

@tochoromero oh? Did you see my PR here?
#73
I was willing to do all the work, but you never replied :S

@mesqueeb
Copy link
Author

@tochoromero I made a final post on that old PR of mine! Would love it if you could have a look :)

#73 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants