En este tutorial continuaremos con el proyecto que creamos en el post anterior "Construye SPAs sin necesidad de hacer una API con Inertia JS" y le agregaremos la funcionalidad para crear, editar y eliminar posts.
Paso 1:
Primero agregaremos Bootstrap a nuestra plantilla para darle un poco de estilo a nuestro sitio.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="{{ mix('/css/app.css') }}" rel="stylesheet"></link>
<script src="{{ mix('/js/app.js') }}" defer></script>
<title>Inertia JS</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
@inertia
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
Paso 2:
Ahora debemos agregar el modelo y la migración para para almacenar los datos de nuestros posts, puedes hacerlo con el siguiente comando artisan make:model Post -m
.
En la migración agregaremos tres campos: nombre, contenido y autor.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('content');
$table->string('author');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
Ejecutamos el comando artisan migrate
para que la tabla se guarde en nuestra base de datos (dentro del archivo .env ya debes tener configurada tu conexión a la base de datos).
Ahora en el modelo agregaremos los mismos campos para habilitar la asignación masiva.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = [
'name',
'content',
'author',
];
}
Paso 3:
Con el modelo ya creado el paso que sigue es crear el componente Vue para listar los posts y tener todas las acciones disponibles.
Para ello creamos el componente Index.vue
dentro del directorio resources\js\Pages\Posts
.
<template>
<div class="col-md-6">
<button class="btn btn-sm btn-primary w-100" @click="openModal()">Agregar nuevo</button>
<table class="table table-bordered table-condensed">
<thead>
<tr>
<td>Nombre</td>
<td>Autor</td>
<td>Acciones</td>
</tr>
</thead>
<tr v-for="row in data">
<td>{{row.name}}</td>
<td>{{row.author}}</td>
<td style="width: 130px">
<button @click="edit(row)" class="btn btn-sm btn-primary">Editar</button>
<button @click="deleteRow(row)" class="btn btn-sm btn-danger">Borrar</button>
</td>
</tr>
</table>
<div class="modal fade" id="modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Nuevo post</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="name">Nombre</label>
<input class="form-control" required id="name" v-model="form.name"/>
</div>
<div class="form-group">
<label for="content">Contenido</label>
<textarea class="form-control" required id="content" v-model="form.content"/>
</div>
<div class="form-group">
<label for="name">Autor</label>
<input class="form-control" required id="author" v-model="form.author"/>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" @click="closeModal()">Cerrar</button>
<button type="submit" class="btn btn-primary" v-show="!editMode" @click="save(form)">Guardar
</button>
<button type="submit" class="btn btn-primary" v-show="editMode" @click="update(form)">Actualizar
</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
</template>
<script>
export default {
props: ['data'],
data() {
return {
editMode: false,
form: {
name: null,
content: null,
author: null,
},
}
},
methods: {
openModal: function () {
$('#modal').modal('show')
},
closeModal: function () {
$('#modal').modal('hide')
this.reset();
this.editMode=false;
},
reset: function () {
this.form = {
name: null,
content: null,
author: null,
}
},
save: function (data) {
this.$inertia.post('/posts', data)
this.reset();
this.closeModal();
this.editMode = false;
},
edit: function (data) {
this.form = Object.assign({}, data);
this.editMode = true;
this.openModal();
},
update: function (data) {
if (!confirm('Sure')) return;
data._method = 'PUT';
this.$inertia.post('/posts/' + data.id, data)
this.reset();
this.closeModal();
},
deleteRow: function (data) {
if (!confirm('Sure')) return;
data._method = 'DELETE';
this.$inertia.post('/posts/' + data.id, data)
this.reset();
this.closeModal();
}
}
}
</script>
Con esto ya tenemos listo el componente para administrar nuestros posts.
Paso 4:
El siguiente paso es agregar el controlador con las funciones para listar, crear, guardar, editar, actualizar y eliminar, puedes usar el comando artisan make:controller PostController --resource
.
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
use Inertia\Inertia;
class PostController extends Controller
{
function index()
{
$data = Post::all();
return Inertia::render('Posts/Index', ['data' => $data]);
}
public function store(Request $request)
{
Post::create($request->all());
return redirect()->back();
}
public function update(Request $request)
{
if ($request->has('id')) {
Post::find($request->input('id'))->update($request->all());
return redirect()->back();
}
}
public function destroy(Request $request)
{
if ($request->has('id')) {
Post::find($request->input('id'))->delete();
return redirect()->back();
}
}
}
Paso 5:
El último paso es crear la ruta para poder ingresar y administrar los posts en el archivo routes\web.php
.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\PostController;
Route::get('/', [HomeController::class, 'index'])->name('home');
Route::resource('posts', PostController::class);
Y ahora solo ejecutamos el comando npm run development
para compilar los componentes de Vue.
En las siguientes capturas les comparto el sitio funcionando:


Conclusión
Con InertiaJS podemos desarrollar mucho más rápido aplicaciones que normalmente necesitarían de una API sin perder las ventajas de usar Frameworks frontend.