Laravel nova: How to override nova components
Asked Answered
W

3

7

Let's say, I want to replace the nova/resources/js/components/Form/FieldWrapper.vue with a custom one (add some CSS classes or add additional HTML), how to do this, without making changes to the /nova directory (to be able to update nova)?

The usecase for changing the edit view is for example:

  • to add a "*" sign to a field, if its a mandatory field
  • to change the "one field per row" style to a "two fields per row" style to use the huge wasted empty space and reduce the height of the form to reduce scrolling
Williams answered 18/9, 2018 at 7:25 Comment(2)
any update? did you manage to make it work? @WilliamsBattleship
Nope. As far as I know, its not possibleWilliams
K
4

It's a bit easier in new versions of Nova, and also some namings has changed.

I use this method at the moment:

  1. Create a resource tool sail php artisan nova:resource-tool yourcompany/nova-overrider

  2. Inside nova-components/NovaOverrider/resources/js/tool.js change the component name to the one you want to override. In newer versions of Nova they use CamelCase, not kebab-case. If you want to override the CreateResourceButton component, it could look like this:

    import Tool from "./components/Tool";
    
    Nova.booting((Vue, router, store) => {
        Vue.component('CreateResourceButton', Tool);
    });
    
  3. Run sail npm run build-nova-overrider to build the assets.

I suggest you change Tool.vue to the name of the actual component. That way you can have multiple overrides in that same nove-resource.

Kalil answered 5/11, 2022 at 15:55 Comment(2)
Your answer is totally works. I try looking for years but unlucky their solution not working with laravel nova 4.Affliction
@SeaklengSay I got same issue. Override Index view component with same name will override component but Inertia in nova 4 not worked. Thus, some features related to url query like search, pagination, sort not workImmanent
U
3

inside nova folder change file :

webpack.mix.js.dist to webpack.mix.js

enter to nova folder and do:

npm install
npm run watch

and then go to folder nova\resources\js

go change vue component do you need

after then run (on your root project):

php artisan nova:publish
Upanddown answered 4/12, 2018 at 11:12 Comment(1)
works with nova 4Deckert
R
2

the easiest way to override laravel nova vue files is to create a tool, and load a component with the same name as the component you want to override.

In my case, i was creating a custom Nova action, laravel Nova doesn't support custom actions but you can do it anyway. In order for the custom Action to work, i need to override 2 laravel nova vue files. let me walk you through how i did it.

i started by creating a custom tool with the command php artisan nova:resource-tool vendor/package-name. change the vendor and package name to your preference. The above command will create your tool folder and the nova-components folder in the root of your Laravel Project.

Under the src folder of your tool, you have the service provider class and the main tool class, my tool service provider looks like this

<?php

namespace TestTool\DataExportAction;

use Laravel\Nova\Nova;
use Laravel\Nova\Events\ServingNova;
use Illuminate\Support\ServiceProvider;

class ActionServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Nova::serving(function (ServingNova $event) {
            Nova::script('data-export-action', __DIR__.'/../dist/js/action.js');
        });
    }
}

as you can see am only serving a js file.

My main tool class named DataExportAction.php looks like this

<?php

namespace TestTool\DataExportAction;

use Laravel\Nova\Actions\Action;
abstract class DataExportAction extends Action
{
    /**
     * The filter's component.
     *
     * @var string
     */
    public $component = 'data-export-action';
}

as you can see, extending the laravel Nova action base class located at nova/src/Actions/Action.php and am overriding the vue component name here public $component = 'data-export-action';

In the tool resources/js folder, i have the main tool.js file which i renamed to action.js and a components folder where we will place the vue components that will override the main Nova vue files.

in the action.js file i have this

Nova.booting(Vue => {
    Vue.component('data-export-action',  require('./components/ConfirmActionModal'));
}) 

note the component name is the same as the one defined in DataExportAction class

now in order to use the custom class, i create the default nova action class and instead of extending the nova/src/Actions/Action.php class, i extend the DataExportAction class and it will automatically use my custom component when loading the action.

now, in order to get more control over the action, i also need to override a Vue component located at nova/resources/js/components/ActionSelector.vue. if you check the main nova components file located at nova/resources/js/components.js, the component is loaded like this

...

import ActionSelector from '@/components/ActionSelector'

Vue.component('action-selector', ActionSelector)

...

create an ActionSelector.vue file in the tool components folder with the contents of nova/resources/js/components/ActionSelector.vue. then in action.js file, add the line

Vue.component('action-selector', require('./components/ActionSelector'));

now the action.js file will look like

Nova.booting(Vue => {
    Vue.component('data-export-action', require('./components/ConfirmActionModal'));
    Vue.component('action-selector', require('./components/ActionSelector'));
})

note that we don't change the component name, now when Nova loads the action-selector component, it will load our custom component instead of the default one

if you try to run npm to compile the js of the tool we just created you will get an error because the component we are overriding requires files that are only in the Nova node_modules folder, to solve this, we edit our webpack.mix.js that looks like this

let mix = require('laravel-mix')

mix.setPublicPath('dist')
    .js('resources/js/action.js', 'js');

to this

let mix = require('laravel-mix')

mix.setPublicPath('dist')
    .js('resources/js/action.js', 'js')
    .webpackConfig({
        resolve: {
            alias: {
                '@/storage': path.resolve(__dirname, '../../nova/resources/js/storage'),
                '@': path.resolve(__dirname, '../../nova/resources/js/'),
            },
            modules: [
                path.resolve(__dirname, '../../nova/node_modules/'),
            ],
            symlinks: false
        },
    });

so instead of using our tools node_modules folder, we use the one in nova/

webpack should now compile successfully.

We have successfully overridden a Laravel Nova vue file

If you have questions, comment below, Cheers!!

Ritchey answered 10/12, 2020 at 3:42 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.