vue- Laravel con Inertia.js-app:TaskList
Laravel con Inertia.js
Aquí tienes el tutorial completamente corregido, especialmente la parte de rutas y controladores:
📁 ESTRUCTURA DE ARCHIVOS CORREGIDA
📁 taskList/
📁 app/
📁 Http/
📁 Controllers/
📄 TareaController.php
📁 resources/
📁 js/
📁 Components/
📄 TaskList.vue
📄 Boton.vue
📁 Pages/
📄 Tarea.vue
📁 views/
📁 routes/
📄 web.php🎯 RUTAS CORREGIDAS
routes/web.php
<?php
use App\Http\Controllers\TareaController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
*/
Route::get('/', function () {
return inertia('Welcome');
});
// ✅ RUTAS CORREGIDAS PARA TAREAS
Route::get('/tareas', [TareaController::class, 'index'])->name('tareas.index');
Route::post('/tareas', [TareaController::class, 'store'])->name('tareas.store');
Route::put('/tareas/{id}', [TareaController::class, 'update'])->name('tareas.update');
Route::delete('/tareas/{id}', [TareaController::class, 'destroy'])->name('tareas.destroy');
// ⚠️ IMPORTANTE: ¡Las rutas deben coincidir con el nombre del controlador!
// ❌ ERROR COMÚN: Route::get('/tarea', [TareaController::class, 'index'])
// ✅ CORRECTO: Route::get('/tareas', [TareaController::class, 'index'])🎯 CONTROLADOR CORREGIDO
app/Http/Controllers/TareaController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Inertia\Inertia; // 🔥 ¡OBLIGATORIO!
class TareaController extends Controller
{
// 📋 Mostrar todas las tareas
public function index()
{
// Recuperar tareas de sesión o base de datos
$tareas = session('tareas', []);
return Inertia::render('Tareas', [
'tareas' => $tareas
]);
}
// ➕ Crear nueva tarea
public function store(Request $request)
{
// Validar
$request->validate([
'titulo' => 'required|string|max:255'
]);
// Obtener tareas existentes
$tareas = session('tareas', []);
// Agregar nueva tarea
$tareas[] = [
'id' => time(),
'titulo' => $request->titulo,
'completada' => false
];
// Guardar en sesión
session(['tareas' => $tareas]);
// Redirigir (Inertia maneja la respuesta)
return redirect()->route('tareas.index');
}
// ✏️ Actualizar tarea
public function update(Request $request, $id)
{
$tareas = session('tareas', []);
foreach ($tareas as &$tarea) {
if ($tarea['id'] == $id) {
$tarea['completada'] = $request->completada ?? false;
$tarea['titulo'] = $request->titulo ?? $tarea['titulo'];
}
}
session(['tareas' => $tareas]);
return redirect()->route('tareas.index');
}
// 🗑️ Eliminar tarea
public function destroy($id)
{
$tareas = session('tareas', []);
$tareas = array_filter($tareas, function($tarea) use ($id) {
return $tarea['id'] != $id;
});
session(['tareas' => array_values($tareas)]);
return redirect()->route('tareas.index');
}
}🎯 COMPONENTE CORREGIDO
resources/js/Pages/Tareas.vue (Página principal)
<template>
<div class="max-w-2xl mx-auto p-6">
<h1 class="text-2xl font-bold mb-6">📝 Lista de Tareas</h1>
<!-- ✅ USO DEL COMPONENTE -->
<TaskList :tareas="tareas" @actualizar="refrescar" />
<!-- Formulario para agregar tareas -->
<form @submit.prevent="agregarTarea" class="mt-6">
<div class="flex gap-4">
<input
v-model="nuevaTarea"
type="text"
placeholder="Nueva tarea..."
class="flex-1 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<button
type="submit"
class="px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600"
>
Agregar
</button>
</div>
</form>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { router } from '@inertiajs/vue3';
import TaskList from '@/Components/TaskList.vue'; // ✅ REGISTRO LOCAL
// Props recibidas del controlador
const props = defineProps({
tareas: Array
});
// Estado local
const nuevaTarea = ref('');
// Métodos
const agregarTarea = () => {
if (!nuevaTarea.value.trim()) return;
router.post('/tareas', {
titulo: nuevaTarea.value
}, {
onSuccess: () => {
nuevaTarea.value = '';
}
});
};
const refrescar = () => {
router.get('/tareas');
};
</script>🎯 COMPONENTE REUTILIZABLE
resources/js/Components/TaskList.vue
<template>
<div class="space-y-3">
<div
v-for="tarea in tareas"
:key="tarea.id"
class="flex items-center justify-between p-4 bg-white rounded-lg shadow"
>
<div class="flex items-center gap-3">
<input
type="checkbox"
:checked="tarea.completada"
@change="toggleTarea(tarea)"
class="w-5 h-5"
>
<span :class="{ 'line-through text-gray-400': tarea.completada }">
{{ tarea.titulo }}
</span>
</div>
<button
@click="eliminarTarea(tarea.id)"
class="text-red-500 hover:text-red-700"
>
🗑️
</button>
</div>
<p v-if="!tareas.length" class="text-gray-500 text-center py-8">
No hay tareas aún. ¡Agrega una! ✨
</p>
</div>
</template>
<script setup>
import { router } from '@inertiajs/vue3';
defineProps({
tareas: Array
});
const emit = defineEmits(['actualizar']);
const toggleTarea = (tarea) => {
router.put(`/tareas/${tarea.id}`, {
completada: !tarea.completada
}, {
onSuccess: () => emit('actualizar')
});
};
const eliminarTarea = (id) => {
if (confirm('¿Eliminar esta tarea?')) {
router.delete(`/tareas/${id}`, {
onSuccess: () => emit('actualizar')
});
}
};
</script>🔥 REGISTRO GLOBAL EN app.js
resources/js/app.js
import './bootstrap';
import '../css/app.css';
import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy';
// ✅ IMPORTAR COMPONENTES
import TaskList from './Components/TaskList.vue';
import Boton from './Components/Boton.vue';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ el, App, props, plugin }) {
const app = createApp({ render: () => h(App, props) })
.use(plugin)
.use(ZiggyVue);
// ✅ REGISTRO GLOBAL
app.component('task-list', TaskList);
app.component('boton', Boton);
return app.mount(el);
},
progress: {
color: '#4B5563',
},
});📝 RESUMEN DE CORRECCIONES
| ❌ Error | ✅ Corrección |
|---|---|
Route::get('/tarea', ...) | Route::get('/tareas', ...) |
return Inertia::render('Tarea', ...) | return Inertia::render('Tareas', ...) |
session('tarea', '') | session('tareas', []) |
'tarea' => $request->tarea | 'titulo' => $request->titulo |
| Solo método store | Añadir métodos update y destroy |
🚀 COMANDOS ÚTILES
#si esta la carpeta creada
composer create-project laravel/laravel .
# Crear proyecto
composer create-project laravel/laravel taskList
# Instalar Jetstream con Inertia
composer require laravel/jetstream
php artisan jetstream:install inertia
# Crear controlador
php artisan make:controller TareaController
# Instalar dependencias
npm install
# Ejecutar desarrollo
npm run dev
# Migrar base de datos
php artisan migrate✅ VERIFICACIÓN RÁPIDA
Rutas: Todas usan
/tareas(plural)Controlador: Importa
Inertia\InertiaVista:
Inertia::render('Tareas', $data)Componente: Archivo
Tareas.vueen PagesRegistro: En
app.jsconapp.component()
¡Ahora sí está todo corregido! ¿Necesitas alguna aclaración adicional?
Comentarios
Publicar un comentario