How to overwrite a default Nova component in Nova 4 #4340
-
|
I am trying to overwrite a Vue component using Laravel Nova 4, but I seem to only be able to register it too soon or too late, using the booting and booted Nova methods. Basically, i want to override the DetailActionDropdown to change the modals width. PS: I have installed the dependencies and compiled the assets. Does anyone have any ideas how to do this? resources/js/nova/components/DetailActionDropdown.vue<template>
<div>
<Dropdown>
<span class="sr-only">{{ __('Resource Row Dropdown') }}</span>
<DropdownTrigger
:dusk="`${resource.id.value}-control-selector`"
:show-arrow="false"
class="rounded hover:bg-gray-200 dark:hover:bg-gray-800 focus:outline-none focus:ring"
>
<BasicButton component="span">
<Icon :solid="true" type="dots-horizontal" />
</BasicButton>
</DropdownTrigger>
<template #menu>
<DropdownMenu width="auto" class="px-1">
<ScrollWrap
:height="250"
class="divide-y divide-gray-100 dark:divide-gray-800 divide-solid"
>
<div class="py-1">
<!-- Preview Resource Link -->
<DropdownMenuItem
v-if="resource.authorizedToView"
:data-testid="`${resource.id.value}-preview-button`"
:dusk="`${resource.id.value}-preview-button`"
as="button"
@click.prevent="openPreviewModal"
:title="__('Preview')"
>
{{ __('Preview') }}
</DropdownMenuItem>
<!-- Replicate Resource Link -->
<DropdownMenuItem
v-if="resource.authorizedToReplicate"
:dusk="`${resource.id.value}-replicate-button`"
:href="
$url(
`/resources/${resourceName}/${resource.id.value}/replicate`,
{ viaResource, viaResourceId, viaRelationship }
)
"
:title="__('Replicate')"
>
{{ __('Replicate') }}
</DropdownMenuItem>
<!-- Impersonate Resource Button -->
<DropdownMenuItem
as="button"
v-if="
currentUser.canImpersonate && resource.authorizedToImpersonate
"
:dusk="`${resource.id.value}-impersonate-button`"
@click.prevent="
startImpersonating({
resource: resourceName,
resourceId: resource.id.value,
})
"
:title="__('Impersonate')"
>
{{ __('Impersonate') }}
</DropdownMenuItem>
<DropdownMenuItem
v-if="resource.authorizedToDelete && !resource.softDeleted"
data-testid="open-delete-modal"
dusk="open-delete-modal-button"
@click.prevent="openDeleteModal"
:destructive="true"
>
{{ __('Delete Resource') }}
</DropdownMenuItem>
<DropdownMenuItem
as="button"
v-if="resource.authorizedToRestore && resource.softDeleted"
class="block text-sm text-left w-full px-3 py-1 font-semibold text-red-400 hover:text-red-300 focus:text-red-600 focus:outline-none focus:ring ring-inset"
data-testid="open-restore-modal"
dusk="open-restore-modal-button"
@click.prevent="openRestoreModal"
>
{{ __('Restore Resource') }}
</DropdownMenuItem>
<DropdownMenuItem
as="button"
v-if="resource.authorizedToForceDelete"
class="block text-sm text-left w-full px-3 py-1 font-semibold text-red-400 hover:text-red-300 focus:text-red-600 focus:outline-none focus:ring ring-inset"
data-testid="open-force-delete-modal"
dusk="open-force-delete-modal-button"
@click.prevent="openForceDeleteModal"
>
{{ __('Force Delete Resource') }}
</DropdownMenuItem>
</div>
<div
v-if="actions.length > 0"
:dusk="`${resource.id.value}-inline-actions`"
class="py-1"
>
<!-- User Actions -->
<DropdownMenuItem
v-for="action in actions"
:key="action.uriKey"
:dusk="`${resource.id.value}-inline-action-${action.uriKey}`"
type="button"
@click="() => handleActionClick(action.uriKey)"
:title="action.name"
>
{{ action.name }}
</DropdownMenuItem>
</div>
</ScrollWrap>
</DropdownMenu>
</template>
</Dropdown>
<!-- Action Confirmation Modal -->
<component
v-if="confirmActionModalOpened"
:show="confirmActionModalOpened"
:is="selectedAction.component"
:working="working"
:selected-resources="selectedResources"
:resource-name="resourceName"
:action="selectedAction"
:endpoint="endpoint"
:errors="errors"
@confirm="executeAction"
@close="closeConfirmationModal"
/>
<!-- Action Response Modal -->
<component
v-if="selectedAction"
:is="actionResponseData.modal"
@close="closeActionResponseModal"
:show="showActionResponseModal"
:data="actionResponseData"
/>
<DeleteResourceModal
:show="deleteModalOpen"
mode="delete"
@close="closeDeleteModal"
@confirm="confirmDelete"
/>
<RestoreResourceModal
:show="restoreModalOpen"
@close="closeRestoreModal"
@confirm="confirmRestore"
/>
<DeleteResourceModal
:show="forceDeleteModalOpen"
mode="force delete"
@close="closeForceDeleteModal"
@confirm="confirmForceDelete"
/>
</div>
</template>
<script>
import DetailActionDropdown from '../../../../vendor/laravel/nova/resources/js/components/Dropdowns/DetailActionDropdown.vue'
export default {
name: 'AppDetailActionDropdown',
extends: DetailActionDropdown,
}
</script>
resources/js/nova/custom.jsNova.booting((app, store) => {
app.component('DetailActionDropdown', require('./components/DetailActionDropdown').default);
});app/Providers/NovaServiceProvider.phppublic function boot()
{
parent::boot();
Nova::remoteScript(asset('js/nova/custom.js'));
} |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
|
@crynobone Correct me if I'm wrong, but it would probably solve the issue if you guys were to add a |
Beta Was this translation helpful? Give feedback.
-
|
Nova.booting is the correct place to put it from a JS standpoint. The way I do this is to create a new Nova Asset and do my overrides in there. Nova::serving($callback) is where scripts are registered within an asset and this works for me. Nova::serving(function (ServingNova $event) {
Nova::script('nova-overrides', __DIR__.'/../dist/js/asset.js');
});I just stick all of my overrides in one asset, but you could do as many assets as you need. Edit: Just saw your PS, but I will leave the below in for anyone else who is struggling Also don't forget you actually need to compile your component and then load the webpacked js, there is guidance on this in the Asset documentation but you also need to be aware that you need to install nova's npm dependencies You may also have to create an |
Beta Was this translation helpful? Give feedback.
-
|
@ianrobertsFF - Thanks for all the advice above. I'm trying to override a component which is coming from a nova-package rather than the nova core. I can't get youur method to work in this scenario. My best guess is that the package I want to override is registering its components after mine and overriding my override! Any idea how I can get this to work? Thanks |
Beta Was this translation helpful? Give feedback.
Nova.booting is the correct place to put it from a JS standpoint.
The way I do this is to create a new Nova Asset and do my overrides in there.
Nova::serving($callback) is where scripts are registered within an asset and this works for me.
I just stick all of my overrides in one asset, but you could do as many assets as you need.
Edit: Just saw your PS, but I will leave the below in for anyone else who is struggling
Also don't forget you actually need to compile your component and then load the webpacked js, there is guidance on this in the Asset documentation but you also…