08. Gestion des saisons et épisodes

Nous verrons qu'à ce stade, la gestion des saisons et des épisodes est très simple grâce à Angular. C’est pourquoi, nous en profiterons pour aborder la création d’une directive personnalisée pour afficher les épisodes.

Saisons et épidodes dans la vue

Plutôt qu'un long discours, regardons les modifications à apporter à la vue d’édition :

<form name="showForm" ng-submit="saveShow(showForm)" novalidate>
    <hr />
    <h2>Show properties</h2>

    <div class="form-horizontal">

        <!-- [formulaire titre et année] -->

        <h2>
            Seasons
            <!-- bouton pour ajouter/enlever une saison -->
            <buton class="btn btn-sm btn-success" ng-click="editCtrl.addSeason()">Add</buton>
            <buton class="btn btn-sm btn-danger" ng-click="editCtrl.removeSeason()">Remove</buton> 
        </h2>

        <blockquote>
            <!-- boucle sur les saisons -->
            <div ng-repeat="season in editCtrl.show.seasons">
                <h3>
                    Season: {{season.number}}
                    <!-- bouton pour ajouter/enlever un épisode -->
                    <buton class="btn btn-sm btn-default" ng-click="editCtrl.addEpisode(season)"><span class="glyphicon glyphicon-plus"></span></buton>
                    <buton class="btn btn-sm btn-default" ng-click="editCtrl.removeEpisode(season)"><span class="glyphicon glyphicon-minus"></span></buton> 
                </h3>
                <!-- boucle sur les épisodes qui utilise la directive 'episode' -->
                <div ng-repeat="episode in season.episodes" episode="episode"></div>
            </div>
        </blockquote>

        <!-- [formulaire bouton de sauvegarde] -->
    </div>
</form>

Enrichissement du controller

Ajoutons maintenant dans le controller les évènements appelés depuis la vue:

// src/modules/show/controllers/ShowEditController.js
'use strict';

app.controller('ShowEditController', ['$location', '$routeParams', 'showService', function($location, $routeParams, showService) {
        var vm = this;

        // [...]

        vm.addSeason = function () {
            if (!vm.show.seasons) {
                vm.show.seasons = [{ number: 1 }];
            } else {
                vm.show.seasons.push({ number: vm.show.seasons.length + 1 });
            }
        };

        vm.removeSeason = function () {
            if (vm.show.seasons && vm.show.seasons.length) {
                vm.show.seasons.pop();
            }
        };

        vm.addEpisode = function (season) {
            if (!season.episodes) {
                season.episodes = [{ number: 1 }];
            } else {
                season.episodes.push({ number: season.episodes.length + 1 });
            }
        }

        vm.removeEpisode = function (season) {
            if (season.episodes && season.episodes.length) {
                season.episodes.pop();
            }
        }
    }
]);

Directive personnalisée

Pour terminer, nous allons créer une directive permettant d'afficher le détail d'un épisode. Tout d'abord créons un dossier directive dans le module show et ajoutons un fichier episode-directive.html qui sera la partie vue de notre directive.

<!-- src/modules/show/directives/episode-directive.html -->
<div style="width:100px;display:inline-block;margin-right:5px" 
    class="alert text-center" 
    ng-class="{'alert-success' : episode.view, 'alert-danger' : !episode.view}" 
    ng-click="toogleView()">
    {{episode.number}}
</div>

En plus de la propriété number, l'objet épisode contient une propriété view qui indique si l'épisode a été visionné ou non. Grâce à la directive ng-class nous afficherons soit du rouge soit du vert en fonction de si l'épisode a été regardé. Au click sur l'épisode, par l'intermédiaire de la fonction toogleView() nous changerons cette propriété.

Créons maintenant la directive dans un nouveau fichier JS episodeDirective.js. Pour cela, il convient d' utiliser la méthode directive() qui prend en paramètre un nom et une fonction qui retourne un objet avec plusieurs propriétés spécifiques.

// src/modules/show/directives/episodeDirective.js
'use strict';

app.directive('episode', function () {

    return {
        templateUrl: 'modules/show/directives/episode-directive.html',
        restrict: 'A',
        replace : true,
        scope: {
            episode: '='
        },
        link: function (scope, el, attrs) {
            scope.toogleView = function () {
                scope.episode.view = !scope.episode.view;
            };
        }
    };

});

Les propriétés les plus communes pour une directive sont: