简体   繁体   中英

AngularJS - Dropdown shows empty field as selected choice when reloading

So I've got this dropdown in AngularJS and when I first load the page it selects the first item as the default one, which is should. Then when I reload the page the default item is now an empty field. When checking the web console I can see that the selected item has value, but it's not showing in the dropdown. How can this be?

The HTML:

<div>
    <h4>{{ dropdown.name }}</h4>
    <select class="form-control"
            ng-options="item as item.name for item in dropdown.items"
            ng-change="change(dropdown)"
            ng-model="dropdown.selected"
            ng-init="defaultSelected(dropdown)">
    </select>
</div>

and my controller:

angular.module('SimPlannerApp')
.controller('dropdownController', function ($scope) {

    $scope.defaultSelected = function(dropdown){
        if(dropdown.selected === undefined){
            dropdown.selected = dropdown.items[0];
        }

        return dropdown.selected;
    };
});


EDIT

As requested here are the full HTML page along with its controller

<link type="text/css" href="app/modules/functions/dropdown/dropdown.css" rel="stylesheet">

<div class="row dropdown-container" ng-controller="dropdownController">
    <div ng-repeat="dropdown in dropdowns track by $index" ng-include="'dropdown.html'"></div>
</div>
<div class="clearfix"></div>

<!-- Template used for repeating HTML -->
<script type="text/ng-template" id="dropdown.html">
    <div>
        <h4>{{ dropdown.name }}</h4>
        <select class="form-control"
            ng-options="item as item.name for item in dropdown.items"
            ng-change="change(dropdown)"
            ng-model="dropdown.selected"
            ng-init="defaultSelected(dropdown)">
        </select>
    </div>

    <div ng-repeat="dropdown in dropdown.nested track by $index" ng-include="'dropdown.html'"></div>
</script>


angular.module('SimPlannerApp')
.controller('dropdownController', function ($scope, $q, viewService, socketService, Account, storedProcedureService, popService, sharedService) {
    console.warn('LOADING: dropdown.controller.js');
    viewService.setParameters({ qryusr: Account.get().login }, 'parameters');
    initalize();

    $scope.change = function(dropdown){
        if(dropdown.nested){
            updateNested(dropdown);
        } else {
            lastInLine(dropdown);
        }
    };

    $scope.defaultSelected = function(dropdown){
        setSelected(dropdown);

        return dropdown.selected;
    };

    function setSelected(dropdown){
        console.info('dropdown.selected : ', dropdown.selected);

        if(dropdown.selected === undefined){
            dropdown.selected = dropdown.items[0];
        }

        return dropdown;
    };

    function initalize(){
        var masters = $scope.functions.dropdown;    //  $scope found in parent Controller.
        $scope.dropdowns = [];

        for(var i = 0; i < masters.length; i++){
            createDropdown(masters[i], true);
        }
    };

    function lastInLine(dropdown){
        setParams(dropdown);

        setSelected(dropdown);

        viewService.get();
    };

    function updateNested(parent){
        if(parent.nested){
            for(var i = 0; i < parent.nested.length; i++){
                var nested = parent.nested[i];

                setParams(nested, parent);

                createDropdown(nested, false);
            }
        }
    };

    function setParams(dropdown, parent){
        if(dropdown.populate.params){
            var params = dropdown.populate.params;
            for(var key in params){
                var keyValue = sharedService.camelcase(params[key]);

                if((parent) && (parent.selected[keyValue])){
                    viewService.setParameters({ [key]: parent.selected[keyValue] }, 'parameters');
                } else if ((dropdown.selected) && (dropdown.selected[keyValue])){
                    viewService.setParameters({ [key]: dropdown.selected[keyValue] }, 'parameters');
                }
            }
        }
    };

    function createDropdown(dropdown, isMaster){
        var populate = dropdown.populate,
            storedProcedure = storedProcedureService.getParam(populate.storedProcedure),
            view = $scope.view; //  $scope found in parent Controller.

        socketService.connect(storedProcedure.name, storedProcedure.verb, view)
            .then(function(response){
                dropdown.items = setItems(response, populate.itemFieldName);

                setSelected(dropdown);

                setParams(dropdown);

                updateNested(dropdown);

                if(isMaster){
                    $scope.dropdowns.push(dropdown);
                }

                if(dropdown.nested === undefined){
                    lastInLine(dropdown);
                }
            })
            .catch(function(error){
                console.error(error.message, '\ndata : ', error.data);
                popService.set('Connection failed.');
            });
    };

    function setItems(items, fieldName){
        fieldName = sharedService.camelcase(fieldName);
        for(var i = 0; i < items.length; i++){
            items[i].name = items[i][fieldName];
        }
        return items;
    };
});

That's not a standard use of ngInit. I'm surprised that works at all.

As the documentation says, the ngInit directive is used to evaluate an expression in the current scope. What you're doing is calling a function, which not what it's intended for.

Here's the doco: https://docs.angularjs.org/api/ng/directive/ngInit

You'd be better off just removing the ngInit entirely and simplifying your controller.

Here's a live working example:

 angular.module('SimPlannerApp', []) .controller('dropdownController', function($scope) { $scope.dropdown = {}; $scope.dropdown.items = [{name: 'one'}, {name: 'two'}]; $scope.dropdown.name = "Dropdown"; if (!$scope.dropdown.selected) { $scope.dropdown.selected = $scope.dropdown.items[0]; } }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="SimPlannerApp"> <div ng-controller="dropdownController"> <h4>{{ dropdown.name }}</h4> <select class="form-control" ng-options="item as item.name for item in dropdown.items" ng-change="change(dropdown)" ng-model="dropdown.selected"> </select> </div> </div> 

Hello i' ve made a jsfiddle example https://jsfiddle.net/tornado1979/106ps0cf/1/

I use an init function to give a default value to the ng-model.

controller snippet:

 $scope.initialize = function(){
        $scope.dropdown.selected = $scope.dropdown.items[0];//initialize the selected value
   };

   $scope.dropdown = {
   name:'myname',
   items:[{name:'first'},{name:'second'},{name:'third'}],
   selected:null
   };

   $scope.initialize();

   $scope.change = function(){
        console.log('option changed');
   };

Hope helps, good luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM