angularjs - ng-model 未更新 Angular ui-bootstrap 模式中的选择下拉列表

标签 angularjs modal-dialog angular-ui-bootstrap html-select

请查看实际问题:
Working Plunker

我有一个用于添加人员信息的网页。它应该允许添加/编辑/删除该人的多个地址。

  1. 页面上有一个“添加新地址”按钮,可打开一个模式对话框来输入地址信息。

  2. 单击模式对话框中的“添加地址”按钮会将此地址添加到页面的地址列表中。

  3. 添加地址后,用户可以单击“编辑”按钮进行编辑。这就是我遇到问题的地方。

出于某种原因,在编辑地址时,地址类型和状态的下拉列表不会使用模型值进行更新,即使这些值似乎已设置并提供。

为此,我使用 Angular 1.6.2Angular-ui-bootstrap 2.5.0

最佳答案

这是因为您使用 ng-option 作为 ng-options="key as value for (key, value) in $ctrl.statesjson track by key"因此,由于这个键值对, Angular 无法绑定(bind)下拉列表中的值。

使用ng-repeat代替ng-options T

试试这个

<!DOCTYPE html>
<html>

  <head>
    <link data-require="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="67050808131413150617275449544950" rel="noreferrer noopener nofollow">[email protected]</a>" data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
    
    <script data-require="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="177d666272656e572439263926" rel="noreferrer noopener nofollow">[email protected]</a>" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script data-require="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="72101d1d06010600130232415c415c45" rel="noreferrer noopener nofollow">[email protected]</a>" data-semver="3.3.7" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script data-require="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fe9f90998b929f8c948dbecfd0c8d0cc" rel="noreferrer noopener nofollow">[email protected]</a>" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
    <script data-require="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a5d0cc88c7cacad1d6d1d7c4d5e5978b908b95" rel="noreferrer noopener nofollow">[email protected]</a>" data-semver="2.5.0" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script>
      (function (angular)
{

    "use strict";
    // make sure you define all dependencies in main app only
    // you need NOT define these again in dependent components
    var addPerson = angular.module('addPerson', ['ui.bootstrap']);

    // only pass required dependencies in the controller
    // just because you've defined the dependency 'ui.bootstrap' in main app 
    // does NOT necessarily require you to pass it again in the controller 
    // when you do not use it here
    addPerson.controller('myCtrl', ['appFactory', '$scope', '$filter', '$log', function (appFactory, $scope, $filter, $log) {
        
        // functions must be defined before they are called
        var clearPerson = function () {
            $scope.selTitleVal = "";
            $scope.fname = "";
            $scope.mi = "";
            $scope.lname = "";
            return (null);
        };
        
        // clear all entries
        clearPerson();
    }])
    .factory('appFactory', function () {
        return {};
    });
})(window.angular);
    </script>
    <script>
      /*
  Contains following custom angular components:
  1. addresses: Add Address button and displays the list of addresses added with Edit, Delete buttons
  2. addressModal: Modal dialog to add/edit an address
*/

