logo

Resource Tools

Overview

Resource tools are very similar to custom tools; however, instead of being listed in the Nova sidebar, resource tools are displayed on a particular resource's detail page. Like Nova tools, resource tools are incredibly customizable, and primarily consist of a single-file Vue component that is totally under your control.

Defining Tools

Resource tools may be generated using the nova:resource-tool Artisan command. By default, all new tools will be placed in the nova-components directory of your application. When generating a tool using the nova:resource-tool command, the tool name you pass to the command should follow the Composer vendor/package format. So, if we were building a Stripe inspector tool, we might run the following command:

bash
php artisan nova:resource-tool acme/stripe-inspector

When generating a tool, Nova will prompt you to install the tool's NPM dependencies, compile its assets, and update your application's composer.json file. All custom tools are registered with your application as a Composer "path" repository.

Nova resource tools include all of the scaffolding necessary to build your tool. Each tool even contains its own composer.json file and is ready to be shared with the world on GitHub or the source control provider of your choice.

Registering Tools

Nova resource tools may be registered in your resource's fields method. This method returns an array of fields and tools available to the resource. To register your resource tool, add your tool to the array of fields returned by this method:

php
use Acme\StripeInspector\StripeInspector;

/**
 * Get the fields displayed by the resource.
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return array
 */
public function fields(NovaRequest $request)
{
    return [
        ID::make()->sortable(),

        StripeInspector::make(),
    ];
}

Authorization

If you would like to only expose a given tool to certain users, you may invoke the canSee method when registering your tool. The canSee method accepts a closure which should return true or false. The closure will receive the incoming HTTP request:

php
use Acme\StripeInspector\StripeInspector;

/**
 * Get the fields displayed by the resource.
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return array
 */
public function fields(NovaRequest $request)
{
    return [
        ID::make('ID', 'id')->sortable(),

        StripeInspector::make()->canSee(function ($request) {
            return $request->user()->managesBilling();
        }),
    ];
}

Tool Options

Often, you will need to allow the consumer's of your tool to customize run-time configuration options on the tool. You may do this by exposing methods on your tool class. These methods may call the tool's underlying withMeta method to add information to the tool's metadata, which will be available within your Tool.vue component. The withMeta method accepts an array of key / value options:

php
<?php

namespace Acme\StripeInspector;

use Laravel\Nova\ResourceTool;

class StripeInspector extends ResourceTool
{
    /**
     * Get the displayable name of the resource tool.
     *
     * @return string
     */
    public function name()
    {
        return 'Stripe Inspector';
    }

    /**
     * Indicates that the Stripe inspector should allow refunds.
     *
     * @return $this
     */
    public function issuesRefunds()
    {
        return $this->withMeta(['issuesRefunds' => true]);
    }

    /**
     * Get the component name for the resource tool.
     *
     * @return string
     */
    public function component()
    {
        return 'stripe-inspector';
    }
}

Accessing Tool Options

Your resource tool's Tool.vue component receives several Vue props: resourceName, resourceId, and panel. The resourceId property contains the primary key of the resource the tool is currently attached to. You may use the resourceId when making requests to your controllers. The panel prop provides access to any tool options that may be available via the fields:

js
const issuesRefunds = this.panel.fields[0].issuesRefunds;

Dynamic Options

Resource tools also offer the ability to dynamically set options on the tool without a setter method by simple calling the desired option as a method when registering the tool. If called with an argument, it will be set as the option's value:

php
use Acme\StripeInspector\StripeInspector;

/**
 * Get the fields displayed by the resource.
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return array
 */
public function fields(NovaRequest $request)
{
    return [
        ID::make('ID', 'id')->sortable(),

        StripeInspector::make()->issuesRefunds(),
    ];
}

Building Tools

Each tool generated by Nova includes its own service provider and "tool" class. Using the stripe-inspector tool as an example, the tool class will be located at src/StripeInspector.php.

The tool's service provider is also located within the src directory of the tool, and is registered within the extra section of your tool's composer.json file so that it will be auto-loaded by Laravel.

Routing

Often, you will need to define Laravel routes that are called by your tool. When Nova generates your tool, it creates a routes/api.php routes file. If needed, you may use this file to define any routes your tool requires.

All routes within this file are automatically defined inside a route group by your tool's ToolServiceProvider. The route group specifies that all routes within the group should receive a /nova-vendor/tool-name prefix, where tool-name is the "kebab-case" name of your tool. So, for example, /nova-vendor/stripe-inspector. You are free to modify this route group definition, but take care to make sure your Nova tool will co-exist with other Nova packages.

Routing Authorization

When building routes for your tool, you should always add authorization to these routes using Laravel gates or policies.

Assets

When Nova generates your tool, resources/js and resources/css directories are generated for you. These directories contain your tool's JavaScript and CSS. The primary files of interest in these directories are: resources/js/components/Tool.vue and resources/css/tool.css.

The Tool.vue file is a single-file Vue component that contains your tool's front-end. From this file, you are free to build your tool however you want. Your tool can make HTTP requests using Axios via Nova.request.

Registering Assets

Your Nova tool's service provider registers your tool's compiled assets so that they will be available to the Nova front-end:

php
use Laravel\Nova\Nova;
use Laravel\Nova\Events\ServingNova;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    $this->app->booted(function () {
        $this->routes();
    });

    Nova::serving(function (ServingNova $event) {
        Nova::script('stripe-inspector', __DIR__.'/../dist/js/tool.js');
        Nova::style('stripe-inspector', __DIR__.'/../dist/css/tool.css');
    });
}

JavaScript Bootstrap & Routing

Your component is bootstrapped and registered in the resources/js/tool.js file. You are free to modify this file or register additional components here as needed.

Compiling Assets

Your Nova resource tool contains a webpack.mix.js file, which is generated when Nova creates your tool. You may build your tool using the NPM dev and prod commands:

bash
# Compile your assets for local development...
npm run dev

# Compile and minify your assets...
npm run prod

In addition, you may run the NPM watch command to auto-compile your assets when they are changed:

bash
npm run watch