Lekce 8 - Jednoduchý redakční systém v AngularJS - Administrace
V minulé lekci, Jednoduchý redakční systém v AngularJS - Výpis článku, jsme vytvořili základní strukturu pro výpis článků.
Dnes si do administrace článků přidáme kontrolery i šablony pro jejich vytváření, editaci a mazání.
Externí JS knihovny
Jelikož AngularJS je poměrně robustní framework, který přebírá kontrolu nad většinou javascriptového dění na celé stránce, není úplně lehké ho propojit s některými knihovnami. Naštěstí pro ty populární existují již připravené moduly, které vše usnadní. Příkladem je třeba TinyMCE, které jsem se rozhodl použít pro pohodlnou editaci HTML obsahu článků.
assets/lib/js/angular-ui-tinymce.min.js
Pro práci s ním je třeba kromě samotné knihovny vložit do projektu i modul - AngularUI wrapper for TinyMCE, který slouží jako obal pro využití této knihovny v prostředí AngularJS. Tento modul si tedy stáhněte a vložte do složky pro externí knihovny naší aplikace.
app/cms.module.js
Dále ho ještě nezapomeneme klasicky zavést jako modul naší aplikace:
'use strict'; // Deklarace modulu aplikace. var app = angular.module('cms', ['ngRoute', 'ngResource', 'ngMockE2E', 'ngSanitize', 'ngMessages', 'ui.tinymce']);
Kontrolery
Jelikož modelovou vrstvu v podobě simulovaného nebo vlastního plnohodnotného API máme již nachystanou z minulé lekce, začneme rovnou od kontrolerů.
app/controllers/article-list.controller.js
V AngularJS máme standardně k jednomu kontroleru jednu šablonu, kontroler tedy většinou reprezentuje jednu samostatnou stránku. Proto si pro výpis seznamu článků, jako samostatnou stránku, vytvoříme vlastní šablonu a kontroler, který bude vypadat následovně:
'use strict'; /** Zpracovává vykreslování seznamu článků. */ app.controller('ArticleListController', function ($rootScope, $scope, Articles) { $rootScope.title = 'Výpis článků'; $rootScope.description = 'Výpis všech článků.'; this.articles = Articles.query(); /** * Odstraní článek. * @param {int} index - Index článku v poli článků. */ this.remove = function (index) { // Odstraní článek pomocí API. Articles.delete({url: this.articles[index].url}, (function () { // Odstraní článek z aktuálního seznamu článků. this.articles.splice(index, 1); }).bind(this), function (error) { console.error(error); }); }; });
Zde se toho moc nového neudálo, pouze vidíme způsob načtení článku z API a definici metody kontroleru pro jejich smazání, jak z lokálně načtených dat, tak opět i z API.
app/controllers/article-editor.controller.js
Další na řadě bude kontroler reprezentující stránku editoru článků:
'use strict'; /** Zpracovává vykreslování editoru článků. */ app.controller('ArticleEditorController', function ($routeParams, $rootScope, $scope, $location, Articles) { $rootScope.title = 'Editor'; $rootScope.description = 'Editor článků.'; // Počáteční hodnota / základ pro nový článek. $scope.article = { url: '', title: '', content: '', description: '' }; var url = $routeParams.url; // Získání URL editovaného článku. // Načtení dat editovaného článku z API, pokud byla zadána jeho URL. if (url) Articles.get({url: url}, function (article) { $scope.article = article; }, function (error) { console.error(error); }); // Nastavení pro TinyMCE. this.tinymceOptions = { selector: '#editorForm-content', plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen', 'insertdatetime media table contextmenu paste' ], toolbar: 'insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image', entities: '160,nbsp', entity_encoding: 'raw' }; /** Uloží článek. */ this.save = function () { Articles.save($scope.article, function (article, headers) { $location.path(headers('Location')); // Přesměrování na zobrazení článku. }, function (error) { console.error(error); }); }; });
Zde si nejdříve připravíme datovou kostru pro nový článek, kterou přes API doplníme daty článku existujícího, v případě že se jedná o editaci. To poznáme jednoduše podle zadané URL adresy. Následuje místní nastavení pro TinyMCE a na konci zde pak ještě přidáváme metodu pro uložení článku do API.
Šablony
Nyní se podíváme na šablony k jednotlivým kontrolerům.
app/templates/article-list.html
Začneme šablonou pro výpis článků:
<table> <tr ng-repeat="(index, article) in articleList.articles"> <td> <h2><a href="#!{{article.url}}">{{article.title}}</a></h2> {{article.description}} <br/> <a href="#!editor/{{article.url}}">Editovat</a> <a href ng-click="articleList.remove(index)">Odstranit</a> </td> </tr> </table>
Zde jsou hned dvě novinky. Za prvé je vidět práce s polem dat v rámci
šablony, kde AngularJS vezme v cyklu ng-repeat
jednotlivé
články a ke každému vytvoří příslušný řádek
(<tr>
) HTML tabulky. Za druhé je zde ukázka volání metody
kontroleru pro smazání článku při kliknutí na odkaz.
app/templates/article-editor.html
Nyní šablona pro editor článků:
<!-- AngularJS formulář s mapováním dat i vlastní validací (výchozí validace v prohlížeči vypnuta). --> <form name="editorForm" ng-submit="articleEditor.save()" novalidate> <!-- TITLE --> <div class="form-group"> <label for="editorForm-title">Titulek</label> <input id="editorForm-title" type="text" name="title" ng-model="article.title" required> <!-- Definice chybových zpráv. --> <div ng-messages="editorForm.title.$error" ng-show="editorForm.title.$touched"> <p ng-message="required">Titulek článku nemůže být prázdný!</p> </div> </div> <!-- URL --> <div class="form-group"> <label for="editorForm-url">URL</label> <input id="editorForm-url" type="text" name="url" ng-model="article.url" required> <div ng-messages="editorForm.url.$error" ng-show="editorForm.url.$touched"> <p ng-message="required">URL článku nemůže být prázdná!</p> </div> </div> <!-- DESCRIPTION --> <div class="form-group"> <label for="editorForm-description">Popisek</label> <input id="editorForm-description" type="text" name="description" ng-model="article.description" required> <div ng-messages="editorForm.description.$error" ng-show="editorForm.description.$touched"> <p ng-message="required">Popisek článku nemůže být prázdný!</p> </div> </div> <!-- CONTENT --> <div class="form-group"> <label for="editorForm-content">Obsah</label> <textarea id="editorForm-content" name="content" ui-tinymce="articleEditor.tinymceOptions" ng-model="article.content" required></textarea> <div ng-messages="editorForm.content.$error" ng-show="editorForm.content.$touched"> <p ng-message="required">Obsah článku nemůže být prázdný!</p> </div> </div> <!-- SUBMIT BUTTON --> <button type="submit" ng-disabled="editorForm.$invalid">Uložit článek</button> </form>
Formulář v AngularJS jsme již viděli v prvním projektu u kalkulačky, ovšem zde je rozšířen o další validační prvky a ukazuje se zde opravdová síla frameworku.
U každého elementu formuláře si můžete povšimnout způsobu definice vlastních validačních pravidel a chybových zpráv, které se zobrazí při jejich porušení. Také formulář nelze odeslat, dokud není celý validní.
Pole pro obsah zde má navíc ještě direktivu pro aktivaci již výše zmíněného TinyMCE a předání jeho příslušné konfigurace.
index.html
Lekci zakončíme klasicky úpravou a rozšířením hlavního souboru naší aplikace. Nebudu sem už vypisovat znovu celou šablonu, ale pouze změny:
... <nav> <ul> <li><a href="#!uvod">Úvod</a></li> <li><a href="#!seznam-clanku">Seznam článků</a></li> <li><a href>Kontakt</a></li> </ul> </nav> ... <!-- TinyMCE a jeho integrace pro AngularJS --> <script type="text/javascript" src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script> <script type="text/javascript" src="assets/lib/js/angular-ui-tinymce.min.js"></script> ... <!-- Kontrolery. --> <script src="app/controllers/article.controller.js"></script> <script src="app/controllers/article-list.controller.js"></script> <script src="app/controllers/article-editor.controller.js"></script> ...
Routování
app/cms.routes.js
Na závěr přidáme nová routovací pravidla:
'use strict'; /** Definice routovacích pravidel naší aplikace. */ app.config(function ($routeProvider) { var templatePath = 'app/templates/'; $routeProvider .when('/seznam-clanku', { templateUrl: templatePath + 'article-list.html', controller: 'ArticleListController', controllerAs: 'articleList' }) .when('/editor/:url?', { templateUrl: templatePath + 'article-editor.html', controller: 'ArticleEditorController', controllerAs: 'articleEditor' }) .when('/:url?', { templateUrl: templatePath + 'article.html', controller: 'ArticleController', controllerAs: 'article' }) .otherwise({ redirectTo: '/' }); });
Jak vidíte, zde se nám naše nové kontrolery a šablony krásně propojí dohromady pod URL adresami, které jsem se rozhodl zachovat v češtině.
Nyní se již můžete podívat na výsledek, zkusit si vypsat seznam
článků a klidně je i nějak editovat.
V příští lekci, Jednoduchý redakční systém v AngularJS - Kontaktní formulář, si do našeho redakčního systému přidáme kontaktní formulář.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 34x (26.41 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript