sergio0983 sergio0983 - 4 months ago 28
AngularJS Question

filter in ng-options returning full dataset when compared to empty string

I have two linked dropdowns. The second one is supposed to show only a filtered set based on what is selected on the first one. It works fine, but when I choose back the empty option in the first one, the second one is loaded with the full recordset (guess that the empty string is not evaluated):

<select required ng-options = 'convenio.id as convenio.nombre for convenio in convenios' ng-model = 'master.id_convenio'>
<option value = ''>Seleccione el Convenio</option>
</select>

<select required ng-disabled = "!master.id_convenio" ng-model = 'master.id_categoria' ng-options = 'categoria.id as categoria.nombre for categoria in categorias | filter:{id_convenio:master.id_convenio}:true'>
<option value = ''>Seleccione la categoría</option>
</select>


What I want is: if master.id_convenio is null or an empty string, the filtered options for the second select should be empty. Not sure if this is a feature, and if so, how can I override it, if possible.

Thanks.

Answer

Since you didn't provide any piece of the structure of your arrays it's a bit hard to say what's wrong, but I guess you're failing on your filter construction filter:{id_convenio:master.id_convenio}:true.

Here's a simple demo which one you can take it as base to correct your:

angular.module('app', [])
  .controller('mainCtrl', function($scope) {
    $scope.countries = [  
       {  
          "id":1,
          "name":"France"
       },
       {  
          "id":2,
          "name":"EUA"
       },
       {  
          "id":3,
          "name":"Italy"
       }
    ];

    $scope.cities = [  
       {  
          "id":4,
          "name":"Nice",
          "countryId":1
       },
       {  
          "id":5,
          "name":"Paris",
          "countryId":1
       },
       {  
          "id":6,
          "name":"New York",
          "countryId":2
       },
       {  
          "id":7,
          "name":"Los Angeles",
          "countryId":2
       },
       {  
          "id":8,
          "name":"Rome",
          "countryId":3
       },
       {  
          "id":9,
          "name":"Milan",
          "countryId":3
       }
    ];
  });
<html ng-app="app">

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>

<body ng-controller="mainCtrl">
  <select ng-options="country.id as country.name for country in countries" ng-model="countrySelected">
    <option value="">Select country</option>
  </select>
  <span ng-bind="countrySelected"></span>
  <hr>
  <select ng-disabled="!countrySelected" ng-options="city.id as city.name for city in cities | filter: { countryId: countrySelected || -1} : true" ng-model="citySelected">
    <option value="">Select city</option>
  </select>
</body>

</html>

EDIT:

After much conversation and really know what was wrong I came up to the solution:

<select ng-disabled="!countrySelected" ng-options="city.id as city.name for city in cities | filter: { countryId: countrySelected || -1} : true" ng-model="citySelected">

Note: The || -1 inside the filter will clear the dependent <select>.

I hope it helps!