// 1. Angular Component: addresses
(function (angular) {
    'use strict';
    
    var stmpl = '';
    stmpl += '<div><input type="button" class="btn btn-info" value="+ Address" ng-click="$ctrl.open();" /></div>';
    stmpl += '<table class="table table-striped table-bordered" ng-if="$ctrl.isShow">';
    stmpl += '  <thead>';
    stmpl += '    <tr>';
    stmpl += '      <th style="display:none">Address Type Id</th>';
    stmpl += '      <th>Address Type</th>';
    stmpl += '      <th>Address1</th>';
    stmpl += '      <th style="display:none">State Id</th>';
    stmpl += '      <th>Actions</th>';
    stmpl += '    </tr>';
    stmpl += '  </thead>';
    stmpl += '  <tbody>';
    stmpl += '    <tr ng-repeat="x in $ctrl.addresses track by $index">';
    stmpl += '      <td style="display:none">{{ x.addresstypeid }}</td>';
    stmpl += '      <td>{{ x.addresstype }}</td>';
    stmpl += '      <td>{{ x.address1 }}<br />{{ x.address2 }}<br />{{ x.city }} {{ x.state }} {{ x.zip }}</td>';
    stmpl += '      <td style="display:none">{{ x.stateid }}</td>';
    stmpl += '      <td><input type="button" class="btn-xs btn-info" style="width:60px" value="Edit..." ng-click="$ctrl.editAddress($index);" />&nbsp;<input type="button" class="btn-xs btn-info" style="width:60px" value="Delete..." ng-click="$ctrl.deleteAddress($index);" /></td>';
    stmpl += '    </tr>';
    stmpl += '  </tbody>';
    stmpl += '</table>';
    stmpl += '<br />';

    function tableRowController($scope, $uibModal) {
        this.$scope = $scope;

        // these are fields in modal dialog - format for json
        $scope.$ctrl.dataForModal = {
            addresstypeid: '',
            addresstype: '',
            address1: '',
            address2: '',
            city: '',
            stateid: '',
            state: '',
            zip: ''
        };

        $scope.$ctrl.title = "Addresses";
        $scope.$ctrl.addresses = [];
        $scope.$ctrl.isShow = false;   

        // below is how you call the dependent component 'addressModal'
        // +Address is button's click event is wired to this
        $scope.$ctrl.open = function () {

            $scope.$ctrl.title = "Add New Address";
            // read documentation for 'ui.bootstrap.modal'
            // open the modal dialog for Add Address
            $uibModal.open({

                // addressModal.init() - initialize the modal dialog
                component: "addressModal",
                //windowClass: "my-dialog",
                resolve: {
                    modalData: function () {
                        return $scope.$ctrl.dataForModal;
                    },
                    title: function(){
                        return $scope.$ctrl.title;
                    }
                }
            }).result.then(function (result) {
                $scope.$ctrl.result = result;
                console.info(result);
                $scope.$ctrl.addAddress();
            }, function (reason) {
                // addressModal.closeAddress() is invoked here - same as cancel the modal dialog event
            });
        };

        $scope.$ctrl.addAddress = function () {
            $scope.$ctrl.addresses.push({
                addresstypeid: $scope.$ctrl.result.addresstypeid,
                addresstype: $scope.$ctrl.result.addresstype,
                address1: $scope.$ctrl.result.address1,
                address2: $scope.$ctrl.result.address2,
                city: $scope.$ctrl.result.city,
                stateid: $scope.$ctrl.result.stateid,
                state: $scope.$ctrl.result.state,
                zip: $scope.$ctrl.result.zip
            });
            $scope.$ctrl.isShow = true;
        }

        $scope.$ctrl.deleteAddress = function ($index) {
            if (confirm("Do you want to delete this address?\r\nOK: Yes     Cancel: No")) {
                $scope.$ctrl.addresses.splice($index, 1);
                if ($scope.$ctrl.addresses.length > 0) $scope.$ctrl.isShow = true;
                else $scope.$ctrl.isShow = false;
            }
        }

        $scope.$ctrl.editAddress = function ($index) {
            $scope.$ctrl.title = "Edit Address";
            $scope.$ctrl.dataForModal = {
                addresstypeid: $scope.$ctrl.addresses[$index].addresstypeid,
                addresstype: $scope.$ctrl.addresses[$index].addresstype,
                address1: $scope.$ctrl.addresses[$index].address1,
                address2: $scope.$ctrl.addresses[$index].address2,
                city: $scope.$ctrl.addresses[$index].city,
                stateid: $scope.$ctrl.addresses[$index].stateid,
                state: $scope.$ctrl.addresses[$index].state,
                zip: $scope.$ctrl.addresses[$index].zip
            };
            
            $uibModal.open({
                // addressModal.init() - initialize the modal dialog
                component: "addressModal",
                scope: $scope,
                resolve: {
                    modalData: function () {
                        $scope.$ctrl.dataForModal.addresstypeid = "102";
                        $scope.$ctrl.dataForModal.addresstype = "PO Box";
                        return $scope.$ctrl.dataForModal;
                    },
                    title: function () {
                        return $scope.$ctrl.title;
                    }
                }
            }).result.then(function (result) {

                $scope.$ctrl.result = result;
                console.info(result);
                
                $scope.$ctrl.addresses[$index].addresstypeid = $scope.$ctrl.result.addresstypeid;
                $scope.$ctrl.addresses[$index].addresstype = $scope.$ctrl.result.addresstype;
                $scope.$ctrl.addresses[$index].address1 = $scope.$ctrl.result.address1;
                $scope.$ctrl.addresses[$index].address2 = $scope.$ctrl.result.address2;
                $scope.$ctrl.addresses[$index].city = $scope.$ctrl.result.city;
                $scope.$ctrl.addresses[$index].stateid = $scope.$ctrl.result.stateid;
                $scope.$ctrl.addresses[$index].state = $scope.$ctrl.result.state;
                $scope.$ctrl.addresses[$index].zip = $scope.$ctrl.result.zip;
                $scope.$ctrl.isShow = true;

            }, function (reason) {
                // addressModal.closeAddress() is invoked here - same as cancel the modal dialog event
            });
        }
    }

    angular.module('addPerson').component('addresses', {
        bindings: { title: '<' },   // two way data-binding
        template: stmpl,
        controller: tableRowController
    });    

})(window.angular);

