Kyle
Kyle

Reputation: 66

Dynamic Drop Down AngularJS and Database with JSON

I have figured out how to populate the first dropdown menu from the database with Angular, but I am stuck on how to grab the selected value of the first dropdown box to query to populate the second box. Also, if the data is in separate tables, will I have to make an API call everytime a dropdown is selected? I have seen plenty of examples doing this with pre set tables, but not with actual api calls. This is where I get confused.

Here is what I have now.

app.controller('SelectOptGroupController', function($scope,$http) {
        $http.get('api2.php').
        success(function(data) {
            $scope.animals = data;
        });
         $scope.species= [];
         $scope.getOptions2 = function(){
            //NOT SURE FROM HERE
          };

  })

HTML file

<div ng-controller="SelectOptGroupController" class="md-padding selectdemoOptionGroups">
          <div>
            <h1 class="md-title">Select Animal</h1>
            <div layout="row">
              <md-select ng-model="animals" placeholder="Animals" ng-change="getOptions2()">
                <md-option ng-repeat="animal in animals" value="{{animal.animal}}">{{animal.animal}}</md-option>
              </md-select>
              <md-select ng-model="species" placeholder="Species">
                <md-option ng-repeat="spec in species" value="{{spec.animal_species}}">{{spec.animal_species}}</md-option>
              </md-select>

          </div>
        </div>

As of now the database has one table with two columns being animal and animal_species. There are multiple species of the same animal, for example there are three inserts with the animal name of bear but each of the animal_species are different grizzly, black, and polar. Thanks for any help!

Upvotes: 1

Views: 7091

Answers (1)

Kevin F
Kevin F

Reputation: 2885

For your first question the ng-model of the md-select will correspond to the selected animal in the collection, so in this example $scope.model.selectedAnimal, would be the variable you can use to access the selected animal.

<div ng-controller="SelectOptGroupController" class="md-padding selectdemoOptionGroups">
    <div>
        <h1 class="md-title">Select Animal</h1>
        <div layout="row">
            <md-select ng-model="model.selectedAnimal" placeholder="Animals" ng-change="getSpecies()">
                <md-option ng-repeat="animal in model.animals" value="{{ animal }}">{{ animal }}</md-option>
            </md-select>
            <md-select ng-model="model.selectedSpecies" placeholder="Species">
                <md-option ng-repeat="species in model.species" value="{{ species.animal_species }}">{{ species.animal_species }}</md-option>
            </md-select>
        </div>
    </div>
</div>

As for your repeated api calls question, you can either have the database return all species and manage the 'active' ones in the js, or use a service to cache each request so that at least each animal will only query the api once. This also keeps the data logic out of the controller to make it reusable (as well as easy to share data between multiple controllers/directives/services).

app.controller('SelectOptGroupController', ['$scope', 'animalService', function($scope, animalService) {
    $scope.model = {
        animals: [],
        species: [],
        selectedAnimal: '',
        selectedSpecies: {}
    };

    animalService.getAnimals().then(function(data){
        $scope.model.animals = data;
    });

    $scope.getSpecies = function(){
        animalService.getSpecies($scope.model.selectedAnimal).then(function(data){
            $scope.model.species = data;
        }); 
    };
}]); //TYPO WAS HERE

app.factory('animalService', ['$http', '$q', function($http, $q){
    var cache = {};

    return {
        getAnimals: function(){
            return $http.get('api2.php').then(function(result) {
                return result.data;
            });
        },
        getSpecies: function(animal){
            if(cache[animal]){
                return $q.when(cache[animal]);
            } else{
                return $http({
                    url: 'whatever.php',
                    method: 'GET',
                    params: {
                        animal: animal
                    }
                }).then(function(result){
                    cache[animal] = result.data;
                    return cache[animal];
                });
            }
        }
    };
}]);

If you want to get all species in one go and just filter on the front end you can do something like this:

app.controller('SelectOptGroupController', ['$scope', 'animalService', function($scope, animalService) {
    $scope.model = {
        animals: [],
        species: [], //this will contain selected animals species
        allSpecies: [], //this will contain all species for all animals
        selectedAnimal: '',
        selectedSpecies: {}
    };

    animalService.getAnimals().then(function(data){
        $scope.model.animals = data;
    });

    animalService.getSpecies().then(function(data){
        $scope.model.allSpecies = data;
    });

    $scope.getSpecies = function(){
        //this filters out the species for the selected animal
        $scope.model.species = $scope.model.allSpecies.filter(function(species){
            return species.animal === $scope.model.selectedAnimal;
        });
    };
}]);

app.factory('animalService', ['$http', '$q', function($http, $q){
    return {
        getAnimals: function(){
            return $http.get('api2.php').then(function(result) {
                return result.data;
            });
        },
        getSpecies: function(animal){
            return $http.get('api3.php').then(function(result){
                return result.data;
            });
        }
    };
}]);

Upvotes: 2

Related Questions