8

Tengo dos array de objetos que son alimentados por un mismo rest, uno alimenta un listado visual y el otro mantiene los datos originales traídos en la respuesta.

Tengo un input de tipo text que se utiliza como buscador del listado por cualquier propiedad que contengan los objetos.

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, $filter) {
  $scope.actividadesShow = [{
    id: 1,
    nombre: 'Actividad 1',
    codigo: 89466,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 2',
    codigo: 89714,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 3',
    codigo: 89755,
    responsable: 'Bender'
  }];
  
  $scope.actividades = [{
    id: 1,
    nombre: 'Actividad 1',
    codigo: 089466,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 2',
    codigo: 089714,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 3',
    codigo: 089755,
    responsable: 'Juan'
  }];
  
  $scope.$watch('buscarActividad', function(value){
    if (value != undefined) {
      $scope.actividadesShow = $filter('filter')($scope.actividades, value);
    }
  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myCtrl">
  <input type="text" ng-model="buscarActividad">
  <ul>
    <li ng-repeat="actividad in actividadesShow track by $index">
      {{ actividad.codigo }} - {{ actividad.nombre }} 
    </li>
  </ul>
</div>

Así el sistema funciona correctamente, puedo buscar por responsable y me muestra los que son del responsable asignado.

El problema es que necesito hacer un buscador que busque por múltiples valores separados por comas y es ahí donde no se como hacerlo, intenté pasando un array al $filter pero no sirvió y por mas que busco en google no entiendo las soluciones que proponen o son soluciones demasiado extensas .

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, $filter) {
  $scope.actividadesShow = [{
    id: 1,
    nombre: 'Actividad 1',
    codigo: 89466,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 2',
    codigo: 89714,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 3',
    codigo: 89755,
    responsable: 'Bender'
  }];
  
  $scope.actividades = [{
    id: 1,
    nombre: 'Actividad 1',
    codigo: 089466,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 2',
    codigo: 089714,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 3',
    codigo: 089755,
    responsable: 'Juan'
  }];
  
  $scope.$watch('buscarActividad', function(value){
    if (value != undefined) {
      $scope.actividadesShow = $filter('filter')($scope.actividades, value.split(', '));
    }
  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myCtrl">
  <input type="text" ng-model="buscarActividad">
  <ul>
    <li ng-repeat="actividad in actividadesShow track by $index">
      {{ actividad.codigo }} - {{ actividad.nombre }} 
    </li>
  </ul>
</div>

Entonces como puedo pasarle varios valores al filtro? Si es posible o debo usar otros métodos?

JackNavaRow
  • 6,836
  • 5
  • 22
  • 49
Bender Paisa
  • 12,491
  • 4
  • 23
  • 41

2 Answers2

7

Puedes hacer lo siguiente:

  1. Realizar la busqueda por medio del filter()
  2. Dentro del filter recorrer el split separado por comas de buscarActividad
  3. Verificar el texto se encuentre en la cadena(aqui el truco#1 llevamos el Objeto a JSON con JSON.stringify())
  4. puesto que el Array.map() retorna un array, usamos la funcion reduce para sumar todas las incidencias(truco # 2)
  5. Finalmente dentro del filter retornamos la suma del reduce si es > 0

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, $filter) {
  $scope.actividadesShow = [];
  $scope.buscarActividad = ""
  $scope.actividades = [{
    id: 1,
    nombre: 'Actividad 1',
    codigo: 089466,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 2',
    codigo: 089714,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 3',
    codigo: 089755,
    responsable: 'Juan'
  }];
  
  $scope.buscar = function(){
    let arrBusqueda = $scope.buscarActividad.split(",");
    $scope.actividadesShow = 
    $scope.actividades
              .filter((item)=>{ 
                 let a =  arrBusqueda.map((value)=>
                 {
                  return JSON.stringify(item)
                            .toUpperCase()
                            .indexOf(value.toUpperCase()) > -1 ? 1 : 0;
                 }).reduce((x, y) => x + y);   
                 return a > 0                 
                }) 

  }
  $scope.buscar()
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myCtrl">
  <input type="text" ng-model="buscarActividad"ng-change="buscar()">
  <ul>
    <li ng-repeat="actividad in actividadesShow track by $index">
      {{ actividad.codigo }} - {{ actividad.nombre }} : {{ actividad.responsable }} 
    </li>
  </ul>
</div>

El unico detalle es que tambien la busqueda sera por key del Objeto

Este ejemplo ejemplo es util para cualquier framework puesto que solo usa funciones Nativas de Javascript

JackNavaRow
  • 6,836
  • 5
  • 22
  • 49
6

Podrías hacerlo exactamente igual que en el primer caso, pero usando la función filter de la clase Array y una función personalizada para comparar:

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, $filter) {
  // Función que compara los datos
  function generaFiltro(value) {
    const lista = value.split(',');
    return (actividad) => {
      return lista.some(str => {
        return actividad.nombre.includes(str.split()) ||
          String(actividad.codigo).includes(str.split()) ||
          actividad.responsable.includes(str.split());
      });   
    }
  }
  
  $scope.actividades = [{
    id: 1,
    nombre: 'Actividad 1',
    codigo: 089466,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 2',
    codigo: 089714,
    responsable: 'Bender'
  }, {
    id: 1,
    nombre: 'Actividad 3',
    codigo: 089755,
    responsable: 'Juan'
  }];
  
  $scope.actividadesShow = $scope.actividades;
  
  $scope.$watch('buscarActividad', function(value){
    if (value != undefined) {
      const data= value.split(',');
      $scope.actividadesShow = $scope.actividades.filter(generaFiltro(value));
    }
  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myCtrl">
  <input type="text" ng-model="buscarActividad">
  <ul>
    <li ng-repeat="actividad in actividadesShow track by $index">
      {{ actividad.codigo }} - {{ actividad.nombre }} 
    </li>
  </ul>
</div>
Pablo Lozano
  • 45,934
  • 7
  • 48
  • 87