Get selected record IDs for custom added admin button

Hi all!

I added custom buttons to “actions” injection zone, added some modals and stuff that I need for bulk operations. Now, I want to do bulk actions but only on selected records - and I simply can not find a way to get the IDs of the records selected in Strapi admin table (no customizations there). Strapi shows the Delete button when one or more is selected so that part works of course. But how do I get those IDs for my custom use?

Since there is no answer and I need a solution - everything else for bulk ops is ready, I simply created a very very hacky method which could help some other poor soul :slight_smile: If someone sees this and knows a correct way of doing this in Strapi Admin, I would surely like to know. This is prone to issues if Strapi table structure changes but it is not that hard to update :confused:

What this does is a very basic DOM scrape in order to get IDs - of course, ID column must be shown!

const getCheckedIDs = () => {
    let ids = []
    document.querySelectorAll('input[type="checkbox"]:checked').forEach(c => {
      const elements = c.parentElement.parentElement.querySelectorAll('td[aria-colindex="2"] > span')
      if (elements.length > 0) ids.push(elements[0].textContent)
    })
    console.log("selected ids", ids)
    return ids
  }
2 Likes

how to use this in custom button components? can you show me the full code?

I can not show you the full code since it is done for a client but I can try to separate important bits.
It really is not that hard if you read the docs - which I highly recommend. There are some gotchas as in everything, so docs will help.

  1. Create a normal React component where you can use Strapi Design elements (put it into /src/admin/extensions/components folder) - for example a simple Button can be shown like this:
import React from "react"
import { Button } from "@strapi/design-system"
import IconCog from "@strapi/icons/Command"

const TestButton = ({}) => {
  const handleClick = () => {
    console.log("TEST button clicked!")
  }

  return (
    <Button variant="secondary" startIcon={<IconCog />} onClick={handleClick}>
      TEST
    </Button>
  )
}

export default TestButton
  1. Inject that button into listview or editview (you have that in Strapi docs) - you need to add this code into bootstrap part of app.js
bootstrap(app) {
  app.injectContentManagerComponent(
    "listView",
    "actions",
    {
      name: "TEST Button",
      Component: TestButton, // you need to import this component into app.js of course
    }
  )
}

This way you will get this button on every listview (browse) screen.
If you want to limit that - you have a simple solution - check for location and show button accordingly.
I do my checks with something like this:

 const validPathNames = [
    "/content-manager/collectionType/api::order.order"
  ]
  let isButtonDisplayed = false
  for (let vp of validPathNames) {
    isButtonDisplayed = useLocation().pathname.includes(vp)
    if (isButtonDisplayed) break
  }

And then it is a simple value check to render it or not.