Laravel Nova: Adding custom buttons to resource toolbars
Tags: laravel, vue, php
Published: 2019-03-14 00:48:15

![header image](https://i.imgur.com/FEVhO9n.png)
If you've seen [issue 786 on laravel/nova-issues](https://github.com/laravel/nova-issues/issues/786) on Github or attempted to add custom buttons to Resources in Laravel Nova you are probably frustrated. I spent a *whole* day trying to figure this out. But it's a lot simpler than you think!

Laravel Nova is powered by Vue.JS a very powerful JS microframework. Each resource has a custom component and that component has its own scope. This allows us to override Nova's built-in components and add custom buttons.

Let's start by creating a new Nova Resource Tool:
```bash
php artisan nova:resource-tool 0x15f/custom-resource-toolbar
```

Say `yes` to all of the prompts...

Now that you've created your resource tool navigate to the `nova-components/custom-resource-toolbar/resources/js` directory open `tool.js` in your favorite JS editor and paste the following.

```javascript
Nova.booting((Vue, router) => {
    Vue.component('custom-detail-toolbar', require('./components/CustomDetailToolbar'));
    Vue.component('quotes-detail-toolbar', require('./components/QuotesDetailToolbar'));
})
```

Navigate into the `components` directory and delete `Tool.vue`. Now create two files, one named `CustomDetailToolbar.vue` the other named `QuotesDetailToolbar.vue`. Paste the following into `CustomDetailToolbar.vue`:

```vue
<template>
    <div class="flex w-full justify-end items-center mx-3">
        <component v-if="hasComponent" :is="component" />
    </div>
</template>

<script>
    export default {
        props: ['resourceName', 'resourceId'],
        computed: {
            component(){
                return this.resourceName + '-detail-toolbar';
            },
            hasComponent()
            {
                return this.component in this.$options.components;
            }    
        }
    }
</script>
```

And paste the following into `QuotesDetailToolbar.vue`:

```vue
<template>
    <div>
        <div class="flex w-full justify-end items-center">
           <a
                class="btn btn-default btn-icon btn-white"
                :href="'/nova-vendor/custom-resource-toolbar/export-quote/' + this.$parent.resourceId"
                style="background-color: var(--primary); color: white;">
                Export as PDF
             </a>
        </div>
    </div>
</template> 

<script>
    export default {
        props: ['resourceName', 'resourceId', 'field'],
        mounted() {
            var elements = document.getElementById('nova').querySelectorAll('h4');
            [].forEach.call(elements, function(element) {
                if(element.innerHTML === 'Custom Detail Toolbar') {
                    element.parentNode.remove();
                }
            });
        }
    }
</script>
```

You can now build your Resource Tool using `npm run watch`, add it to your Resources, and open your `CustomResourceToolbar.php` file and change the component name to `custom-detail-toolbar`. I'll explain what we did below.

In `tool.js` we registered two new components `custom-detail-toolbar` and `quotes-detail-toolbar`, `custom-detail-toolbar` is used by Nova to load any components that should be displayed on that toolbar. Nova then looks for the resource's toolbar. You can define your resources toolbar component by registering a component with your resources plural name followed by `-detail-toolbar`. Within that component, you can add any CSS/JS that should be placed in the toolbar.

If you notice I have a `mounted` function in my component with the following code:

```js
mounted() {
    var elements = document.getElementById('nova').querySelectorAll('h4');
    [].forEach.call(elements, function(element) {
        if(element.innerHTML === 'Custom Detail Toolbar') {
            element.parentNode.remove();
        }
    });
}
```

Typically a resource tool has a panel on your resource detail page. This function runs when our component has been mounted to remove the panel that nova adds giving your page a clean feel.

You can find all the code used in this tutorial [on github](https://github.com/0x15f/custom-resource-toolbars).

**Note:** I quickly wrote this article, I'll clean it up later.