Commit fdd4dada172a399dc97d9152a61df5a3ce07402d

Authored by Nicolás Guarnieri
Exists in master

Merge branch 'master' into 'master'

Modal de búsqueda de producto con tabla, filtro, paginación y navegación por teclado

See merge request modulos-npm/foca-modal-busqueda-productos!1
1 # Busqueda de productos en modal para Debo Suite 1 # Busqueda de productos en modal para Debo Suite
2 2
3 Para ser utilizado en otro modulo debe iniciarse con este codigo ejemplo: 3 Para ser utilizado en otro modulo debe iniciarse con este codigo ejemplo:
4 <pre> 4 <pre>
5 var modalInstance = $uibModal.open( 5 var modalInstance = $uibModal.open(
6 { 6 {
7 ariaLabelledBy: 'Busqueda de Productos', 7 ariaLabelledBy: 'Busqueda de Productos',
8 templateUrl: 'src/views/modal-busqueda-productos.html', 8 templateUrl: 'src/views/modal-busqueda-productos.html',
9 controller: 'modalBusquedaProductosCtrl', 9 controller: 'modalBusquedaProductosCtrl',
10 size: 'md' 10 size: 'md'
11 } 11 }
12 ); 12 );
13 </pre>
13 </pre>
14
15 Y despues consiguiendo el resultado de esta forma:
16 <pre>
17 modalInstance.result.then(
18 function (producto) {
19 console.info(producto);
20 // variable producto tiene el producto seleccionado en el modal
21 }, function () {
22 // funcion ejecutada cuando se cancela el modal
23 }
24 );
25 </pre>
1 <html ng-app="focaBusquedaProductos"> 1 <html ng-app="focaBusquedaProductos">
2 <head> 2 <head>
3 <meta charset="UTF-8"/> 3 <meta charset="UTF-8"/>
4 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> 4 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
5 5
6 <!--CSS--> 6 <!--CSS-->
7 <link href="node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"/> 7 <link href="node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"/>
8 <link href="node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet"/> 8 <link href="node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet"/>
9 9
10 <!--VENDOR JS--> 10 <!--VENDOR JS-->
11 <script src="node_modules/jquery/dist/jquery.min.js"></script> 11 <script src="node_modules/jquery/dist/jquery.min.js"></script>
12 <script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script> 12 <script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
13 <script src="node_modules/angular/angular.min.js"></script> 13 <script src="node_modules/angular/angular.min.js"></script>
14 <script src="node_modules/ui-bootstrap4/dist/ui-bootstrap-tpls.js"></script> 14 <script src="node_modules/ui-bootstrap4/dist/ui-bootstrap-tpls.js"></script>
15 <script src="node_modules/foca-directivas/dist/foca-directivas.min.js"></script>
15 16
16 <!-- BUILD --> 17 <!-- BUILD -->
17 <script src="src/js/app.js"></script> 18 <script src="src/js/app.js"></script>
18 <script src="src/js/controller.js"></script> 19 <script src="src/js/controller.js"></script>
20 <script src="src/js/service.js"></script>
19 21
20 <!-- /BUILD --> 22 <!-- /BUILD -->
21 23
22 <!-- CONFIG PARA DEVELOP --> 24 <!-- CONFIG PARA DEVELOP -->
23 <script src="src/etc/develop.js"></script> 25 <script src="src/etc/develop.js"></script>
24 <script type="text/javascript"> 26 <script type="text/javascript">
25 angular.module('focaBusquedaProductos') 27 angular.module('focaBusquedaProductos')
26 .controller('controller', ['$uibModal', function($uibModal) { 28 .controller('controller', [
27 var modalInstance = $uibModal.open( 29 '$scope',
28 { 30 '$uibModal',
29 ariaLabelledBy: 'Busqueda de Productos', 31 '$timeout',
30 templateUrl: 'src/views/modal-busqueda-productos.html', 32 function($scope, $uibModal, $timeout) {
31 controller: 'modalBusquedaProductosCtrl', 33 openModal();
32 size: 'md' 34
35 function openModal() {
36 var modalInstance = $uibModal.open(
37 {
38 ariaLabelledBy: 'Busqueda de Productos',
39 templateUrl: 'src/views/modal-busqueda-productos.html',
40 controller: 'modalBusquedaProductosCtrl',
41 size: 'lg'
42 }
43 );
44
45 modalInstance.result.then(
46 function (selectedItem) {
47 console.info(selectedItem);
48 $timeout(openModal, 500);
49 }, function () {
50 console.info('modal-component dismissed at: ' + new Date());
51 $timeout(openModal, 500);
52 }
53 );
33 } 54 }
34 ); 55 }
35 }]); 56 ]);
36 </script> 57 </script>
37 </head> 58 </head>
38 <body ng-controller="controller"> 59 <body ng-controller="controller">
39 </body> 60 </body>
40 </html> 61 </html>
41 62
1 { 1 {
2 "name": "foca-navegacion-doble", 2 "name": "foca-modal-busqueda-productos",
3 "version": "0.0.1", 3 "version": "0.0.1",
4 "description": "Menu de navegacion de doble entrada", 4 "description": "Menu de navegacion de doble entrada",
5 "main": "index.js", 5 "main": "index.js",
6 "scripts": { 6 "scripts": {
7 "test": "echo \"Error: no test specified\" && exit 1", 7 "test": "echo \"Error: no test specified\" && exit 1",
8 "compile": "gulp templates && gulp uglify", 8 "compile": "gulp templates && gulp uglify",
9 "pre-commit": [ 9 "gulp-pre-commit": "gulp pre-commit",
10 "gulp-pre-commit" 10 "postinstall": "npm run compile && rm -R src && rm index.html && rm .jshintrc && rm gulpfile.js",
11 ], 11 "install-dev": "npm install angular bootstrap jquery font-awesome gulp gulp-concat gulp-jshint gulp-rename gulp-replace gulp-uglify-es jshint pump gulp-connect jasmine-core pre-commit"
12 "postinstall": "npm run compile && rm -R src && rm index.html && rm .jshintrc && rm gulpfile.js", 12 },
13 "install-dev": "npm install angular bootstrap jquery font-awesome gulp gulp-concat gulp-jshint gulp-rename gulp-replace gulp-uglify-es jshint pump gulp-connect jasmine-core pre-commit" 13 "pre-commit": [
14 }, 14 "gulp-pre-commit"
15 "repository": { 15 ],
16 "type": "git", 16 "repository": {
17 "url": "https://192.168.0.11/modulos-npm/foca-navegacion-doble" 17 "type": "git",
18 }, 18 "url": "https://192.168.0.11/modulos-npm/foca-navegacion-doble"
19 "author": "Nicolás Guarnieri", 19 },
20 "license": "ISC", 20 "author": "Nicolás Guarnieri",
21 "peerDependencies": { 21 "license": "ISC",
22 "angular": "^1.7.4", 22 "peerDependencies": {
23 "bootstrap": "^4.1.3", 23 "angular": "^1.7.4",
24 "font-awesome": "^4.7.0", 24 "bootstrap": "^4.1.3",
25 "ui-bootstrap4": "^3.0.4", 25 "font-awesome": "^4.7.0",
26 "gulp": "^3.9.1", 26 "ui-bootstrap4": "^3.0.4",
27 "gulp-angular-templatecache": "^2.2.1", 27 "gulp": "^3.9.1",
28 "gulp-concat": "^2.6.1", 28 "gulp-angular-templatecache": "^2.2.1",
29 "gulp-connect": "^5.6.1", 29 "gulp-concat": "^2.6.1",
30 "gulp-htmlmin": "^5.0.1", 30 "gulp-connect": "^5.6.1",
31 "gulp-rename": "^1.4.0", 31 "gulp-htmlmin": "^5.0.1",
32 "gulp-replace": "^1.0.0", 32 "gulp-rename": "^1.4.0",
33 "gulp-uglify": "^3.0.1", 33 "gulp-replace": "^1.0.0",
34 "jquery": "^3.3.1", 34 "gulp-uglify": "^3.0.1",
35 "pump": "^3.0.0" 35 "jquery": "^3.3.1",
36 }, 36 "pump": "^3.0.0",
37 "devDependencies": { 37 "foca-directivas": "git+https://192.168.0.11/modulos-npm/foca-directivas"
38 "angular": "^1.7.4", 38 },
39 "bootstrap": "^4.1.3", 39 "devDependencies": {
40 "font-awesome": "^4.7.0", 40 "angular": "^1.7.4",
41 "gulp": "^3.9.1", 41 "bootstrap": "^4.1.3",
42 "gulp-angular-templatecache": "^2.2.1", 42 "foca-directivas": "git+https://192.168.0.11/modulos-npm/foca-directivas",
43 "gulp-concat": "^2.6.1", 43 "font-awesome": "^4.7.0",
44 "gulp-connect": "^5.6.1", 44 "gulp": "^3.9.1",
45 "gulp-htmlmin": "^5.0.1", 45 "gulp-angular-templatecache": "^2.2.1",
46 "gulp-jshint": "^2.1.0", 46 "gulp-concat": "^2.6.1",
47 "gulp-rename": "^1.4.0", 47 "gulp-connect": "^5.6.1",
48 "gulp-replace": "^1.0.0", 48 "gulp-htmlmin": "^5.0.1",
49 "gulp-uglify": "^3.0.1", 49 "gulp-jshint": "^2.1.0",
50 "jasmine-core": "^3.2.1", 50 "gulp-rename": "^1.4.0",
51 "jquery": "^3.3.1", 51 "gulp-replace": "^1.0.0",
52 "jshint": "^2.9.6", 52 "gulp-uglify": "^3.0.1",
53 "pre-commit": "^1.2.2", 53 "jasmine-core": "^3.2.1",
54 "pump": "^3.0.0", 54 "jquery": "^3.3.1",
55 "ui-bootstrap4": "^3.0.4" 55 "jshint": "^2.9.6",
56 } 56 "pre-commit": "^1.2.2",
57 "pump": "^3.0.0",
58 "ui-bootstrap4": "^3.0.4"
59 }
57 } 60 }
58 61
1 angular.module('focaBusquedaProductos', ['ui.bootstrap']); 1 angular.module('focaBusquedaProductos', ['ui.bootstrap', 'focaDirectivas']);
2 2
src/js/controller.js
1 angular.module('focaBusquedaProductos') 1 angular.module('focaBusquedaProductos')
2 .controller('modalBusquedaProductosCtrl',
3 ['$uibModalInstance', function($uibModalInstance) {
4
5 }]
6 )
2 .controller('modalBusquedaProductosCtrl',
3 [
4 '$filter',
5 '$scope',
6 '$uibModalInstance',
7 'focaBusquedaProductosService',
8 function($filter, $scope, $uibModalInstance, focaBusquedaProductosService) {
9 focaBusquedaProductosService.getProductos().then(
10 function(res) {
11 $scope.productos = res.data;
12 $scope.search();
13 }
14 );
15
16 // pagination
17 $scope.numPerPage = 10;
18 $scope.currentPage = 1;
19 $scope.filteredProductos = [];
20 $scope.currentPageProductos = [];
21 $scope.selectedProducto = -1;
22
23 //METODOS
24 $scope.search = function() {
25 $scope.filteredProductos = $filter('filter')(
26 $scope.productos,
27 {$: $scope.filters}
28 );
29
30 $scope.lastPage = Math.ceil(
31 $scope.filteredProductos.length / $scope.numPerPage
32 );
33
34 $scope.resetPage();
35 };
36
37 $scope.resetPage = function() {
38 $scope.currentPage = 1;
39 $scope.selectPage(1);
40 };
41
42 $scope.selectPage = function(page) {
43 var start = (page - 1) * $scope.numPerPage;
44 var end = start + $scope.numPerPage;
45 $scope.paginas = [];
46 $scope.paginas = calcularPages(page);
47 $scope.currentPageProductos = $scope.filteredProductos.slice(start, end);
48 $scope.currentPage = page;
49 };
50
51 $scope.select = function(producto) {
52 $uibModalInstance.close(producto);
53 };
54
55 $scope.cancel = function() {
56 $uibModalInstance.dismiss('cancel');
57 };
58
59 $scope.busquedaDown = function(key) {
60 if (key === 40) {
61 primera(key);
62 }
63 };
64
65 $scope.busquedaPress = function(key) {
66 if (key === 13) {
67 primera(key);
68 }
69 };
70
71 $scope.itemProducto = function(key) {
72 if (key === 38) {
73 anterior(key);
74 }
75
76 if (key === 40) {
77 siguiente(key);
78 }
79
80 if (key === 37) {
81 retrocederPagina();
82 }
83
84 if (key === 39) {
85 avanzarPagina();
86 }
87 };
88
89 function calcularPages(paginaActual) {
90 var paginas = [];
91 paginas.push(paginaActual);
92
93 if (paginaActual - 1 > 1) {
94
95 paginas.unshift(paginaActual - 1);
96 if (paginaActual - 2 > 1) {
97 paginas.unshift(paginaActual - 2);
98 }
99 }
100
101 if (paginaActual + 1 < $scope.lastPage) {
102 paginas.push(paginaActual + 1);
103 if (paginaActual + 2 < $scope.lastPage) {
104 paginas.push(paginaActual + 2);
105 }
106 }
107
108 if (paginaActual !== 1) {
109 paginas.unshift(1);
110 }
111
112 if (paginaActual !== $scope.lastPage) {
113 paginas.push($scope.lastPage);
114 }
115
116 return paginas;
117 }
118
119 function primera() {
120 $scope.selectedProducto = 0;
121 }
122
123 function anterior() {
124 if ($scope.selectedProducto === 0 && $scope.currentPage > 1) {
125 retrocederPagina();
126 } else {
127 $scope.selectedProducto--;
128 }
129 }
130
131 function siguiente() {
132 if ($scope.selectedProducto < $scope.currentPageProductos.length - 1 ) {
133 $scope.selectedProducto++;
134 } else {
135 avanzarPagina();
136 }
137 }
138
139 function retrocederPagina() {
140 if ($scope.currentPage > 1) {
141 $scope.selectPage($scope.currentPage - 1);
142 $scope.selectedProducto = $scope.numPerPage - 1;
143 }
144 }
145
146 function avanzarPagina() {
147 if ($scope.currentPage < $scope.lastPage) {
148 $scope.selectPage($scope.currentPage + 1);
149 $scope.selectedProducto = 0;
150 }
1 angular.module('focaBusquedaProductos')
2 .service('focaBusquedaProductosService', [
3 '$http',
4 'API_ENDPOINT',
5 function($http, API_ENDPOINT) {
6 return {
7 getProductos: function() {
8 return $http.get(API_ENDPOINT.URL + '/articulos');
9 }
10 };
11 }
12 ]);
13
src/views/modal-busqueda-productos.html
1 <div class="modal-header"> 1 <div class="modal-header">
2 <h3 class="modal-title" id="modal-title">I'm a modal!</h3> 2 <h3 class="modal-title">Busqueda de Productos</h3>
3 </div> 3 </div>
4 <div class="modal-body" id="modal-body"> 4 <div class="modal-body" id="modal-body">
5 Esto es una prueba espero que funcione 5 <div class="input-group mb-3">
6 <input
7 type="text"
8 class="form-control"
9 placeholder="Busqueda"
10 ng-model="filters"
11 ng-change="search()"
12 ng-keydown="busquedaDown($event.keyCode)"
13 ng-keypress="busquedaPress($event.keyCode)"
14 foca-focus="selectedProducto == -1"
15 ng-focus="selectedProducto = -1"
16 >
17 <table class="table table-striped table-sm">
18 <thead>
19 <tr>
20 <th>Sec.</th>
21 <th>Cod.</th>
22 <th>Descripción</th>
23 <th>P. Base</th>
24 <th></th>
25 </tr>
26 </thead>
27 <tbody>
28 <tr ng-repeat="(key,producto) in currentPageProductos">
29 <td ng-bind="producto.sector"></td>
30 <td ng-bind="producto.codigo"></td>
31 <td ng-bind="producto.descripcion"></td>
32 <td ng-bind="producto.precio | currency"></td>
33 <td>
34 <button
35 type="button"
36 class="btn p-2 float-right"
37 ng-class="{
38 'btn-secondary': selectedProducto != key,
39 'btn-primary': selectedProducto == key
40 }"
41 ng-click="select(producto)"
42 foca-focus="selectedProducto == {{key}}"
43 ng-keydown="itemProducto($event.keyCode)"
44 >
45 <i class="fa fa-arrow-right" aria-hidden="true"></i>
46 </button>
47 </td>
48 </tr>
49 </tbody>
50 </table>
51 <nav>
52 <ul class="pagination justify-content-end">
53 <li class="page-item" ng-class="{'disabled': currentPage == 1}">
54 <a class="page-link" href="#" ng-click="selectPage(currentPage - 1)">
55 <span aria-hidden="true">&laquo;</span>
56 <span class="sr-only">Anterior</span>
57 </a>
58 </li>
59 <li
60 class="page-item"
61 ng-repeat="pagina in paginas"
62 ng-class="{'active': pagina == currentPage}"
63 >
64 <a
65 class="page-link"
66 href="#"
67 ng-click="selectPage(pagina)"
68 ng-bind="pagina"
69 ></a>
70 </li>
71 <li class="page-item" ng-class="{'disabled': currentPage == lastPage}">
72 <a class="page-link" href="#" ng-click="selectPage(currentPage + 1)">
73 <span aria-hidden="true">&raquo;</span>
74 <span class="sr-only">Siguiente</span>
75 </a>
76 </li>
77 </ul>
78 </nav>
79 </div>
6 </div> 80 </div>
7 <div class="modal-footer"> 81 <div class="modal-footer">
8 <button class="btn btn-primary" type="button">OK</button> 82 <button class="btn btn-secondary" type="button" ng-click="cancel()">Cancelar</button>
9 <button class="btn btn-warning" type="button">Cancel</button>
10 </div> 83 </div>