1

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.

1 Answer 1

3

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

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, I'll look more into promises. (I'll upvote your answer once I have the reputation to do so...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.