larave-jquery-ajax-json

Gracias a Blade el sistema de plantillas que Laravel posee, podemos hacer cosas que podríamos pensar complicadas de manera muy sencilla. Una de esas cosas es refrescar una sección de una plantilla o layout en tu aplicación, sin necesidad de cargar la pagina completamente, usando la función renderSection().  En los siguientes párrafos explicaremos como hacerlo usando la función AJAX de jQuery y retornando un texto en formato Json, para esto haremos una pequeña interfaz que permita ver, agregar y borrar imagenes.

Les recomendamos pasar por estos tutoriales, pues serán de gran utilidad para este artículo.

Bien, luego de tener una aplicación Laravel recién instalada. Lo primero será instalar con el componente Faker como se les menciona arriba.

Para continuar crearemos un modelo llamado Image, para esto escribimos en el terminal lo siguiente.

php artisan make:model Image

Esto nos creara dos archivos, Image ubicado en /UsoDeRenderSectionsl5/app/Image ; y la migracion en Database/Migration/.

Veamos como quedara la migración en la cual solo para este articulo vamos a agregar un campo «imageUrl» a la función up() :

public function up()
	{
		Schema::create('images', function(Blueprint $table)
		{
			$table->increments('id');
            $table->string('imageUrl');
            $table->timestamps();
        });
	}

Aprovechemos que estamos por la base de datos y creamos un Seeders con el componte Faker, el código debería quedar de la siguiente manera.

<?php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
use Faker\Factory as Faker;
class ImagesSeeder extends Seeder {
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $faker = Faker::create();
        for($i=0;$i < 12;$i++) {
            \DB::table('images')->insert(array(
                'imagesUrl' => $faker->imageUrl($width = 171, $height = 180, 'nature'),
            ));
        }
    }
}

Nota: Recuerda añadir el llamado de la Clase ImagesSeeder en el metodo run de la Clase DatabaseSeeder, para finalizar esta parte, en el terminal ejecuta 

composer dump-autoload

Al modelo Image no le haremos ningún cambio y lo dejaremos como está. Así que podemos seguir adelante con las vistas. Para no hacer muchos cambios usaremos la plantilla welcome.blade.php como plantilla principal, pero la editaremos un poco.

<html>
	<head>
		<title>Uso de Render Sections L5</title>
        <link href="{{ asset('/css/app.css') }}" rel="stylesheet">
		<link href='//fonts.googleapis.com/css?family=Lato:100' rel='stylesheet' type='text/css'>

		<style>
			body {
				margin: 0;
				padding: 0;
				width: 100%;
				color: #333333;
				display: table;
				font-weight: 100;
				font-family: 'Lato';
                background-color: #c5e1a5;
			}
		</style>
	</head>
	<body>
    <div class="container">
        <div class="page-header">
            <div class="row">
                <div class="col-md-8">
                    <h1>renderSections()</h1>
                </div>
                <div class="col-md-4">
                    <a class="btn btn-primary pull-right addImage" href="#" role="button">Agregar Imagen</a>
                </div>
            </div>
        </div>
        <div id="principalPanel">
            @section('contentPanel')

            @show
        </div>
    </div>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
    <script src="{{asset('js/functions.js')}}"></script>
	</body>
</html>

Detallemos esto paso a paso:

  1. Seguimos usando Boostrap, asi que no tocamos el css y los scripts.
  2. Tenemos un Boton con la clase addImage, que usaremos en conjunto con AJAX para agregar una nueva imagen.
  3. Agregamos un div padre con un id «principalPanel», este se usara para limpiar el los datos dentro de el y pintar nueva data desde el controlador
  4. Por ultimo creamos un Section de Blade, con el nombre «contentPanel», esta sera la sección que usaremos para recargar.

En la plantilla no vimos nada extraño, y en la vista que recargara el usuario pues tampoco sera muy distinta.

@extends('welcome')
@section('contentPanel')
    <div class="row">

    @foreach($images as $image)
            <div class="col-xs-6 col-md-3">
                <a href="#" class="thumbnail deleteImage" data-id="{{$image->id}}">
                    <img  src="{{$image->imagesUrl}}"  style="height: 180px; width: 100%; display: block;">
                </a>
            </div>

    @endforeach
    </div>
@endsection

Expliquemos esto paso a paso:

  1. Extendemos de la plantilla welcome, para tomar todas sus caracteristicas.
  2. Adherimos el Sections contentPanel, para identificar que lo que esta dentro sera lo único que se recargara en pantalla.
  3. Dentro usamos los Thumbnail como se hace en este artículo y cada uno tiene una clase extra llamada deleteImage, esto con el fin de que cada vez que se haga click sobre una imagen la elimine.

Ahora trabajemos sobre el controlador, ejecutamos en la consola lo siguiente:

