Getting Started
Larajax UI builds data-driven interfaces for Laravel from configuration. You describe a form's fields or a list's columns in YAML, bind a model, and the widget renders working markup with its AJAX behaviour (sorting, pagination, search, validation, uploads) wired up.
There is no JavaScript framework and no build step: the browser assets are plain CSS and ES modules, styled on top of Bootstrap 6. The widgets run on plain Eloquent models as well as October Rain models, and every widget is a Larajax view component, so its AJAX handlers reach the controller that built it without any routing of your own.
Run the demo app
Amber is the demo app for Larajax UI, a Laravel application that runs every example in these docs. Clone it, set it up and serve it:
git clone https://github.com/larajax/amber.git
cd amber
composer setup
composer devcomposer setup installs the dependencies, creates the .env file and an SQLite database, and seeds it with users, groups and a blog of posts. composer dev serves the app at http://localhost:8000. Every seeded user's password is password.
The app has two halves:
- Reference, at
/reference, has one page for every part of the library, grouped the way these docs are: list columns and options, filter scopes, form fields and layout, each form widget, the UI elements, and the extension points. Every example runs beside the YAML or Blade that renders it, and you can change it and save it. Each example's heading links to its section in these docs. - Showcase is a small blog that puts the pieces together: posts with a filtered list, bulk actions and a quick post popup (
/posts), a category tree you reorder by dragging (/categories), authors on a plain Eloquent model (/authors), and groups edited in a popup (/groups). Each page links to the guide that builds it.
The sixty second version
The demo's Authors page lists Laravel's stock User model. Its columns are a YAML file:
# ===================================
# Author List Column Definitions
# ===================================
columns:
name:
label: Name
searchable: true
sortable: true
email:
label: Email Address
searchable: true
sortable: true
posts_count:
label: Posts
type: number
relation: posts
relationCount: true
sortable: true
width: 100px
created_at:
label: Joined
type: date
sortable: true
width: 160pxA controller builds the list with Lists::make(), and a filter and a toolbar bound to it:
/**
* prepareListVars builds the list, filter and toolbar, bound together, for the index view.
*
* @return array{list: Lists, filter: Filter, toolbar: Toolbar}
*/
protected function prepareListVars(): array
{
$list = $this->makeListWidget();
$filter = $this->makeFilterWidget();
$filter->bindToListWidget($list);
$toolbar = $this->makeToolbarWidget();
$toolbar->bindToListWidget($list);
return [
'list' => $list,
'filter' => $filter,
'toolbar' => $toolbar,
];
}
/**
* makeListWidget builds the paginated list of authors in name order, where clicking a row opens the author's form.
*/
protected function makeListWidget(): Lists
{
return Lists::make(
model: new User,
columns: '~/resources/ui/user/columns.yaml',
recordsPerPage: 10,
showCheckboxes: true,
recordUrl: 'authors/:id/edit',
defaultSort: ['column' => 'name', 'direction' => 'asc'],
noRecordsMessage: 'No authors match the search and filters.',
);
}The view prints the widgets:
@extends('layouts.app')
@section('title', 'Authors')
@section('content')
<h1 class="mb-3">
Authors
</h1>
<p class="fg-3 mb-7">
The people who write the posts. Click an author to edit their account and groups, or check rows to delete them; their posts stay, without an author.
<a href="{{ config('reference.docs_url') }}/guides/models#what-works-on-eloquent" target="_blank" rel="noopener">
How this page is built
</a>
</p>
{{ $toolbar }}
{{ $filter }}
{{ $list }}
@endsectionThat renders a sortable, searchable, paginated table of authors, with filter scopes from resources/ui/user/scopes.yaml and a toolbar of buttons and a search box above it. Clicking a row opens the author's form, which works the same way from a fields.yaml file.
Each widget declares its common options as make() arguments, so your editor can suggest and document them as you type, and less common options pass through the same call by name. A configuration array built at runtime goes to Lists::makeWithConfig($config). Widgets are Htmlable, so Blade's prints their markup as it is.
How it fits together
A widget built with make() inside a controller action is bound to that controller, so its AJAX handlers, such as a click on a sortable header, reach it with no routes beyond the page's own address. The widgets are Larajax view components: see Widgets and Controllers for what that means for your controllers, and the Larajax documentation for Larajax itself.
Configuration is declarative but never a cage: each widget also takes plain PHP arrays, can be extended by subclassing or by binding to its events, and reads any model, including plain Eloquent models (see Models).
The docs
- Introduction: this page and Installation, which adds Larajax UI to an application.
- Guides walk through the Showcase pages: Building a Form Page, Building a List Page, Models and Widgets and Controllers.
- Reference pages explain every option, one page for each page of the demo's Reference, section for section:
- Lists: columns, list options, the list structure, the toolbar and search;
- Filters: scope types and filter options;
- Forms: field types, layout and behaviour;
- Form Widgets: relations, repeaters, uploads, editors, pickers and more;
- UI: buttons, dropdowns, popups, tabs, feedback and inputs;
- Extending: custom widgets, icons, and URL and timezone rules.
Next steps
- Installation: get Larajax UI into your application