Search code examples
angularjsng-options

Default angularjs ng-option when data is returned from a service


The normal solutions I've seen for this so far haven't been working. My controller returns the list of options from a service and populates the select element without any problems but I haven't been able to set a default value. The closest I've come returned an error: Cannot read property '0' of undefined with the code $scope.new_account.account_type = $scope.new_account.account_type[0];. With that error I assumed that the object just wasn't ready yet so I used a resolve to return my service data.

.when('/accounts/new/', {
    controller: function ($scope, accountTypes) {
        $scope.accountTypes = accountTypes;
        $scope.new_account.account_type = accountTypes[0];
    },
    resolve: {
        accountTypes: function (AccountService) {
            return AccountService.getAccountTypes();
        }
    }
})

But this, along with similar solutions, have had no affect. The select element gets populated but the default option is blank. I would prefer to set a default option rather than use a "please select" default with the ? value.

I've also tried

controller: function ($scope, AccountService) {
    $scope.accountTypes = AccountService.getAccountTypes();
}

With various implementations of $scope and ng-init...

<select ng-model="new_account.account_type" ng-options="type.id as type.name for type in accountTypes" 
    ng-init="new_account.account_type='General'">

    ng-init="new_account.account_type.name='General'">

    ng-init="new_account.account_type=0">

Any thoughts to help set a default value for this?

As requested, the accountTypes returns [{"id":1, "name":"General"}, {"id":2, "name":"Super"}, {"id":3, "name":"Trial"}


Solution

  • Try this approach:

    HTML

    <div ng-controller="fessCntrl">
        <select ng-model="selectedItem" ng-options="selectedItem.name as selectedItem.name for selectedItem in values"></select>selectedItem: {{selectedItem}}
    </div>
    

    JS

    var fessmodule = angular.module('myModule', ['ngResource']);
    
    fessmodule.controller('fessCntrl', function ($scope, Data, $timeout) {
        Data.loadData().then(function (result) {
    
            $timeout(function () {
                $scope.values = result;
                $scope.selectedItem = $scope.values[0].name;
            }, 2000); // dummy, to simulate delay 
        },
    
        function (result) {
            alert("Error: No data returned");
        });
    });
    fessmodule.$inject = ['$scope', 'Data', '$timeout'];
    
    
    fessmodule.service('Data', ['$resource', '$q', function ($resource, $q) {
        this.values = [{
            "id": 1,
                "name": "General"
        }, {
            "id": 2,
                "name": "Super"
        }, {
            "id": 3,
                "name": "Trial"
        }];
    
         this.loadData = function() {
         this.deferred = $q.defer();
         this.deferred.resolve(this.values);
    
          return this.deferred.promise;
        };   
    }]);
    

    Demo Fiddle

    Sounds like you have problem AccountService. Above code with service is work

    However if I'll write service by this way:

    fessmodule.service('Data', ['$resource', '$q', function ($resource, $q) {
        this.values = [{
            "id": 1,
                "name": "General"
        }, {
            "id": 2,
                "name": "Super"
        }, {
            "id": 3,
                "name": "Trial"
        }];
    
    
        this.factory = {
            loadData: function (selectedSubject) {
                this.deferred = $q.defer();
                this.deferred.resolve(this.values);
    
                return this.deferred.promise;
            }
        }
        return this.factory;
    }]);
    

    I get error: TypeError: Cannot read property '0' of undefined Fiddle