Erik Grosskurth
Erik Grosskurth

Reputation: 3932

AngularJS: Set default select option when using directive to apply select drop down to page


EDIT/UPDATE I have added a plunker for this issue: http://plnkr.co/edit/mlYKJQc7zQR0dsvDswMo


I am loading in data from the previous page into $scope.visit in my page controller. I would like to have a directive that constructs and loads select elements on the page with options from the database. Here is what I have so far:

app.directive('popList', ['$http', function($http) {
    'use strict';
    var directive = {
        restrict: 'EA',
        link: link,
        scope: {
            popList: '='
        },
        template: function(elem,attrs) {
            return  '<select '+
                        'ng-model="'+attrs.model+'" '+
                        'ng-options="option.name for option in ddlOpts track by option.id" '+
                        'required '+
                    '></select>';
        }
    };
    return directive;
    function link(scope, elem, attrs, ctrl) {
        var data = {
                sTableName: attrs.tbl
            };
        $http.post('ddl.asmx/populateDDL',data).
        then(function(response) {
            console.log('This is the value I want to set it to '+scope.$parent.visit.data.state_id);
            //ddlOpts loads with no problem
            scope.ddlOpts = response.data.d;
        });

    }
}]);

Then the HTML looks like this:

<div style="width: 5%" class="tableLabel">State</div>
<div
    style="width: 27%;"
    class="tableInput"
    model="visit.data.state_id"
    tbl="tblStates"
    pop-list="states"
>
</div>

Essentially I pass in the name of the table that holds my drop down options. I also pass in the model which will tell the select what value is the default (if it has one.)

I can get the data loaded into the select element as options with no problem. I have checked the ng-model to ensure that I have the correct value to match to the ng-value. I have tried ng-repeat then started all over with ng-options but I cannot for the life of me get the select option to set the default to the ng-model value.

I am starting to think its because the when the select is constructed its in a different scope than the where the controller set the data to $scope.visit. Can someone explain why the two scopes don't recognize one another or just explain why I can't set my default value to the value stored in the ng-model?

Here is the page controller just in case you need for reference:

app.controller('demographicsFormCtrl', function($rootScope, $scope, $cookies, $http, $window, $route) {
    if (
        typeof $cookies.get('visitTrack') === 'undefined' ||
        typeof $cookies.get('visitInfo') === 'undefined' ||
        typeof $cookies.get('visitData') === 'undefined'
    ){
        window.location.href = "#/";
        return false;   
    }
    $scope.visit = {};
    $scope.visit.track = JSON.parse($cookies.get('visitTrack'));
    $scope.visit.data = JSON.parse($cookies.get('visitData'));
    $scope.visit.info = JSON.parse($cookies.get('visitInfo'));
    $rootScope.preloader = true;
    console.log('controller set');

});

Upvotes: 0

Views: 742

Answers (2)

Erik Grosskurth
Erik Grosskurth

Reputation: 3932

First, thanks to Ravi as I couldn't have found the answer without him...

OK so here is the skinny on doing this in a directive. The database was sending down an object with just a key and an integer value. Angular, when using ng-options, was creating an object with k/v pairs of id-int, name-string... As you can see here in this plunk when I converted the database data (MANUALLY) to match the outcome of the selected option it worked like a charm...

See it here: http://plnkr.co/edit/mlYKJQc7zQR0dsvDswMo

Essentially when trying to change the value of your directive created just make sure the data object in ng-model matches the data object created by ng-options...

or if you have the same issue with the served data you can write in something after you set ddlOpts to set based on the int sent from the DB like so:

app.directive('popList', ['$http', function($http) {
    'use strict';
    var directive = {
        restrict: 'EA',
        scope: {
            model: '='
        },
        template: function(elem,attrs) {
            return  '<select '+
                        'ng-model="model" '+
                        'ng-options="option.name for option in ddlOpts track by option.id" '+
                        'required '+
                    '></select>';
        },
        link: link
    };
    return directive;
    function link(scope, elem, attrs) {
        var defaultInt;
        if (typeof scope.model === "number"){
            defaultInt = scope.model;
        }else{
            defaultInt = parseInt(scope.model);
        }
        var data = {
                sTableName: attrs.tbl
            };
        $http.post('/emr4/ws/util.asmx/populateDDL',data).
        then(function(response) {
            scope.ddlOpts = response.data.d;
// THIS LINE BELOW HERE SETS THE VALUE POST COMPILE
            angular.forEach(scope.ddlOpts, function (v, i) {
                if (v.id === defaultInt) {
                    scope.model = v;
                }
            });
        });

    }
}]);

iTS ALWAYS BETTER AS A RULE OF THUMB TO HAVE YOUR DATA COMING FROM THE db MATCH WHAT ANGULAR CREATES BUT THAT IS NOT ALWAYS SO...

Upvotes: -1

Ravi Teja
Ravi Teja

Reputation: 1107

 template: function(elem,attrs) {
            return  '<select '+
                        'ng-model="'+attrs.model+'" '+
                        'ng-options="option.name for option in ddlOpts track by option.id" '+
                        'required '+
                    '></select>';
        }

In the above template you have ddlOpts, which I believe is an array of objects. And you are displaying name in drop down and storing option in ng-model when user selects one of the name.

For attrs.model, you are passing data from the main view model="visit.data.state_id". So, you are passing just an id to set the default option.

If you want to set an default option, you have to pass an object matching one of the objects of ddlOpts.

Also note that if you try to pass an object to model="visit.data.state_id", I don't think you can read an object inside directive by attrs.model, since model="" holds a string.

Probably, you have add one more isolated scope binding in your directive.

 scope: {
            popList: '=',
            model: '='
        },

In HTML

template: function(elem,attrs) {
            return  '<select '+
                        'ng-model="'+model+'" '+
                        'ng-options="option.name for option in ddlOpts track by option.id" '+
                        'required '+
                    '></select>';
        }

Upvotes: 1

Related Questions