// 2. Angular Component: addressModal
(function (angular) {
    var stmpl = "";
    stmpl += '<!-- MODAL DIALOG: Add Address -->';
    stmpl += '      <div class="modal-content">';
    stmpl += '          <div class="modal-header">';
    stmpl += '              <button type="button" class="close" data-dismiss="modal" ng-click="$ctrl.closeAddress();">&times;</button>';
    stmpl += '              <h4 class="modal-title">{{ $ctrl.title }}</h4>';
    stmpl += '          </div>';
    stmpl += '          <div class="modal-body">';
    stmpl += '            <div class="row form-group">';    
    stmpl += '              <label class="control-label col-md-2" for="ddlAddressType">Address Type</label>';    
    stmpl += '              <div class="col-md-10">';
    stmpl += '                <select class="form-control" id="ddlAddressType" name="ddlAddressType" ng-model="$ctrl.modalData.addresstypeid" ng-change="$ctrl.changeAddressType();">';
    stmpl += '                          <option value="">** Select Address Type **</option >';
    stmpl += '                          <option ng-repeat="(id, value) in $ctrl.addresstypesjson track by id" value="{{id}}">{{value}}</option>';
    stmpl += '                </select>';
    stmpl += '                <span class="field-validation-valid text-danger" data-valmsg-for="ddlAddressType" data-valmsg-replace="true"></span>';
    stmpl += '                  </div> ';
    stmpl += '              </div>';
    stmpl += '              <div class="row form-group">';
    stmpl += '                  <label class="control-label col-md-2" for="Address1">Address1</label>';
    stmpl += '                  <div class="col-md-10">';
    stmpl += '                      <input class="form-control text-box single-line" id="Address1" name="Address1" ng-model="$ctrl.modalData.address1" type="text" value="" />';
    stmpl += '                      <span class="field-validation-valid text-danger" data-valmsg-for="Address1" data-valmsg-replace="true"></span>';
    stmpl += '                  </div> ';
    stmpl += '              </div>';
    stmpl += '              <div class="row form-group">';
    stmpl += '                <label class="control-label col-md-2" for="Address1">Address2</label>';    
    stmpl += '                <div class="col-md-10">';
    stmpl += '                  <input class="form-control text-box single-line" id="Address2" name="Address2" ng-model="$ctrl.modalData.address2" type="text" value="" />';
    stmpl += '                  <span class="field-validation-valid text-danger" data-valmsg-for="Address2" data-valmsg-replace="true"></span>';
    stmpl += '                </div>';
    stmpl += '              </div>';
    stmpl += '              <div class="row form-group">';
    stmpl += '                <label class="control-label col-md-2" for="City">City</label>';
    stmpl += '                <div class="col-md-10">';
    stmpl += '                  <input class="form-control text-box single-line" id="City" name="City" ng-model="$ctrl.modalData.city" type="text" value="" />';
    stmpl += '                  <span class="field-validation-valid text-danger" data-valmsg-for="City" data-valmsg-replace="true"></span>';
    stmpl += '                </div>';
    stmpl += '              </div>';
    stmpl += '              <div class="row form-group">';
    stmpl += '                <label class="control-label col-md-2" for="ddlState">State</label>';
    stmpl += '                <div class="col-md-10">{{getValue($ctrl.modalData.stateid)}}';
    stmpl += '                  <select class="form-control" id="ddlState" name="ddlState" ng-model="$ctrl.modalData.stateid">';
    stmpl += '                          <option value="">** Select State **</option>';
    stmpl += '                          <option ng-repeat="(id, value) in $ctrl.statesjson" value="{{id}}">{{value}}</option>';
    stmpl += '                  </select>';
    stmpl += '                  <span class="field-validation-valid text-danger" data-valmsg-for="ddlState" data-valmsg-replace="true"></span>';
    stmpl += '                  </div>';
    stmpl += '              </div>';
    stmpl += '              <div class="row form-group">';
    stmpl += '                <label class="control-label col-md-2" for="Zip">Zip</label>';
    stmpl += '                <div class="col-md-10">';
    stmpl += '                  <input class="form-control text-box single-line" id="Zip" name="Zip" ng-model="$ctrl.modalData.zip" type="text" value="" />';
    stmpl += '                  <span class="field-validation-valid text-danger" data-valmsg-for="Zip" data-valmsg-replace="true"></span>';
    stmpl += '                  </div> ';
    stmpl += '              </div>';
    stmpl += '          </div>';
    stmpl += '          <div class="modal-footer">';
    stmpl += '              <input type="button" value="Add Address" class="btn btn-success" ng-click="$ctrl.addAddress();"/>';
    stmpl += '              <input type="button" value="Close" class="btn btn-default" ng-click="$ctrl.closeAddress();" />';
    stmpl += '          </div>';
    stmpl += '      </div>  <!-- model - content -->';
    
    function tableRowController($scope, $http, $uibModal) {
        this.$scope = $scope;
        //var $ctrl = this;
        $scope.$ctrl.addresstypesjson = {"100": "Home", "101": "Work", "102": "PO Box"};
        $scope.$ctrl.statesjson = {"AN": "Andaman and Nicobar Islands", "AP": "Andhra Pradesh", "AR": "Arunachal Pradesh", "DD": "Daman and Diu", "DH": "Dadra and Nagar Haveli", "DL": "Delhi"};
        
        // Events
        // 1. init - initialize
        $scope.$ctrl.$onInit = function () {
            $scope.$ctrl.modalData = $scope.$ctrl.resolve.modalData;
            $scope.$ctrl.title = $scope.$ctrl.resolve.title;
            
            if ($scope.$ctrl.title != "Edit Address") {
                $scope.$ctrl.modalData.addresstypeid = "";
                $scope.$ctrl.modalData.addresstype = "";
                $scope.$ctrl.modalData.address1 = "";
                $scope.$ctrl.modalData.address2 = "";
                $scope.$ctrl.modalData.city = "";
                $scope.$ctrl.modalData.stateid = "";
                $scope.$ctrl.modalData.state = "";
                $scope.$ctrl.modalData.zip = "";
            }
        }

        // 2. dismiss - cancel model dialog
        $scope.$ctrl.closeAddress = function () {
            $scope.$ctrl.modalInstance.dismiss("cancel");
        }

        // 3. close - add new address and close the dialog
        $scope.$ctrl.addAddress = function () {
            // assign selected text for drop-down list items
            $scope.$ctrl.modalData.addresstype = $scope.$ctrl.addresstypesjson[$scope.$ctrl.modalData.addresstypeid];
            $scope.$ctrl.modalData.state = $scope.$ctrl.statesjson[$scope.$ctrl.modalData.stateid];
            $scope.$ctrl.modalInstance.close($scope.$ctrl.modalData);
        }

        $scope.getValue = function(id){
            debugger
        }

        $scope.$ctrl.changeAddressType = function () {
            console.info("Address Type drop-down list changed");
        }
    }

    // register the component - dependecies automatically follow from app (parent)
    angular.module('addPerson').component('addressModal', {
        bindings: {
            title: '<',
            modalInstance: "<",
            resolve: "<"
        },   // two way data-binding
        template: stmpl,
        controller: tableRowController
    });
})(window.angular);
    </script>
  </head>

  <body>
    <h2>Add New Person</h2>
    <hr />
    <form action="#">
      <div class="form-horizontal"  ng-app="addPerson" ng-controller="myCtrl">
        
        <div class="form-group">
          <label class="control-label col-md-2" for="Title_Title_Title">Title</label>
          
          <div class="col-md-10">
            <select class="form-control" id="Title_Title_Title" name="Title.Title_Title" ng-value="selTitleVal"><option value="">** Select Title **</option>
            <option value="104">Dr.</option>
            <option value="103">Ma&#39;am</option>
            <option value="102">Miss</option>
            <option value="100">Mr.</option>
            <option value="101">Mrs.</option>
            <option value="106">Smt.</option>
            <option value="105">Sri</option>
            </select>
          <span class="field-validation-valid text-danger" data-valmsg-for="Title.Title_Title" data-valmsg-replace="true"></span>
          </div>
        </div>
        
        <div class="form-group">
          <label class="control-label col-md-2" for="Person_FName">First Name</label>
          <div class="col-md-10">
            <input class="form-control text-box single-line" id="Person_FName" name="Person_FName" ng-model="fname" type="text" value="" />
            <span class="field-validation-valid text-danger" data-valmsg-for="Person_FName" data-valmsg-replace="true"></span>
          </div>
        </div>
        
        <div class="form-group">
          <label class="control-label col-md-2" for="Person_MI">MI</label>
          <div class="col-md-10">
            <input class="form-control text-box single-line" id="Person_MI" name="Person_MI" ng-model="mi" type="text" value="" />
            <span class="field-validation-valid text-danger" data-valmsg-for="Person_MI" data-valmsg-replace="true"></span>
          </div>
        </div>
        
        <div class="form-group">
          <label class="control-label col-md-2" for="Person_LName">Last Name</label>
          <div class="col-md-10">
            <input class="form-control text-box single-line" id="Person_LName" name="Person_LName" ng-model="lname" type="text" value="" />
            <span class="field-validation-valid text-danger" data-valmsg-for="Person_LName" data-valmsg-replace="true"></span>
          </div>
        </div>
        
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create Person" class="btn btn-primary" />
            </div>
        </div>

        <div class="container-fluid" style="padding:unset;margin:unset;">
            <div class="row" style="padding:unset;margin:unset;">
                <div class="col-md-12" style="padding:unset;margin:unset;">
                    <addresses id="addresses1" title="'Addresses'"></addresses>
                </div>
            </div>
        </div>

        
      </div>
    </form>

  </body>

</html>

Here是工作中的笨蛋。

关于angularjs - ng-model 未更新 Angular ui-bootstrap 模式中的选择下拉列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43648669/

相关文章:

angularjs - 如何使用Angular cookie存储(和检索)cookie数组

javascript - 在下拉选择中显示 Bootstrap 模式

jquery - 无法禁用 Bootstrap 模式窗口

javascript - 当有人点击 facebook like 按钮后,如何关闭 Bootstrap 模式?

angularjs - 重写 AngularJs DatePicker 弹出窗口以添加新标题

javascript - JsFiddle : Unknown provider: $intervalProvider <- $interval

javascript - 如何在 CSS 过渡中使用 ng-class?

javascript - 对于 Angular JS, curl 到 $http.post()

css - 与 Ionic app + Bootstrap 中的样式混淆

javascript - 将数据从模态传递到主 Controller -(附有Plunker)----在模态中包含自动完成输入框