angular filter with ng-repeat giving strange error

0

I'm having trouble using a filter in conjunction with ng-repeat. I have an event json where I want, when selecting an event type in select, the filter returns a new json with only events that have the event type chosen, this is my code

CONTROLLER

            $scope.filtro = "";
            $scope.eventos = [
            {
                data: "2016-05-09",
                eventos: [1, 5, 3, 7]
            },
            {
                data: "2016-05-08",
                eventos: [2, 0]
            },
            {
                data: "2016-05-07",
                eventos: [0, 3, 6]
            },
            {
                data: "2016-04-03",
                eventos: [1, 6, 7, 8]
            },
            {
                data: "2016-04-02",
                eventos: [7]
            },
            {
                data: "2015-01-01",
                eventos: [7, 3]
            }
        ];

HTML

    <div ng-repeat="(key,evento) in (eventos|filtraEvento:filtro)">
        <div><b style="color:red">{{key}}º) - </b>{{evento.data}}</div>
        <div>
            <span ng-repeat="e in evento.eventos">[{{e}}]</span>
        </div>
    </div>
    <select ng-model="filtro">
        <option value="0">0</option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
        <option value="6">6</option>
        <option value="7">7</option>
        <option value="8">8</option>
    </select>

FILTER

.filter('filtraEvento', ['Util', function (Util) {
    return function (eventos, tipoEvento) {
        var eventosFiltrado = [];
        if (!Util.isNull(tipoEvento)) {
            for (var i = 0; i < eventos.length; i++) {
                var evento = [];
                for (var j = 0; j < eventos[i].eventos.length; j++) {
                    if (eventos[i].eventos[j] == tipoEvento) {
                        evento.push(eventos[i].eventos[j]);
                    }
                }
                if (evento.length > 0) {
                    eventosFiltrado.push({
                        data: eventos[i].data,
                        eventos: evento
                    });
                }

            }
        } else {
            eventosFiltrado = eventos;
        }
        return eventosFiltrado;
    }
}]);

Unfiltered the system displays normal, but if I choose some filter, besides giving the error:

  "Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!"

The system often duplicated the result: Ex: If I choose the filter "2" the displayed result would be:

1º)2016-05-08
1º)2016-05-08
1º)2016-05-08
1º)2016-05-08
1º)2016-05-08
.
.
.
seguido do json original

From now on I thank you for any help, sorry if I did something out of the standard of the site, I'm new here

    
asked by anonymous 12.05.2016 / 20:09

2 answers

0

Hello, I understand you want to filter which dates have the selected number.

I put a field identifier in JSON so that you can use the angle filter itself, see below for JSON.

          $scope.eventos = [
        {
            data: "2016-05-09",
            eventos: [
              {numero: 1}, 
              {numero: 5}, 
              {numero: 3}, 
              {numero: 7}
              ]
        },
        {
            data: "2016-05-08",
            eventos: [
              {numero:2},
              {numero:0}
              ]
        },
        {
            data: "2016-05-07",
            eventos: [
              {numero:0},
              {numero:3},
              {numero:6}
              ]
        },
        {
            data: "2016-04-03",
            eventos: [
              {numero:1}, 
              {numero:6}, 
              {numero:7}, 
              {numero:8}
              ]
        },
        {
            data: "2016-04-02",
            eventos: [{numero:7}]
        },
        {
            data: "2015-01-01",
            eventos: [
                {numero:7}, 
                {numero:3}
              ]
        }
    ];

Then I put a filter parameter that I named as filterTxn

   <div ng-repeat="evento in eventos  | filter: filterTxn">

And I put this parameter in your ng-model as the name of the field that you want to filter in JSON in case and field number of the events node then gets filterTex.events.number.

   <select ng-model="filterTxn.eventos.numero">

When selecting the select it filters and displays only the data that contains the selected number.

An OBS as the Node event contains an Array of Numbers following the entire Array.

I hope I have helped publish Plunker this test if you want to see.

link

    
13.05.2016 / 04:33
0

If you care about performance, DO NOT USE PIPE FILTER

(eventos | filtraEvento:filtro) //Não use o filtro assim ' | filtro'

Each $ digest interaction, regardless of whether it was originated by the filter, ng-click, or any other type of trigger, will run its filter 2 times for $ digest. That is, roughly speaking, any other interaction you have in your view will rotate this filter, even if it has nothing to do with the filter itself.

How to solve? Do this in the controller and only update the $ scope value, this way you will only run the filter once and when it is actually used.

How? (And now I already answer your question). It's important to note that you do not need to change your JSON framework to make this work, okay? Another difference is that you can simplify your code using:

angular.forEach(colecao, function(objeto, index) {
    //Loop aqui
})

This replaces the for () . Now below see an example of how to use it in your controller:

var eventos = [
    { 
        data: "2016-05-09",
        eventos: [1, 5, 3, 7]
    },
    [...etc...]
];

$scope.eventos = eventos;

/* Função de Filtro */
$scope.rodaFiltro = function(filtro) {

    if (filtro) { //Se algum filtro foi selecionado, aplicamos a filtragem
        var filtrados = [];

        angular.forEach(eventos, function(obj){ //Loop na coleção
            angular.forEach(obj.eventos, function (item) { //Loop no tipo de evento
                if(item == filtro) { //Verifica se o evento é igual a um dos eventos cadastrados na data
                    filtrados.push(obj); //Se sim, coloca ele na array de filtrados
                }
            })
        })

        $scope.eventos = filtrados; //Atualiza a lista

    } else { //Se nenhum filtro foi selecionado, voltamos a lista original
        $scope.eventos = eventos;
    }
}

See a working example: link

    
13.05.2016 / 14:35