{"ok": true, "next": null, "next_url": null, "rows": [{"id": "plugin_hooks:plugin-actions", "page": "plugin_hooks", "ref": "plugin-actions", "title": "Action hooks", "content": "Action hooks can be used to add items to the action menus that appear at the top of different pages within Datasette. Unlike  menu_links() , actions which are displayed on every page, actions should only be relevant to the page the user is currently viewing. \n             Each of these hooks should return a list of menu items, with optional  \"description\": \"...\"  keys describing each action in more detail. \n             The most common action item is a link to another page: \n             {\n    \"href\": datasette.urls.path(\"/-/custom-action\"),\n    \"label\": \"Custom action\",\n    \"description\": \"Run this action on a separate page.\",\n} \n             Plugins can also return button actions for JavaScript-backed interactions: \n             {\n    \"type\": \"button\",\n    \"label\": \"Open custom dialog\",\n    \"description\": \"Show a dialog without leaving this page.\",\n    \"attrs\": {\n        \"aria-label\": \"Open custom dialog\",\n        \"data-plugin-action\": \"open-custom-dialog\",\n    },\n} \n             These are rendered as  <button type=\"button\" class=\"button-as-link action-menu-button\" role=\"menuitem\" tabindex=\"-1\"> . The optional  attrs  dictionary is added to the button, and is useful for  data-*  attributes that your plugin's JavaScript can use to attach event handlers. \n             Here is a minimal plugin example that adds a button to a table page and loads JavaScript to handle clicks on that button: \n             from datasette import hookimpl\n\n\n@hookimpl\ndef table_actions(datasette, database, table):\n    return [\n        {\n            \"type\": \"button\",\n            \"label\": \"Show table name\",\n            \"description\": \"Open a JavaScript-powered plugin action.\",\n            \"attrs\": {\n                \"aria-label\": \"Show table name\",\n                \"data-plugin-action\": \"show-table-name\",\n                \"data-database\": database,\n                \"data-table\": table,\n            },\n        }\n    ]\n\n\n@hookimpl\ndef extra_js_urls(datasette):\n    return [\n        datasette.static(\n            \"show-table.js\", plugin=\"datasette_show_table\"\n        )\n    ] \n             The  static/show-table.js  file in that plugin could look like this: \n             document.addEventListener(\"click\", (event) => {\n  const button = event.target.closest(\n    \"button[data-plugin-action='show-table-name']\"\n  );\n  if (!button) {\n    return;\n  }\n  alert(`${button.dataset.database}.${button.dataset.table}`);\n}); \n             They can alternatively return an  async def  awaitable function which, when called, returns a list of those menu items.", "breadcrumbs": "[\"Plugin hooks\"]", "references": "[]"}], "truncated": false}