ng-inertia
v0.1.2
Published
Angular adapter for Inertia.js
Readme
ng-inertia
Angular adapter package for Inertia.js.
This package lets Angular render pages returned by an Inertia server like Laravel. The adapter handles the Inertia router, page resolution, page rendering, layouts, link navigation, and form helpers.
The purpose of this package is to provide a first-party quality experience for Angular developers who want to use Inertia.js in their projects.
It is not an official Inertia.js package, but it follows the same principles and API design as the official adapters.
See the Inertia.js documentation for more information on how Inertia works and how to use it with different server-side frameworks.
This adapter is still in early development, so expect some rough edges and breaking changes. Feedback and contributions are welcome!
I made a Laravel-Angular-Inertia starter template to demonstrate how to use this adapter in a real app. Check it out here:
https://github.com/Ademking/laravel-angular-inertia-starter
If you want to install the adapter in your existing Angular app, follow the instructions below.
Install
npm install @inertiajs/core ng-inertiaHow it works
The setup is intentionally small:
createInertiaApp()boots Angular and connects it to the Inertia router.<inertia-root />renders the active Inertia page.@InertiaPage()marks a component as an Inertia page and can attach layouts.inertiaLinkturns normal anchors into Inertia visits.useForm()provides a simple form helper for Inertia requests.
Quick start
src/main.ts
import { createInertiaApp } from "ng-inertia";
import { appConfig } from "./app/app.config";
import { App } from "./app/app";
void createInertiaApp({
root: App,
appConfig,
importPage: (pageName: string) => import(`./app/pages/${pageName}.page.ts`),
}).catch((err) => console.error(err));src/app/app.ts
import { Component } from "@angular/core";
import { InertiaRootComponent } from "ng-inertia";
@Component({
selector: "app-root",
standalone: true,
imports: [InertiaRootComponent],
template: "<inertia-root />",
})
export class App {}src/app/app.html
<inertia-root />Page components
Page components should be default exports with a *.page.ts filename.
Use @InertiaPage() to mark a class as an Inertia page and to enable prop binding.
import { Component } from "@angular/core";
import { InertiaPage, InertiaPageFields } from "ng-inertia";
@InertiaPage()
@Component({
selector: "app-home-page",
standalone: true,
template: `
<section class="page-shell">
<h1>{{ title }}</h1>
<p>{{ subtitle }}</p>
</section>
`,
})
export default class HomePage implements InertiaPageFields<{
title: string;
subtitle: string;
}> {
title = "Home";
subtitle = "Rendered from an Inertia response.";
}Server props are assigned to matching class fields. If a prop does not match any field, the adapter warns in development mode.
Layouts
You can attach one layout or a chain of layouts to a page.
import { Component } from "@angular/core";
import { InertiaPage } from "ng-inertia";
import { MainLayoutComponent } from "../layouts/main-layout.component";
@InertiaPage({ layout: MainLayoutComponent })
@Component({
selector: "app-users-page",
standalone: true,
template: `
<section class="page-shell">
<h1>{{ heading }}</h1>
<p>{{ description }}</p>
</section>
`,
})
export default class UsersPage {
heading = "Users";
description = "This page uses a shared layout.";
}For nested layouts, pass an array:
@InertiaPage({ layout: [ShellLayoutComponent, MainLayoutComponent] })Each layout receives:
layoutsfor the remaining layout chain.pageComponentfor the page component.pagePropsfor the current page props.
Navigation links
Use the inertiaLink directive on anchors to trigger Inertia navigation.
import { Component } from "@angular/core";
import { InertiaLinkDirective } from "ng-inertia";
@Component({
standalone: true,
imports: [InertiaLinkDirective],
template: ` <a inertiaLink href="/users">Users</a> `,
})
export class ToolbarComponent {}Supported inputs include method, data, replace, preserveScroll, preserveState, only, except, headers, and queryStringArrayFormat.
Forms
useForm() gives you a simple form helper backed by RxJS streams.
import { Component, inject } from "@angular/core";
import { InertiaService, useForm } from "ng-inertia";
@Component({
standalone: true,
template: `
<form (submit)="save($event)">
<input
name="name"
[value]="form.data.name"
(input)="updateName($any($event.target).value)"
/>
<button type="submit" [disabled]="form.processing$ | async">Save</button>
</form>
`,
})
export class UserFormComponent {
private readonly inertia = inject(InertiaService);
readonly form = useForm(this.inertia, {
name: "",
email: "",
});
updateName(name: string): void {
this.form.set({ name });
}
save(event: SubmitEvent): void {
event.preventDefault();
void this.form.post("/users");
}
}The form helper exposes data$, errors$, and processing$, plus get, post, put, patch, and delete methods.
Resolver options
createInertiaApp() supports two page resolution strategies:
importPage, which loads page modules dynamically by page name.resolve, which lets you provide a custom resolver.
For most apps, importPage is the simplest option.
If you use importPage, keep your page files under a consistent path such as:
src/app/pages/home.page.ts
src/app/pages/users.page.tsApp structure
A typical Angular app using this adapter looks like this:
src/
main.ts
app/
app.ts
app.html
app.config.ts
layouts/
main-layout.component.ts
pages/
home.page.ts
users.page.tsAPI summary
createInertiaApp(options)
Bootstraps Angular and connects it to the Inertia router.
<InertiaRootComponent>
Internal root host that subscribes to page changes and renders the active component tree.
@InertiaPage(options?)
Marks a component as an Inertia page and optionally attaches layouts.
inertiaLink
Directive for client-side Inertia navigation.
useForm(inertia, initialData)
Returns a form helper for Inertia submissions.
usePage(inertia)
Returns the current Inertia page observable.
Minimal example
If you want the smallest possible setup, keep the app shell thin and let the adapter do the rest.
import { Component } from "@angular/core";
import { InertiaRootComponent } from "ng-inertia";
@Component({
selector: "app-root",
standalone: true,
imports: [InertiaRootComponent],
template: "<inertia-root />",
})
export class App {}import { createInertiaApp } from "ng-inertia";
import { appConfig } from "./app/app.config";
import { App } from "./app/app";
void createInertiaApp({
root: App,
appConfig,
importPage: (pageName: string) => import(`./app/pages/${pageName}.page.ts`),
});Credits
Created and maintained by Adem Kouki Repository: https://github.com/Ademking/ng-inertia GitHub: https://github.com/Ademking
