You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AngularJS升级ui-select后下拉框始终向后端传'true'问题排查

问题描述

我在开发AngularJS项目时,将组件库从ui-select2升级为ui-select,原ui-select2代码如下:

<select data-ui-select2="{allowClear: true}" ui-select2="clearDropDown" ng-model="isFinalSubmission" data-placeholder="Final Submission Done?" class="padding-left-right-zero">
   <option></option>
   <option value="true">Yes</option>
   <option value="false">No</option>    
</select>

升级后的ui-select代码:

<ui-select style="cursor: pointer;" ng-model="isFinalSubmission" theme="select2" 
class="padding-left-right-zero" search-enabled="true" 
ng-init="options = [{ value: 'true', label: 'Yes' },{ value: 'false' , label: 'No' }]">
   <ui-select-match allow-clear="true" placeholder="Final Submission Done?">{{$select.selected.label}}</ui-select-match>
   <ui-select-choices repeat="option.value as option in options | filter: $select.search">
      {{option.label}}
   </ui-select-choices>
</ui-select>

<div class="col-sm-5">
   <br />
   <button type="button" class="btn btn-sm btn-primary pull-right" style="border-radius:5px" ng-click="loadGrid()">Search</button>
</div>

当前问题:下拉框选择值能正常显示,但执行操作时,发送到后端的始终是初始固定值true,选择“No”时后端仍收到true。

对应的控制器核心代码片段:

(function (window, angular, undefined) {
    'use strict';
    angular.module('angularModule.controllers').controller('searchHoldingCtrl', ['$scope', '$compile', '$window', 'ajaxCall', '$controller', 'checkPermissions', '$rootScope', '$location', 'permissionCheckService', 'fileDownloadService', 'holdingColumns','$timeout', function ($scope, $compile, $window, ajaxCall, $controller, checkPermissions, $rootScope, $location, permissionCheckService, fileDownloadService, holdingColumns, $timeout) {
        permissionCheckService.check('ETT_Reports_View');
        $controller('commonCtrl', { $scope: $scope });
        $scope.selectIsinList();
        $scope.searchIsin = { Id: null };
        $scope.selectOptionsEmployeePromise();
        $scope.searchEmployee = { Id: null };
        $scope.searchTimePeriod = {}
        $scope.searchClass = {}
        $scope.searchParentCompany = {};
        $scope.copyHoldingToOpening = {};
        $scope.searchTimePeriodType = {};
        $scope.isFinalSubmission = true; // 初始布尔值
        $scope.isTimePeriodShow = false;
        $scope.isHoldingdateShow = false;
        $scope.loadGrid();

        $scope.loadGrid = function (reset) {
            $scope.reset = reset ? true : false;
            $scope.isGridIsShown = true;
            $scope.gridconfig.isLocalData = false;
            $timeout(function () {
                $scope.$broadcast('LoadKendoGridEvent')
            })
        };

        $scope.ExportAnnualHoldingPDFReport = function () {
            var url = "/ETT/Reports/ExportAnnualHoldingPDFReport";
            var emp = isValidObject($scope.searchEmployee) ? $scope.searchEmployee.Id : null;
            var time = isValidObject($scope.searchTimePeriod) ? $scope.searchTimePeriod.Id : null;
            var holdingDate = isValidObject($scope.model.searchHoldingDate) ? $scope.model.searchHoldingDate : "";
            var timePeriodTypeId = isValidObject($scope.searchTimePeriodType) ? $scope.searchTimePeriodType.Id : null;
            var isin = isValidObject($scope.searchIsin) ? $scope.searchIsin.Id : null;
            var classId = isValidObject($scope.searchClass) ? $scope.searchClass.Id : null;
            var parentCompanyId = isValidObject($scope.searchParentCompany) ? $scope.searchParentCompany.Id : null;
            var isFinalSubmission = isValidObject($scope.isFinalSubmission) ? $scope.isFinalSubmission : null;
            $rootScope.viewLoading = true;

            fileDownloadService.downloadFilePost(url, JSON.stringify({
                emp: emp,
                timePeriod: time,
                holdingDate: holdingDate,
                timePeriodTypeId: timePeriodTypeId,
                isin: isin,
                classId: classId,
                parentCompanyId: parentCompanyId,
                isFinalSubmission: isFinalSubmission
            })).then(function (data) {
                if (!angular.isUndefined(data) && data.IsError == true) {
                    alertify.error(data.Message);
                    $rootScope.viewLoading = false;
                    return;
                }
                else {
                    $rootScope.viewLoading = false;
                }
            });
        }

        //Search
        $scope.gridconfig.getData = function (e) {
            $scope.gridconfig.isLocalData = true;
            $scope.model.RowsPerPage = $scope.reset ? 20 : e.data.pageSize;
            $scope.model.PageNumber = $scope.reset ? 1 : e.data.page;

            var emp = $scope.searchEmployee == undefined ? null : $scope.searchEmployee.Id;
            var time = $scope.searchTimePeriod == undefined ? null : $scope.searchTimePeriod.Id;
            var holdingDate = $scope.model.searchHoldingDate == undefined ? "" : $scope.model.searchHoldingDate;
            var timePeriodTypeId = $scope.searchTimePeriodType == undefined ? null : $scope.searchTimePeriodType.Id;
            var isin = $scope.searchIsin == undefined ? null : $scope.searchIsin.Id;
            var classId = $scope.searchClass == undefined ? null : $scope.searchClass.Id;
            var parentCompanyId = $scope.searchParentCompany == undefined ? null : $scope.searchParentCompany.Id;
            var isFinalSubmission = $scope.isFinalSubmission == undefined ? null : $scope.isFinalSubmission;
            $rootScope.viewLoading = true;
            ajaxCall.get('/ETT/Reports/SearchHoldings?emp=' + emp + '&timePeriod=' + time + '&holdingDate=' + holdingDate + '&timePeriodTypeId=' + timePeriodTypeId + '&isin=' + isin + '&classId=' + classId +
                '&parentCompanyId=' + parentCompanyId + '&isFinalSubmission=' + isFinalSubmission).then(function (data) {
                    if (angular.isUndefined(data) && data == null) {
                        $scope.holdingDataSource = [];
                        return;
                    }
                    if (!data.IsError) {
                        $scope.holdingDataSource = data.SearchResults;
                        $scope.gridconfig.ds = getRecordsForPage($scope.holdingDataSource, $scope.model.PageNumber, $scope.model.RowsPerPage);
                        $scope.gridconfig.dataCount = $scope.holdingDataSource.length;
                        e.success({ data: $scope.gridconfig.ds, total: $scope.gridconfig.dataCount });
                        $rootScope.viewLoading = false;
                    }
                    else {
                        alertify.error(data.Message)
                        $rootScope.viewLoading = false;
                    }
                });
        };

    }]);
})(window, window.angular);

已尝试操作:

  • 查阅ui-select文档确认配置正确
  • 验证isFinalSubmission是否包含预期数据

预期行为:下拉框正确反映选中选项,向后端发送对应值。


问题原因与解决方案

核心原因

ui-select中repeat="option.value as option in options"会将选中的option.value(字符串类型的'true'/'false')绑定到ng-model,但控制器中初始值$scope.isFinalSubmission = true是布尔类型。AngularJS的模型绑定会因为类型不匹配导致更新失败,视图显示正常但实际模型值未被修改。

解决步骤

方案1:统一为字符串类型(适配现有选项配置)

  1. 修改控制器初始值为字符串类型,和ui-select选项的value一致:
    $scope.isFinalSubmission = 'true'; // 替换原来的布尔值true
    
  2. 检查isValidObject函数逻辑,确保它能正确识别字符串类型的'true'/'false',避免在请求中被错误替换为null。

方案2:统一为布尔类型(适配后端接收需求)

如果后端期望接收布尔类型参数,调整如下:

  1. 修改ui-select的options,将value设为布尔值:
    ng-init="options = [{ value: true, label: 'Yes' },{ value: false , label: 'No' }]"
    
  2. 保持repeat表达式不变,控制器初始值维持布尔类型$scope.isFinalSubmission = true,此时模型绑定无类型冲突。

验证方法

在控制器中添加监听,确认模型值是否正确更新:

$scope.$watch('isFinalSubmission', function(newVal, oldVal) {
    console.log('isFinalSubmission updated:', newVal, typeof newVal);
});

选择下拉选项后,查看控制台输出,确认新值和类型符合预期。


内容的提问来源于stack exchange,提问作者Abhishek Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 07:02:04