Skip to content

Inertia.js

Pages and 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

Inertia.js pages should be named using Laravel's resource verbs. Here are a few examples:

  • /inertia/views/pages/listings/auctions/show/Page.vue
  • /inertia/views/pages/dealers/show/Page.vue
  • /inertia/views/pages/search/index/Page.vue
  • /inertia/views/pages/index/Page.vue

Page partials live alongside the Page.vue in a directory called partials:

  • partials/{PartialName}.vue
  • Page.vue

For instance, if dealers/show/Page.vue includes a partial for the dealer details, the filename would be: partials/DealerDetailsPanel.vue.

Page Props

When passing data from the inertia() PHP function to Inertia page components, use spatie/laravel-data, to generate TypeScript type definitions.

Prefer

dealers/show/Page.vue
<template>
  <div>
    <h1>{{ dealer.name }}</h1>
    <p>{{ dealer.bio }}</p>
  </div>
</template>

<script setup lang="ts">
export interface Props {
  dealer: App.View.Inertia.DealerData;
}

defineProps<Props>();
</script>

Avoid

ListingShowPage.vue
<template>
  <div>
    <h1>{{ $page.props.dealer.name }}</h1>
    <p>{{ $page.props.dealer.bio }}</p>
  </div>
</template>

Note

It is fine to use const page = usePage() 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 Event Handling.

<template>
  <button @click="emit('someEvent', 'event-parameter')">Click me</button>
</template>

<script setup lang="ts">
const emit = defineEmits({
    someEvent: [name: string];
})
</script>

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 a Pinia store

Avoid using this.$root

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

modal-store.ts
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 setup lang="ts">
import { useModalStore } from "./modal-store";

const modalStore = useModalStore();
</script>