Rechercher dans ce blog

dimanche 3 novembre 2013

Visibilité


Il arrive fréquemment qu'on veuille masquer ou au contraire afficher un élément d'une page selon le contexte. On le fait en général en CSS avec :
display:none
pour rendre invisible. C'est ce que fait AngularJS avec les directives ngShow et ngHide. Voici un exemple (JSFiddle) :
<div ng-app>
  Cochez pour voir la suite : 
  <input type="checkbox" ng-model="voir"><br/>
  <p ng-show="voir">Je suis la suite !</p>
  Cochez pour ne pas voir la suite : 
  <input type="checkbox" ng-model="cacher"><br/>
  <p ng-hide="cacher">Je suis la suite !</p> 
</div>
J'ai créé un lien entre les cases à cocher et les paragraphes avec la directive ngModel. Ainsi lorsque la valeur la case change elle est répercutée sur la valeur de la classe dans les paragraphes. Au départ on a ce code qui est généré :
<div class="ng-scope" ng-app="">
  Cochez pour voir la suite : 
  <input class="ng-pristine ng-valid" ng-model="voir" 
type="checkbox"><br>
  <p style="display: none;" ng-show="voir">Je suis la suite !</p>
  Cochez pour ne pas voir la suite : 
  <input class="ng-pristine ng-valid" ng-model="cacher" 
type="checkbox"><br>
  <p ng-hide="cacher">Je suis la suite !</p> 
</div>
On se rend compte qu'une règle de style display: none a été ajoutée pour le premier paragraphe qui doit être invisible. Si vous changez la valeur des coches vous verrez le style s'adapter automatiquement.

Classes


La directive ngClass permet de déclarer de façon dynamique des classes pour des éléments HTML. Il suffit d'utliser une liaison pour la valeur de la classe en utilisant une expression. Voici un exemple (JSFiddle) :
<div ng-app ng-controller="controleur">
  <button ng-click="voirDanger()">Danger</button>
  <button ng-click="voirWarning()">Alerte</button>
  <button ng-click="voirInfo()">Information</button>
  <div ng-class="maClasse">{{message}}</div>
  <script>
    function controleur($scope) {
      $scope.voirDanger = function() {
        $scope.message = 'On est en danger !';
        $scope.maClasse='rouge';
      };
      $scope.voirWarning = function() {
        $scope.message = 'Ce n\'est qu'une alerte.';
        $scope.maClasse='orange';
      };
      $scope.voirInfo = function() {
        $scope.message = 'Une petite information.';
        $scope.maClasse='bleu';
      };
    }
  </script>
</div>
J'ai prévu deux propriétés pour le scope : message qui contient le message à afficher et maClasse qui contient la classe à utiliser pour le message. Le tout est géré par un simple contrôleur qui comporte 3 méthodes, une pour chacun des aspects désirés. Les messages sont déclenchés par des boutons avec la directive ngClick.

Validation de formulaire


La validation d'un formulaire côté client est une tâche qui a été grandement améliorée avec l'arrivée du HTML 5. Mais d'une part il y a encore des navigateurs en service qui ne tiennent pas compte de ces améliorations. D'autre part il arrive souvent qu'on doivent ajouter des fonctionnalités. AngularJS apporte une réponse à ces deux problématiques. Pour la première c'est automatique et même les vieux navigateurs sont assistés pour les nouvelles possibilités du HTML 5. Pour le reste nous allons le voir. Voici l'exemple d'un formulaire d'inscription avec trois champs de saisie obligatoires pour le nom, le prénom et l'adresse Email (JSFiddle) :
<div ng-app>
  <style>
    .ng-invalid { border-color: #B94A48; }
    .rouge { color: red; }
    .vert { color: green; }
  </style>
  <h1>Inscription</h1>
  <form name="ajoutUtilisateur" ng-controller="controleur" 
ng-submit="soumission(ajoutUtilisateur.$valid)">
    <label for="nom">Nom :</label>
    <input type="text" id="nom" placeholder="Votre nom"
ng-model="user.nom" required>
    <label for="nom">Prénom :</label>
    <input type="text" id="prenom" placeholder="Votre prénom"
ng-model="user.prenom" required>
    <label for="email">Email :</label>
    <input type="email" id="email" placeholder="Votre Email" 
ng-model="user.email" required>
    <button type="submit">Envoyer</button>
    <div ng-class="messageClass" ng-show="message">{{message}}
</div>
  </form>
  <script>
    function controleur($scope) {
      $scope.message = '';
      $scope.soumission = function (valid) {
        if(valid) {
          $scope.messageClass='vert';
          $scope.message = 'Merci ' + $scope.user.nom + 
' votre inscription est validée !';
        }
        else {
          $scope.messageClass='rouge';
          $scope.message = 'Désolé mais il y a des 
données non valides !';
        }
      };
    }
  </script>
</div>

Lorsque AngularJS rencontre une balise form il crée un objet FormController. Parmi toutes les propriétés intéressantes de cet objet il y a $valid qui est vraie si tous les contrôles du formulaire ont une valeur correcte. Lors de la soumission du formulaire je transmets donc en paramètre cette valeur au contrôleur qui va effectuer son traitement en fonction d'elle.

Lorsqu'un contrôle n'est pas valide AngularJS lui adjoint la classe ng-invalid, on peut utiliser cette classe pour ajouter du style, comme je l'ai fait ici en prévoyant une règle pour la bordure. AngularJS prévoit ainsi 4 classes :
  • ng-invalid : la valeur n'est pas valide
  • ng-valid : la valeur est valide
  • ng-pristine : l'utilisateur n'a pas encore utilisé ce contrôle
  • ng-dirty : l'utilisateur a déjà utilisé ce contrôle
Evidemment dans un environnement réel il faudrait envoyer ces informations au serveur pour les mémoriser. Nous verrons cet aspect plus tard.

Un petit TP 


On va faire un nouveau point de ce qu'on a vu avec un petit exercice. Le but est de remplir un tableau à partir d'un formulaire. On prévoit deux zones de texte et des boutons radio pour entrer les informations. On veut que les deux zones de texte aient une bordure rouge tant que la valeur n'est pas valide et verte ensuite, et qu'elles soient à saisie obligatoire. On veut aussi un message en cas de soumission avec des champs non valides (mais avec un navigateur qui gère bien le HTML 5 ça ne devrait pas arriver) :

Ajout d'utilisateurs




{{message}}
Utilisateurs
Nom Prénom Rôle
{{utilisateur.nom | uppercase}} {{utilisateur.prenom}} {{utilisateur.role}}

Vous trouverez ma solution dans ce JSFiddle. Vous avez peut-être remarqué que ça ne sert à rien de prévoir un bouton radio checked étant donné qu'avec la liaison de données c'est le scope qui gère tout. Il faut donc judicieusement le renseigner.

Aucun commentaire:

Enregistrer un commentaire