Comment faire une liste et un contrôle de commutateur de vue de grille qui se charge en partiels dans AngularJS?

Je suis nouveau sur AngularJS et j'ai été incapable de trouver des tutoriels spécifiques d'une liste et des boutons de basculement de la vue de la grille qui se chargent en deux partitions HTML différentes. Lisez officiel ng-include , ng-switch documents officiels et recherché SO. Malheureusement, nous ne voulons pas utiliser UI-routeur .

Est-ce que le chargement en deux partiels ( list.html et grid.html ) est la manière angulaire correcte de coder cela?

Vue de grilleVue de liste

L'aide la plus pertinente que j'ai trouvée est la suivante:

1. http://tutorialzine.com/2013/08/learn-angularjs-5-examples (Exemple n ° 5)

Il y a eu un commentaire perspicace sur l'exemple n ° 5

De beaux exemples simples – bien fait. Le dernier exemple qui bascule entre les vues de la grille et de la liste n'est pas très efficace puisqu'il crée les deux options et les affiche / les masque. Une approche plus simple / meilleure serait d'utiliser un seul ul avec répéteur et ng-switch, puis en activant les éléments de la liste alternative en utilisant ng-switch-case. – Johan

2. http://www.adobe.com/devnet/html5/articles/getting-started-with-angularjs.html

3. Créez une seule vue html pour plusieurs vues partielles dans angularjs

4. Conditionnalité ng-inclure dans angularjs


Mon code HTML

  <div class="col-xs-6" ng-controller="ToggleDisplayCtrl"> <div class="btn-group select-format-container" ng-switch on="selected"> <button ng-switch-when="true" ng-click="toggleGrid()" type="button" class="btn btn-primary" ng-model="formatChoice" ng-disabled="">grid</button> <button ng-switch-when="false" ng-click="toggleList()" type="button" class="btn btn-primary" ng-model="formatChoice" ng-disabled="">list</button> </div> <div ng-include src="formatChoice.url" scope="" onload=""></div> </div><!-- col-xs-6 END ToggleDisplayCtrl--> 

Mon code de directive

 'use strict'; var app = angular.module('tempApp'); app.controller('ToggleDisplayCtrl', function($scope) { $scope.formatChoices = [ { name: 'grid', url: 'partials/grid.html'}, { name: 'list', url: 'partials/list.html'} ]; $scope.selected = true; $scope.toggleGrid = function() { if(selected) { return "partials/grid.html"; } return "main.html"; }; $scope.toggleList = function() { if(selected) { return "partials/list.html"; } return "main.html"; }; }); 

Vous devez définir la propriété de portée du contrôleur d'application qui tiendra l'URL du modèle pour ng-include et lier cette propriété à la portée de votre directive. Assurez-vous d'utiliser une portée isolée dans votre directive afin d'éviter les effets secondaires tout en modifiant la portée de la directive. Voici un exemple de le faire (voir les commentaires dans le code):

