Skip to content

Inertia Guidelines

Page & Layout Components (Partials)

Partials are smaller parts of a page or layout, intended solely to reduce the amount of code within a single component and simplify the codebase. These are single-use components.

Naming Convention

To keep partials scoped and separate, follow this naming convention:

{ParentComponentName}{PartialName}.vue

For instance, if ListingShowPage.vue includes a partial for the vehicle details, the file name would be:

Example
ListingShowPageVehicleDetailPanel.vue

Placement

  • Make a partials directory in the same directory as the parent page component
  • Make a directory inside the partials directory for each partial
Example
/inertia/views/pages/listings/show
├── ListingShowPage.vue
└── /partials
    └── /vehicle-details-panel
        ├── ListingShowPageVehicleDetailPanel.stories.js
        ├── ListingShowPageVehicleDetailPanel.vue
        └── ListingShowPageVehicleDetailPanelItem.vue

Storybook

Put Storybook stories for partials in the same directory as the partial.

In order to scope partial stories, use the following naming convention:

title: 'Pages/{PageName}/{ComponentName}',
Example
title: 'Pages/ListingShow/Vehicle Details Panel',

Page Props

When passing data from the inertia() PHP function to Inertia page components, use the props property in the component to define the expected props.

Prefer

ListingShowPage.vue
<template>
    <div>
        <h1>{{ listing.title }}</h1>
        <p>{{ listing.description }}</p>
    </div>
</template>

<script>
export default {
    props: {
        listing: {
            type: Object,
            required: true,
        },
    },
};
</script>

Avoid

ListingShowPage.vue
<template>
    <div>
        <h1>{{ $page.props.listing.title }}</h1>
        <p>{{ $page.props.listing.description }}</p>
    </div>
</template>

Note

It is fine to use $page.props to access globally shared props, such as the user object. These are passed by the HandleInertiaRequests middleware.

Communication Between Components

Direct Communication

For direct communication between parent and child components, use standard Vue events.

<button @click="$emit('someEvent')">
    Click me
</button>

<my-component @some-event="callback" />

However, if you find the need to bubble the event up to the parent's parent, or even higher, consider using the Store.

Indirect Communication

The goal is to limit the number of techniques used for communication between components.

Prefer using the Pinia Store

Avoid using this.$root

Avoid using EventHub

We have Pinia Store available. Prefer it over other techniques when dealing with indirect communication between components. Example:

modal-store.js
export const useModalStore = defineStore('modal', () => {
    const isModalSortOpen = ref(false);

    function openModalSort() {
        isModalSortOpen.value = true;
    }

    return {
        isModalSortOpen,
        openModalSort,
    };
});
StoreConsumer.vue
<template>
    <button @click="modalStore.openModalSort">
        Open modal
    </button>
</template>

<script>
import { useModalStore } from './modal-store.js';

export default {
    setup() {
        const modalStore = useModalStore();

        return {
            modalStore,
        };
    },
};
</script>