Nette ajax – Naja

Načítání obsahu webových stránek bez nutnosti obnovení stránky prostřednictvím AJAXového volání je dnes běžnou praxí.

Zavést toto funkčnost web postaveném na Nette frameworku, je velice jednoduché a rychlé. Ukážeme si jak na to s ajaxovou knihovnou s názvem Naja. Pokud děláte úplně nový projekt, doporučuji Nette 3.0, zapomeňte na nette.ajax.js ale rovnou použijte Naju. Nette,ajax.js je již “hotový” a dál se nevyvijí. Naja je jeho nástupce.

Instalace a zprovoznění Naja knihovny

npm install naja –save-dev

Pro sloučení všech js souborů a jejich minifikaci používám Gulp. V Gulp tasku přidáme Naja.js do našeho jednoho velkého minifikovaného main.min.js souboru:

var uglify = require('gulp-uglify-es').default;
 //…..
 gulp.task('jsMain', done => {
     gulp
         .src(['node_modules/jquery/dist/jquery.min.js',
             'node_modules/popper.js/dist/umd/popper.min.js',
             'node_modules/bootstrap/dist/js/bootstrap.min.js',
             'node_modules/tether/dist/js/tether.min.js',
             'node_modules/naja/dist/Naja.js',
             'venor/nette/forms/src/assets/netteForms.min.js',
             'src/js/main.js'], {allowEmpty: true})
         .pipe(uglify({
             mangle: false,//disable rename variables and functions
         }))
         .pipe(concat('main.min.js'))
         .pipe(gulp.dest('www/js'));
 done();
 });

TIP: je potřeba použít knihovnu gulp-uglify-es ( gulp-uglify nestačí)

npm gulp-uglify-es --save-dev

Pak jen jednoduše tento 1 minifikovaný JS vložíme do šablony:

<script src="{$basePath}/js/main.min.js"></script>

Do souboru /src/js/main.js (který se také přidává do main.min.js přidáme tento kód pro inicializaci Naji):

document.addEventListener(
     'DOMContentLoaded',
     () => {
         naja.initialize();
     }
);

A máme hotovo. Nyní jen přidáme class=”ajax” prvků, které chceme mít ajaxově, stejně jako u Nette.ajax.js

Demo signálu

Po kliknutí na tlačítko aktualizujeme ajaxem snippet, ve kterém se překreslí aktuální datum. Jednoduché 🙂

Presenter:

<?php
 declare(strict_types=1);
 namespace App\FrontModule\Presenters;
 use App;
 use Nette\Utils\DateTime;
 class HomepagePresenter extends BasePresenter
 {
    private $dateTime;
 public function handleActualiseDateTime()
    {
       $this->dateTime = new DateTime();
       if ($this->isAjax()) {
          $this->redrawControl('dateTimeSnippet');
       }
    }
 public function renderDefault(): void
    {
       if ($this->dateTime === null) {
          $this->dateTime = new DateTime();
       }
       $this->template->dateTime = $this->dateTime;
    }
 }

Šablona:

<div class="col-12">
   <hr/>
   {snippet dateTimeSnippet}
      {$dateTime|date:'j. n. Y H:i:s'}
   {/snippet}
   <a n:href="actualiseDateTime!" class="ajax">AKTUALIZOVAT</a>
</div>

Grunt + Bower: Ajax v Nette

Mám projekt v Nette ve kterém potřebuji rozjet Ajax. Na projektu mám již připraven Grunt (jak nainstalovat Grunt) a Bower (slibuji to dlouho ale o tom zase někdy příště).

Pro Ajax v Nette doporučuji nette.ajax.js (od Vojtěcha Dobeše). Nette.ajax.js samozřejmě nainstalujeme přes Bower:

bower install nette.ajax.js --save-dev

Pro automatizaci používám Grunt (jak nainstalovat Grunt), do kterého existuje nepřeberné množství doplňků.

Pro spojení více .js souborů do jednoho používám doplněk grunt-contrib-concat kde mám vytvořený následující task:

        concat: {
            js: {
                src: ['bower_components/jquery/dist/jquery.min.js',
                    'bower_components/nette.ajax.js/nette.ajax.js',
                    'vendor/nette/forms/src/assets/netteForms.js',
                    'www/js/main.js'],
                dest: 'www/js/compiled.js',
                nonull: true
            }
        },

V souboru compiled.js máme potřebné js soubory. Můžeme se pustit do další fáze.

Nette + Ajax

Ajaxace již funkčních částí je v Nette velice jednoduchá. Nyní mám vytvořený formulář který odesílá data. Po odeslání formuláře se znovu načte kompletně celá stránka. Tento skript vylepšíme, aby se po odeslání formuláře nemusela načítat komplet celá stránka ale pouze odeslaný formulář (u mne to je formulář s rezervací).

Pojďme si připravit inicializace knihovny nette.ajax.js do souboru main.js:

$(function () {
    $.nette.init();// And you fly... 
});

Mému formuláři stačí přidat class ajax:

$form = new Form;
$form->getElementPrototype()->class( 'ajax' );

V presenteru nyní máme funkci isAjax, která nám vrací TRUE pokud se jedná o Ajaxový požadavek.

Po odeslání formuláře se přesvědčíme zda byl odeslán Ajaxem:

    public function selectWorkshopFormSucceeded( $form, $values )
    {
        if ($this->isAjax()) {
            echo "fomulář odeslán AJAXem";
        }
        else
        {
            echo "fomulář nebyl odeslán AJAXem";
        }
        exit();
    }

V latte můžeme jednotlivé bloky zabalit do snippetu a nechat překreslit pouze tento snippet:

{snippet workshop}
   {control selectWorkshopForm}
{/snippet}
    public function selectWorkshopFormSucceeded( $form, $values )
    {
        if ($this->isAjax()) {
            $this->redrawControl( 'workshop' );//znovu vykresli snippet workshop
        }
        else
        {
            $this->redirect( 'this' );//znovu vykresli celou stranku
        }
    }

Proto Nette miluju!