JavaScript

 angular.module('app',['ngRoute']). config(['$routeProvider', function($routeProvider){ $routeProvider. when('/main', { controller: 'appController', templateUrl: 'main.html' }). otherwise({ redirectTo: '/main' }); }]). controller('appController', ['$scope', function($scope){ $scope.view = 'list.html'; // <- default template used for ng-include $scope.data = [{ text: '1' }, { text: '2' }, { text: '3' }, { text: '4' }, { text: '5' }, { text: '6' }]; }]). directive('appView', function() { return { scope: { view: '=appView' // <= link view property of directive's scope to some property in the parent scope (scope of appController) specified in app-view attribute of root element of directive }, replace: true, template: '<nav class="navbar navbar-default">' + '<div class="container">' + '<ul class="nav navbar-nav navbar-right">' + '<li ng-repeat="v in views" ng-bind="v.name" ng-class="v.icon" ng-click="switchView(v)"></li>' + '</ul>' + '</div>' + '</nav>', link: function(scope, el, attr) { scope.views = [{ name: 'List', template: 'list.html', icon: 'btn btn-default navbar-btn glyphicon glyphicon-th-list' }, { name: 'Grid', template: 'grid.html', icon: 'btn btn-default navbar-btn glyphicon glyphicon-th' }]; }, controller: ['$scope', function($scope){ $scope.switchView = function(view) { $scope.view = view.template; // <- modify parent scope view } }] } }); 

Page principale de l'application (index.html)

 <html ng-app="app"> ... <body ng-view=""></body> </html> 

Modèle d'itinéraire (main.html)

 <header app-view="view"></header> <section ng-include="view"></section> 

Modèle de liste de liste (list.html)

 <div class="container"> <div class="row"> <div class="col-md-12 col-sm-12 panel panel-default" ng-repeat="item in data"> <div class="panel-body">{{item.text}}</div> </div> </div> </div> 

Modèle de vue en grille (grid.html)

 <div class="container"> <div class="row"> <div class="col-md-4 col-sm-6 panel panel-default" ng-repeat="item in data"> <div class="panel-body">{{item.text}}</div> </div> </div> </div> 

Plunker: http://plnkr.co/edit/uWw7NuPG0I161mHXZg2r?p=preview

Bonus: la grille est réactive, il suffit de jouer un peu avec une taille de fenêtre

Une autre option:

Comme vous l'avez probablement remarqué, grid.html et list.html sont très similaires, alors, si vous avez seulement ces deux options, vous pouvez décider de ne pas utiliser ng-include avec des vues séparées, mais placez la vue de contenu directement dans le modèle de votre itinéraire Et simplement changer les classes utilisées dans les panneaux en utilisant la directive ng-class qui peut changer de classe lorsque la vue est modifiée.

Modèle d'itinéraire (main.html)

 <header app-view="view"></header> <section> <div class="container"> <div class="row"> <div ng-class="{'col-md-4': view === 'grid.html', 'col-md-12': view === 'list.html', 'panel':true, 'panel-default':true}" ng-repeat="item in data"> <div class="panel-body">{{item.text}}</div> </div> </div> </div> </section> 

Voici un JSBin de travail simple: http://jsbin.com/jomiquqi/1/edit

La directive ng-include prend une variable pour inclure le modèle. Donc, pour mettre à jour votre code pour le faire fonctionner, votre méthode toggleGrid() ne devrait pas renvoyer quelque chose, il devrait être de définir une variable sur la portée que vous passez à ng-include comme dans mon exemple.

Fondamentalement, ce que vous devez faire est de mettre une liste et une même grille sur la même page et d'afficher une à la fois, en basculant entre elles (en changeant la classe css) avec le bouton de commutation. Je vais discuter de l'exemple n ° 5 ici:

Première variable de mise en page dans la portée

 $scope.layout = 'grid'; 

Voici les boutons de commutateur

 <!-- On click change "$scope.layout = list" and if layout=='list' add class 'active' to self--> <a href="#" class="list-icon" ng-class="{active: layout == 'list'}" ng-click="layout = 'list'"></a> <!-- On click change "$scope.layout = grid" and if layout=='grid' add class 'active' to self--> <a href="#" class="grid-icon" ng-class="{active: layout == 'grid'}" ng-click="layout = 'grid'"></a> 

Ce sont les blocs de la grille et de la liste.

 <!-- Layout=='grid' if layout parameter is grid than show this block --> <ul ng-show="layout == 'grid'" class="grid">...</ul> <!-- Layout=='list' if layout parameter is list than show this block --> <ul ng-show="layout == 'list'" class="list">...</ul> 

Css qui fait la liste et la mise en page

 /*------------------------- List layout --------------------------*/ ul.list{ list-style: none; width: 500px; margin: 0 auto; text-align: left; } ul.list li{ border-bottom: 1px solid #ddd; padding: 10px; overflow: hidden; } ul.list li img{ width:120px; height:120px; float:left; border:none; } ul.list li p{ margin-left: 135px; font-weight: bold; color:#6e7a7f; } /*------------------------- Grid layout --------------------------*/ ul.grid{ list-style: none; width: 570px; margin: 0 auto; text-align: left; } ul.grid li{ padding: 2px; float:left; } ul.grid li img{ width:280px; height:280px; display:block; border:none; } 

La façon la plus simple de le faire est:

 <div class = "bar"> <h1>Contacts</h1> <a href="#" class="list-icon" ng-class="{active: layout == 'list'}" ng-click="layout = 'list'"></a> <a href="#" class="grid-icon" ng-class="{active: layout == 'grid'}" ng-click="layout = 'grid'"></a> </div> <div ng-show="layout == 'list'" class="list"> //Add your list page here <div ng-show="layout == 'grid'" class="grid"> //Add your grid page here 

CSS:

 /* Contacts bar with toggle switches */ .bar{ background-color: #5c9bb7; background-size: 100% 100%; box-shadow: 0 1px 1px #ccc; border-radius: 2px; height: 100px; padding: 10px; position: relative; text-align: right; line-height: 1; } .bar a{ background:#4987a1 center center no-repeat; width:32px; height:32px; display:inline-block; text-decoration:none !important; margin-right:5px; border-radius:2px; } .bar a.active{ background-color:#c14694; } .bar a.list-icon{ background- image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7h1bLqAAAAWUlEQVR42mL8////BwYGBn4GCACxBRlIAIxAA/4jaXoPEkMyjJ+A/g9MDJQBRhYg8RFqMwg8RJIUINYLFDmBUi+ADQAF1n8ofk9yIAy6WPg4GgtDMRYAAgwAdLYwLAoIwPgAAAAASUVORK5CYII=); } .bar a.grid-icon{ background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4MjPshAAAAXklEQVR42mL4////h/8I8B6IGaCYKHFGEMnAwCDIAAHvgZgRyiZKnImBQsACxB+hNoDAQyQ5osQZIT4gH1DsBZABH6AB8x/JaQzEig++WPiII7Rxio/GwmCIBYAAAwAwVIzMp1R0aQAAAABJRU5ErkJggg==); } /*------------------------- List layout --------------------------*/ ul.list{ list-style: none; width: 500px; margin: 0 auto; text-align: left; } ul.list li{ border-bottom: 1px solid #ddd; padding: 10px; overflow: hidden; } ul.list li img{ width:120px; height:120px; float:left; border:none; } ul.list li p{ margin-left: 135px; font-weight: bold; color:#6e7a7f; } /*------------------------- Grid layout --------------------------*/ ul.grid{ list-style: none; width: 570px; margin: 0 auto; text-align: left; } ul.grid li{ padding: 2px; float:left; } ul.grid li img{ width:280px; height:280px; display:block; border:none; } l' /* Contacts bar with toggle switches */ .bar{ background-color: #5c9bb7; background-size: 100% 100%; box-shadow: 0 1px 1px #ccc; border-radius: 2px; height: 100px; padding: 10px; position: relative; text-align: right; line-height: 1; } .bar a{ background:#4987a1 center center no-repeat; width:32px; height:32px; display:inline-block; text-decoration:none !important; margin-right:5px; border-radius:2px; } .bar a.active{ background-color:#c14694; } .bar a.list-icon{ background- image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7h1bLqAAAAWUlEQVR42mL8////BwYGBn4GCACxBRlIAIxAA/4jaXoPEkMyjJ+A/g9MDJQBRhYg8RFqMwg8RJIUINYLFDmBUi+ADQAF1n8ofk9yIAy6WPg4GgtDMRYAAgwAdLYwLAoIwPgAAAAASUVORK5CYII=); } .bar a.grid-icon{ background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4MjPshAAAAXklEQVR42mL4////h/8I8B6IGaCYKHFGEMnAwCDIAAHvgZgRyiZKnImBQsACxB+hNoDAQyQ5osQZIT4gH1DsBZABH6AB8x/JaQzEig++WPiII7Rxio/GwmCIBYAAAwAwVIzMp1R0aQAAAABJRU5ErkJggg==); } /*------------------------- List layout --------------------------*/ ul.list{ list-style: none; width: 500px; margin: 0 auto; text-align: left; } ul.list li{ border-bottom: 1px solid #ddd; padding: 10px; overflow: hidden; } ul.list li img{ width:120px; height:120px; float:left; border:none; } ul.list li p{ margin-left: 135px; font-weight: bold; color:#6e7a7f; } /*------------------------- Grid layout --------------------------*/ ul.grid{ list-style: none; width: 570px; margin: 0 auto; text-align: left; } ul.grid li{ padding: 2px; float:left; } ul.grid li img{ width:280px; height:280px; display:block; border:none; } 

Pour une meilleure compréhension de l'action de changement de vitesse pour voir la liste et la vue de la grille: suivez ce lien et j'espère que cela vous sera utile.

Dans cela, nous avons utilisé Jquery, si vous expérimentez à ce sujet. Placez ceci: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>