MJV
MJV

Reputation: 1882

Initializing/populating select boxes on page load in AngularJS

I'm writing a web application using AngularJS. I use a third-party library (that provides an Angular service) to fetch values from a database, and then use those to initialize some dropdown/select boxes on a page.

So, I have simple select boxes like this:

<div ng-controller="ChoiceCtrl">
    <select ng-model="selectedFoo" ng-options="foo in foos"></select>
    <select ng-model="selectedBar" ng-options="bar in bars"></select>
</div>

And a corresponding controller that initializes the choices for the select boxes. The service I'm using calls the given callback function after it receives values from the database. (The callback functions could be refactored into one but I'm using separate ones for clarity.)

angular.module('choice').controller('ChoiceCtrl', function($scope, ThirdPartyService) {
    $scope.selectedFoo = '';
    $scope.selectedBar = '';
    $scope.foos = '';
    $scope.bars = '';

    var fooCallback = function(result) {
        $scope.foos = result;
        $scope.$apply;
    }

    var barCallback = function(result) {
        $scope.bars = result;
        $scope.$apply;
    }

    ThirdPartyService.asyncGetData('fetchFooOptions', fooCallback);
    ThirdPartyService.asyncGetData('fetchBarOptions', barCallback);
});

The database calls are asynchronous and finish after the page has been rendered for the first time, so I manually call $scope.$apply in each callback function.

Is this the right way to initialize dropdown/select boxes in an AngularJS app when the values are fetched asynchronously when loading a page?

I've read tutorials saying that calling $scope.$apply manually is always a "code smell"... But since I'm fetching the values from a database, the operation happens "outside of Angular" which I believe makes those calls justified - and actually necessary.

I'm also wondering if the controller is the right place for these calls. In the tutorials I've read the options are always set in the controller but those sandbox examples never have an asynchronous database call happening.

Upvotes: 1

Views: 3548

Answers (1)

Ajay Singh Beniwal
Ajay Singh Beniwal

Reputation: 19037

You should modify three things in your code

  1. The service should return a promise :Refer to documentation of angular for creating promise Inside service resolve the promise when data is recieved from the server
  2. Inside controller just assign proper values to bar and foos when promise is resolved
  3. Remove $scope.apply since now you are modifying the values inside proper angular scope

Link:Use Promise and service together in Angular

Upvotes: 3

Related Questions