3

I'm trying to build double select with null option.

One select is filtered according to the first select chosen option. The problem I have is I want to keep the first 'null' row even after filter.

I've made a plunker based on solution of null option I saw. Here's the plunker: demo

I am trying to select a country and in the cities, keep the 'null' option (anyCity) as a selectable option. What is the best approach to achieve this?

(My original problem consists of double filter--> selecting a city also filtering the country)

Html:

<body ng-controller="DemoCtrl">
<h3>Countries</h3>
  <p>Selected: {{country.selected || (country.selected === null ? 'null' : '')}}</p>
  <ui-select ng-model="country.selected" theme="bootstrap" ng-disabled="disabled" style="width: 300px;">
    <ui-select-match placeholder="Select or search a country in the list...">{{$select.selected.name}}</ui-select-match>
    <ui-select-choices repeat="country in countries | filter: $select.search" null-option="anyCountry">
      <span ng-bind-html="country.name | highlight: $select.search"></span>
      <small ng-bind-html="country.code | highlight: $select.search"></small>
    </ui-select-choices>
  </ui-select>

  <h3>Cities</h3>
  <p>The loose-null option treats undefined the same as null.</p>
  <p>Selected: {{country2.selected || (country2.selected === null ? 'null' : '')}}</p>
  <ui-select ng-model="country2.selected" theme="bootstrap" ng-disabled="disabled" style="width: 300px;">
    <ui-select-match placeholder="Select or search a city in the list...">{{$select.selected.name}}</ui-select-match>
    <ui-select-choices repeat="city in cities | filter: {country: country.selected.code}" null-option="anyCity" loose-null>
      <span ng-bind-html="city.name | highlight: $select.search"></span>
      <small ng-bind-html="city.code | highlight: $select.search"></small>
    </ui-select-choices>
  </ui-select>
</body>
</html>
Ziv Weissman
  • 4,400
  • 3
  • 28
  • 61

1 Answers1

1

The issue is that there is a filter on cities which is trying to match each city's country against the selected country, and currently the 'Any city' option will not meet that criteria.

One approach would be to leave the filter as-is, but ensure that the 'Any city' option always meets the filter criteria. You could achieve this by setting a country property on the existing anyCity object and populate it with all possible cities.

$scope.anyCity = {name: 'Any city', country:['GB', 'US', 'UM']};

Another approach is to change the filter to always allow the 'Any city' option.

View:

<ui-select-choices repeat="city in cities | filter: countryFilter" null-option="anyCity" loose-null>

Controller:

$scope.countryFilter = function(city){
  return city === $scope.anyCity
  || city.country === $scope.country.selected.code;
}

Which is better? The first approach is simple in this example but for a long list of countries less ideal. If your data can change, you'd need to populate it dynamically. I prefer the second as it's more explicit what the intended functionality is.

sheilak
  • 5,833
  • 7
  • 34
  • 43
  • 1
    Thank you, I've actually tried something like this, seems to work, only I used a comma separated values instead of array... does it suppose to work? (like your first example) – Ziv Weissman Nov 02 '15 at 20:24
  • 1
    Yes a string with comma separated values will work because `filter:` does a substring match [(docs)](https://docs.angularjs.org/api/ng/filter/filter). As mentioned I prefer the scope function approach for clarity & in case the data changes, but yours should work reliably too. – sheilak Nov 02 '15 at 20:34