AngularJS:在使用指令应用 select 下拉到页面时设置默认 select 选项

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


EDIT/UPDATE 我为这个问题添加了一个plunker: http://plnkr.co/edit/mlYKJQc7zQR0dsvDswMo


我正在将上一页的数据加载到我的页面控制器中的 $scope.visit 中。我想要一个指令,该指令使用数据库中的选项在页面上构造和加载 select 元素。这是我目前所拥有的:

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;
        });

    }
}]);

然后 HTML 看起来像这样:

<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>

本质上,我传递了包含下拉选项的 table 的名称。我还传入了模型,它将告诉 select 默认值是什么(如果它有的话)

我可以毫无问题地将数据作为选项加载到 select 元素中。我已经检查了 ng-model 以确保我有正确的值来匹配 ng-value。我已经尝试过 ng-repeat,然后从头开始使用 ng-options,但我终生无法获得 select 选项来将默认值设置为 ng-model 值。

我开始认为这是因为 select 的构建范围与控制器将数据设置为 $scope.visit 的范围不同。有人可以解释为什么这两个范围不能相互识别,或者只是解释为什么我不能将我的默认值设置为存储在 ng-model 中的值吗?

这里是页面控制器,以备不时之需:

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');

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

在上面的模板中你有 ddlOpts,我认为它是一个对象数组。当用户选择其中一个名称时,您在下拉列表中显示 name 并在 ng-model 中存储 option

对于 attrs.model,您正在从 main 视图 model="visit.data.state_id" 传递数据。因此,您只传递一个 id 来设置默认选项。

如果你想设置一个默认选项,你必须传递一个匹配ddlOpts的对象之一的对象。

另请注意,如果您尝试将对象传递给 model="visit.data.state_id",我认为您无法通过 attrs.model 读取指令内部的对象,因为 model="" 持有 string.

您可能在指令中添加了一个独立的作用域绑定。

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

在HTML

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

首先,感谢 Ravi,没有他我找不到答案...

好的,这是在指令中执行此操作的简明扼要。数据库正在发送一个只有一个键和一个整数值的对象。 Angular,当使用 ng-options 时,正在创建一个具有 k/v 对 id-int,name-string 的对象......正如你在我转换数据库数据时在这个 plunk 中看到的那样(MANUALLY ) 来匹配所选选项的结果,它就像一个魅力...

看这里:http://plnkr.co/edit/mlYKJQc7zQR0dsvDswMo

基本上,在尝试更改创建的指令的值时,只需确保 ng-model 中的数据对象与 ng-options 创建的数据对象相匹配...

或者如果您对提供的数据有同样的问题,您可以在设置 ddlOpts 之后写入一些内容,以根据从数据库发送的 int 进行设置,如下所示:

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;
                }
            });
        });

    }
}]);

根据经验,最好让来自数据库的数据与 ANGULAR 创建的内容相匹配,但并非总是如此...