0

I´m currently trying to create a kind of form to choose options from two dependent drop-down menus. If you are changing the option on the upper one, the data on the lower one should also change depending on the upper one.
Therefore I created a small example where you first select a country. After this you can select a city from this country.
The data is stored in a local array and will be later fetched via a service. The data should be saved in an object array because that's how data is provided by the service, so no conversion will be necessary.

Here you can see my pretty simple code, which is just a spare skeleton at the moment due to the fact that I have no clue how to create such a 'communicating' form. I hope you guys can help me to solve this kind of problem.

HTML

<body ng-app="AngularApp">
  <div ng-controller="MainCtrl as Main">
    <h1>{{Main.message}}</h1>
    country:
    <select name="country">
      <option></option>
    </select>
    <br/>city:
    <select name="city">
      <option></option>
    </select>
  </div>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</body>

App.js

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

app.controller("MainCtrl", function() {
  var vm = this;

  vm.message = "Select your destination";
  vm.data = [
    { city: 'Berlin',         country: 'Germany' },
    { city: 'Hamburg',        country: 'Germany' },
    { city: 'Munich',         country: 'Germany' },
    { city: 'New York',       country: 'USA' },
    { city: 'Whashington DC', country: 'USA' },
    { city: 'Paris',          country: 'France' }
  ];
});

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

app.controller("MainCtrl", function() {
  var vm = this;

  vm.message = "Select your destination";
  vm.data = [
    { city: 'Berlin',         country: 'Germany' },
    { city: 'Hamburg',        country: 'Germany' },
    { city: 'Munich',         country: 'Germany' },
    { city: 'New York',       country: 'USA' },
    { city: 'Whashington DC', country: 'USA' },
    { city: 'Paris',          country: 'France' }
  ];
});
<body ng-app="AngularApp">
  <div ng-controller="MainCtrl as Main">
    <h1>{{Main.message}}</h1>
    country:
    <select name="country">
      <option></option>
    </select>
    <br/>city:
    <select name="city">
      <option></option>
    </select>
  </div>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</body>

Additional explanation:
So if you choose 'Germany' as your country, in the city selection only the options 'Berlin', 'Hamburg' and 'Munich' should be available because of the attribute country. The other cities like Paris or New York won´t be displayed.


EDIT It also would be nice if there is one country selected per default, so that no empty drop-down will show up.

JohnDizzle
  • 1,268
  • 3
  • 24
  • 51

4 Answers4

2

You can use the 'angular-filter' module to show unique options.

<select name="country" ng-model="country">
    <option ng-repeat="option in Main.data | unique: 'country'"
            value="{{option.country}}">{{option.country}}</option>
</select>

<select name="city" ng-model="city">
    <option ng-repeat="option in Main.data" ng-if="option.country == country"
            value="{{option.city}}">{{option.city}}</option>
</select>

Example

I added some Bootstrap classes to the form to clean up its presentation. :)

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

app.controller("MainCtrl", function() {
  var vm = this;

  vm.message = "Select Your Destination";
  vm.data = [
    { city: 'Berlin',         country: 'Germany' },
    { city: 'Hamburg',        country: 'Germany' },
    { city: 'Munich',         country: 'Germany' },
    { city: 'New York',       country: 'USA' },
    { city: 'Whashington DC', country: 'USA' },
    { city: 'Paris',          country: 'France' }
  ];
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.11/angular-filter.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />

<body ng-app="AngularApp">
  <div ng-controller="MainCtrl as Main" class="container">
    <h1>{{Main.message}}</h1>
    <form>
      <div class="form-group">
        <label>Country</label>
        <select name="country" ng-model="country" class="form-control">
          <option ng-repeat="option in Main.data | unique: 'country'" value="{{option.country}}">{{option.country}}</option>
        </select>
      </div>
      <div class="form-group">
        <label>City</label>
        <select name="city" ng-model="city" class="form-control">
          <option ng-repeat="option in Main.data" ng-if="option.country == country" value="{{option.city}}">{{option.city}}</option>
        </select>
      </div>
      <br />
      <button type="submit" class="btn btn-default">Submit</button>
    </form>
  </div>
</body>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • Good one. Keep it. – Kalu Singh Rao Aug 30 '16 at 13:47
  • Is there a way how to set a country per default so your sexy looking form won´t be empty at loading ;-) ? – JohnDizzle Aug 30 '16 at 13:49
  • You mean set a city default for each country? – Mr. Polywhirl Aug 30 '16 at 18:24
  • You might be able to set `ng-init` on your country option to point to a default city. Try looking for info here: [*"Angular js init ng-model from default values"*](http://stackoverflow.com/questions/13769732/angular-js-init-ng-model-from-default-values). – Mr. Polywhirl Aug 30 '16 at 18:32
  • I want to set the first country in my list and the first city of the country to default. It´s not possible to set the `ng-init`-value to a static string due to changes in the data. How is it possible to set the **first** country and a fitting city to default? – JohnDizzle Aug 31 '16 at 06:23
1

HTML Code

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Login</title>
  </head>
  <body ng-app="AngularApp">

  <div ng-controller="MainCtrl as Main">
    <h1>{{Main.message}}</h1>
    country:
    <select name="country" ng-model="cont" ng-init="cont = cont || 'Germany'">   
        <option ng-selected="$first" ng-repeat="con in Main.data | unique:'country'">{{con.country}}</option> 
    </select>
    <br/>
    city:
    <select name="city" ng-model="cit">
        <option ng-selected="$first" ng-repeat="ct in Main.data | filter:{country: cont}">{{ct.city}}</option>
    </select>
  </div>



  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js" type="text/javascript"></script>
  <script src="app.js"></script>
  </body>
</html>

Create one filter named 'unique' in your app.js . So your app.js like this..

var app = angular.module('AngularApp', []);
app.controller("MainCtrl", function() {
    var vm = this;

    vm.message = 'select your destination';

    vm.data = [{city: 'Berlin', country: 'Germany'},
               {city: 'Hamburg', country: 'Germany'},
               {city: 'Munich', country: 'Germany'},
               {city: 'New York', country: 'USA'},
               {city: 'Whashington DC', country: 'USA'},
               {city: 'Paris', country: 'France'}
            ];
});
app.filter('unique', function() {
  return function (arr, field) {
    var o = {}, i, l = arr.length, r = [];
    for(i=0; i<l;i+=1) {
      o[arr[i][field]] = arr[i];
    }
    for(i in o) {
      r.push(o[i]);
    }
    return r;
  };
});
Raj
  • 439
  • 1
  • 8
  • 28
0

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

app.controller("MainCtrl", function() {
  var vm = this;

  vm.message = "Select Your Destination";
  vm.data = [
    { city: 'Berlin',         country: 'Germany' },
    { city: 'Hamburg',        country: 'Germany' },
    { city: 'Munich',         country: 'Germany' },
    { city: 'New York',       country: 'USA' },
    { city: 'Whashington DC', country: 'USA' },
    { city: 'Paris',          country: 'France' }
  ];
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.11/angular-filter.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />

<body ng-app="AngularApp">
  <div ng-controller="MainCtrl as Main" class="container">
    <h1>{{Main.message}}</h1>
    <form>
      <div class="form-group">
        <label>Country</label>
        <select name="country" ng-model="country" class="form-control">
          <option value="" selected="selected">Choose one</option>
          <option ng-repeat="option in Main.data | unique: 'country'" value="{{option.country}}">{{option.country}}</option>
        </select>
      </div>
      <div class="form-group">
        <label>City</label>
        <select name="city" ng-model="city" class="form-control">
          <option value="" selected="selected">Choose one</option>
          <option ng-repeat="option in Main.data" ng-if="option.country == country" value="{{option.city}}">{{option.city}}</option>
        </select>
      </div>
      <br />
      <button type="submit" class="btn btn-default">Submit</button>
    </form>
  </div>
</body>
Kalu Singh Rao
  • 1,671
  • 1
  • 16
  • 21
-1

You can use below HTML:

Country:
<select name="country" ng-model="country">
  <option ng-repeat="option in Main.data" value="{{option.country}}">{{option.country}}</option>
</select>

City:
<select name="city" ng-model="city">
  <option ng-repeat="option in Main.data" ng-if="option.country == country" value="{{option.city}}">{{option.city}}</option>
</select>
dipendra
  • 261
  • 1
  • 3
  • 9
  • thanks for your answer but 'Germany' shows up 3 times in the selection. It should just be displayed once to prevent an unnecessarily long list. – JohnDizzle Aug 30 '16 at 12:36