If you've seen issue 786 on laravel/nova-issues 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:
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.
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
:
<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
:
<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:
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.
Note: I quickly wrote this article, I'll clean it up later.
Top comments (11)
Hi,
I want try this tool,but when install i am getting the following namespace parser error.
Fixed!
Just removed a vendor dir in project (rm -rf vendor)
Then run composer update
And try to create a new nova resourse-tool with following command:
php artisan nova:resource-tool my-vendor-name/custom-resource-toolbar
'my-vendor-name' should be in kebab case
It helped me, hope it will help you
After I run your command:
php artisan nova:resource-tool 0x15f/custom-resource-toolbar
The artisan in my project stopped working...
It always reports an error with this wierd thing
In case if you know how to fix it please let me know!
what do you mean with
add it to your Resources
?This is the important part: "You can define your resources toolbar component by registering a component with your resources plural name followed by -detail-toolbar."
So in my case, I was using for an Article nova resource. So I changed the 'quotes-detail-toolbar' to 'articles-detail-toolbar'. That's it. You don't even need to add it as a tool, like you do with most other Nova tools in your NovaServiceProvider.
The button will now show up in your Resource (url should be something like: '/resources/articles/76'), assuming you ran 'npm run dev' on your tool.
hi ! i'm so sorry, i'm learning laravel and i dont understand where i can add my button. I mean i did all of things at top, but event a random button doesnt appeared x3
Yes! When you add the resource tool to the model use the canSee method you use to hide fields and stuff. More info here
Hello,
great job !
I do this in the Index page - and it works perfectly!
I have one question, maybe you have any idea how to add to button permissions?
On the detail page I can use withMeta method, but is there any way to pass the permission to do the action on index page ?
Thank you for this tutorial but can you please explain how to use this on a resource? Thank you!
This is the important part: "You can define your resources toolbar component by registering a component with your resources plural name followed by -detail-toolbar."
So in my case, I was using for an Article nova resource. So I changed the 'quotes-detail-toolbar' to 'articles-detail-toolbar'. That's it. You don't even need to add it as a tool, like you do with most other Nova tools in your NovaServiceProvider.
The button will now show up in your Resource (url should be something like: '/resources/articles/76'), assuming you ran 'npm run dev' on your tool.
This is really simple! thank you very much.