php artisan make:controller ImageController

Esto creará el controlador ImageController con todo el CRUD de los metodos del controlador, para este articulo solo usaremos, Index, Store y Destroy.

Detallaremos solo el método index, pues Store y Destroy no tiene nada de distinto a lo que vimos en el Curso de Laravel 5 para agregar y eliminar.

public function index(Request $request){
        $image = Image::all();
        $view = View::make('renderSections')->with('images',$image);
        if($request->ajax()){
            $sections = $view->renderSections();
            return Response::json($sections['contentPanel']); 
        }else return $view;
}

Linea a linea vemos lo siguiente:

  1. Asignamos a la variable $image de todos los datos que están en modelo Image.
  2. A la variable $view, le asignamos la vista y le pasamos las imagenes que que se pintaran en pantalla. Lo hacemos como variable para poder usar el método renderSections()
  3. Preguntamos si la solicitud es de tipo AJAX, esto con el fin de identificar si se quiere recargar solo una seccion de la plantilla.
  4. A la variable $sections le asignamos la vista con el método renderSections, aquí es donde sucede todo.
  5. Retornamos como json a $sections[‘contentPanel’], Si solo se retornara $sections estariamos recargando toda la plantilla y solo queremos una seccion, para este caso nuestro seccion es ‘contentPanel’
  6. Si la solicitud no es AJAX, retornamos las vista.

Para terminar con la parte de Laravel tenemos la modificacion del archivo Routes.php en nuestra aplicacion, el cual termina con esta estructura. No hay necesidad de detallarlo mucho.

Route::get('/', 'ImageController@index');
Route::post('CreateImage','ImageController@store');
Route::resource('images','ImageController');

Dejamos atras el codigo php y comenzamos con la etapa final, jQuery AJAX y el manejo de archivos Json.

Solo son dos funciones,  ajaxRenderSection y ajaxPost. Detallemos la primera, pues gracias a esa función ocurre la recarga.  

function ajaxRenderSection(url) {
        $.ajax({
            type: 'GET',
            url: url,
            dataType: 'json',
            success: function (data) {
                $('#principalPanel').empty().append($(data)); 
            },
            error: function (data) {
                var errors = data.responseJSON;
                if (errors) {
                    $.each(errors, function (i) {
                        console.log(errors[i]);
                    });
                }
            }
        });
    }
  1. La función solo tiene como parametros el url donde se realizara la solicitud, pues los demás datos los conocemos.
  2. Cuando la respuesta del AJAX sea Success, borramos todo el div que engloba a la Seccion ContentPanel de Blade, y luego pintamos dentro de el toda la data que estamos recibiendo en formato Json .
  3. Si la respuesta contiene errores, simplemente los mostramos con un console.log().

La segunda función es ajaxPost, como referencia a los métodos Store y Destroy del ImageController.

 $.fn.ajaxPost = function(url,method,sectionToRender) {
        $.ajax({
            type: method,
            url: url,
            dataType: 'json',
            success: function (data) {
                ajaxRenderSection(sectionToRender)
            },
            error: function (data) {
                var errors = data.responseJSON;
                if (errors) {
                    $.each(errors, function (i) {
                        console.log(errors[i]);
                    });
                }
            }
        });
    }
  1. Esta función se maneja con tres parámetros. la url donde haremos la solicitud, method que identifica el tipo de método se la solicitud y sectionToRender que no es mas que la url que toma la función ajaxRenderSenction
  2. Si la respuesta es Success, vamos ejecutar la función ajaxRenderSection con el parámetro de sectionToRender.

Por ultimo tenemos los eventos que ejecutaran esas funciones, para este caso son dos:

  1. Cuando queremos agregar con el botón en la parte superior derecha.
  2. Cuando queremos eliminar una foto, haciendo click sobre ella.
    $(document).on('click','.addImage',function(event){
        $(this).ajaxPost('CreateImage','POST','/');
    })

    $(document).on('click','.deleteImage',function(event){
        var id = $(this).attr('data-id');
        $(this).ajaxPost('images/'+id,'DELETE','/');
    });

Para verificar que los AJAX se están ejecutando de la forma correcta, nos pasamos a la consola en nuestro navegador, para este articulo usamos Chrome.

Aquí vemos un ejemplo eliminando una imagen.

Delete

Y ahora vemos a respuesta del json.

Json

Bien, con esto terminamos este artículo, que tal vez sea algo extenso pero se quiso hacer lo más explícito posible, acá esta el repositorio  para cualquier duda y bueno también pueden dejar comentarios o preguntas.

Happy Coding!

Publicaciones recomendadas:

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Como generar CRUD en Laravel 5 con Laravel API Generator Lección siguiente Aprende a integrar Ckeditor en Laravel con Blade