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

AngularJS表单首次点击验证无效,二次点击恢复正常问题求助

AngularJS模态框表单首次加载验证异常问题

我用AngularJS开发应用,通过接口获取数据预填表单字段,但首次点击打开模态框时,数据已成功获取,但表单验证显示valid为false、pristine为true;第二次点击则完全正常,仅首次操作出现该问题。

首次点击异常表现:

  • 表单字段已填充数据,但验证状态显示字段为未修改(pristine=true)
  • 表单整体valid为false,提交按钮因UpdateCommodity.$error.required处于禁用状态

二次点击正常表现:

  • 表单字段正常填充,验证状态显示字段已修改(pristine=false)
  • 表单整体valid为true,提交按钮可正常点击

模态框HTML代码(modal.html)

<div class="modal-body" >
    <div class="row centered-form">
    <div class="col-md-12">
        <div class="panel panel-default">
            <div class="panel-heading">
                <div ng-show="isUpdateCommodityBatch">
                    <span class="modalHeader">Update Commodity Batch</span>
                    <i class="fa fa-times-circle-o fa-2x closeIconForModal" ng-click="closeUpdateCommodityBatchModal()"></i>
                </div>
                 </div>
                 <div ng-hide="isUpdateCommodityBatch">
                 <div class="panel-heading">
                    <span class="modalHeader">Update Commodity Batch</span>
                    <i class="fa fa-times-circle-o fa-2x closeIconForModal" 
                    ng-click="closeUpdatedcommodityModal()" ></i>
                     </div>
                 </div>
                <div class="panel-body">
                    <div ng-show="isUpdateCommodityBatch">
                        <form name="UpdateCommodity" role="form" novalidate >
                            <div class="row">
                                <div class="col-xs-6 col-sm-6 col-md-6">
                                    <label>Commodity name</label>
                                    <div class="form-group" ng-class="{ 'has-error' : UpdateCommodity.commodityname.$error.required && !UpdateCommodity.commodityname.$pristine, 'has-success' : UpdateCommodity.commodityname.$error.required && !UpdateCommodity.commodityname.$pristine}">
                                    <input  type="text" name="commodityname"  class="form-control input-sm" ng-value="selectedCommodityBatch.dc_commodity.commodity.name" ng-init="updateCommoditybatch.name=selectedCommodityBatch.dc_commodity.commodity.name" placeholder="commodity Name" ng-model="updateCommoditybatch.name" required>
                                    </div>
                                <div class=" col-md-12">
                                    <p class="help-block">
                                        <span ng-show="UpdateCommodity.commodityname.$error.required && !UpdateCommodity.commodityname.$pristine">Commodity name is required.</span>
                                    </p>
                                </div>
                                </div>
                                <div class="col-xs-6 col-sm-6 col-md-6">
                                    <label>Commodity Batch ID</label>
                                    <div class="form-group" ng-class="{ 'has-error' : UpdateCommodity.batchId.$error.required && !UpdateCommodity.batchId.$pristine, 'has-success' : UpdateCommodity.batchId.$error.required && !UpdateCommodity.description.$pristine}">
                                    <input  type="text"  ng-model="updateCommoditybatch.batch_id" ng-init="updateCommoditybatch.batch_id=selectedCommodityBatch.batch_id" ng-value="selectedCommodityBatch.batch_id" class="form-control input-sm" placeholder="description" name="batchId" required>
                                    </div>
                                    <div class=" col-md-12">
                                        <p class="help-block">
                                            <span ng-show="UpdateCommodity.description.$error.required && !UpdateCommodity.description.$pristine">commodity description is required.</span>
                                        </p>
                                    </div>
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-xs-6 col-sm-6 col-md-6">
                                    <label>Commodity Batch Price</label>
                                    <div class="form-group" ng-class="{ 'has-error' : UpdateCommodity.commodityBatchPrice.$error.required && !UpdateCommodity.commodityBatchPrice.$pristine, 'has-success' : UpdateCommodity.commodityBatchPrice.$error.required && !UpdateCommodity.commodityBatchPrice.$pristine}">
                                        <input type="number" step="0.01" name="commodityBatchPrice"  class="form-control input-sm" ng-value="selectedCommodityBatch.price" ng-init="updatedCommoditybatch.price=selectedCommodityBatch.price" placeholder="commodity price" ng-model="updatedCommoditybatch.price" required>
                                    </div>
                                    <div class=" col-md-12">
                                        <p class="help-block">
                                            <span ng-show="UpdateCommodity.commodityBatchPrice.$error.required && !UpdateCommodity.commodityBatchPrice.$pristine">Commodity Batch Price is required.</span>
                                        </p>
                                    </div>
                                </div>
                                <div class="col-xs-6 col-sm-6 col-md-6">
                                    <label>Commodity Batch Available Quantity</label>
                                    <div class="form-group" ng-class="{ 'has-error' : UpdateCommodity.availableQuantity.$error.required && !UpdateCommodity.availableQuantity.$pristine, 'has-success' : UpdateCommodity.availableQuantity.$error.required && !UpdateCommodity.availableQuantity.$pristine}">
                                        <input type="number" step="0.01" ng-model="updatedCommoditybatch.availableQuantity" ng-init="updatedCommoditybatch.availableQuantity=selectedCommodityBatch.available_quantity" ng-value="selectedCommodityBatch.available_quantity" class="form-control input-sm" placeholder="available quantity" name="availableQuantity" required>
                                    </div>
                                    <div class=" col-md-12">
                                        <p class="help-block">
                                            <span ng-show="UpdateCommodity.availableQuantity.$error.required && !UpdateCommodity.availableQuantity.$pristine">Available Quantity is Required.</span>
                                        </p>
                                    </div>
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-xs-6 col-sm-6 col-md-6">
                                    <label>Commodity Batch Minimum Order Quantity</label>
                                    <div class="form-group" ng-class="{ 'has-error' : UpdateCommodity.minimumOrderQuantity.$error.required && !UpdateCommodity.minimumOrderQuantity.$pristine, 'has-success' : UpdateCommodity.minimumOrderQuantity.$error.required && !UpdateCommodity.minimumOrderQuantity$pristine}">
                                        <input type="number" name="minimumOrderQuantity"  class="form-control input-sm" ng-init="updatedCommoditybatch.minimumOrderQuantity=selectedCommodityBatch.minimum_order_quantity" ng-value="selectedCommodityBatch.minimum_order_quantity" placeholder="minimum order quantity" ng-model="updatedCommoditybatch.minimumOrderQuantity" required>
                                    </div>
                                    <div class=" col-md-12">
                                        <p class="help-block">
                                            <span ng-show="UpdateCommodity.minimumOrderQuantity.$error.required && !UpdateCommodity.minimumOrderQuantity.$pristine">Minimum Order Quantity is Required.</span>
                                        </p>
                                    </div>
                                </div>
                                <div class="col-xs-6 col-sm-6 col-md-6">
                                    <label>Commodity Batch Expiry Date</label>
                                    <div class="form-group" ng-class="{ 'has-error' : UpdateCommodity.expiryDate.$error.required && !UpdateCommodity.expiryDate.$pristine, 'has-success' : UpdateCommodity.expiryDate.$error.required && !UpdateCommodity.expiryDate.$pristine}">
                                        <input type="date"  ng-model="updatedCommoditybatch.expiryDate" ng-init="updatedCommoditybatch.expiryDate=selectedCommodityBatch.expiry_date" ng-value="selectedCommodityBatch.expiry_date" class="form-control input-sm" placeholder="expiry_date" name="expiryDate" required>
                                    </div>
                                    <div class=" col-md-12">
                                        <p class="help-block">
                                            <span ng-show="UpdateCommodity.expiry_date.$error.required && !UpdateCommodity.expiryDate.$pristine">Expiry Date is Required.</span>
                                        </p>
                                    </div>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
                <div class="panel-footer">
                    <div class="row">{{UpdateCommodity.$error.required}}
                        <div class="col-xs-12 col-sm-12 col-md-12">
                            <button class="btn btn-block formSubmitButton" ng-disabled="UpdateCommodity.$error.required" ng-click="submitUpdateCommodityBatch(selectedCommodityBatch)">Update Commodity </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

回调函数代码

function showBatchDetails(){
  //getBatchDetails funtion sets the selectedCommodityBatch
  $scope.currentUserTypeForModals();
  $scope.isUpdateCommodityBatch=true;
  $scope.errorText="";
  $scope.updatedCommoditybatch = {};
  $scope.updateCommodityBatchModal= $uibModal.open({
    animation: false,
    ariaLabelledBy: 'modal-title',
    ariaDescribedBy: 'modal-body',
    templateUrl: 'views/CommonModals/updateCommodityBatchModal.html',
    scope: $scope,                
    size: 'lg',     
    show: true,
    keyboard: false,
    backdrop: 'static'    
  });
}

$scope.updateCommodityBatch=function(batch){
  getBatchDetails(batch.id, showBatchDetails())
}

getBatchDetails()代码

function getBatchDetails(batch_id,callback) {
  var accessToken = localStorage.getItem('access_token')

  var form = {
    "batchId": parseInt(batch_id),
  };

  $scope.errorText = "";
  
  var request = {
    method:'POST',
    url: BASE_URL+'api/commodity/get-batch-details',
    xhrFields: {
      withCredentials: true
    },
    headers:{
      'Content-Type': 'application/json',
      'authorization': `Bearer ${accessToken}`,
    },
    data:form};
    
  $http(request).then(function(response){
    console.log("respnse", response.data)
    if(response.data.status == 'success'){
      $scope.selectedCommodityBatch = response.data.commodity_batch
      if(callback){
        callback();
      }
      // callback(response.data.commodity_batch)
    }
  },function(error){
      $scope.successStatusInfo("Unknown error! Please try again.");
  });
}

问题原因及修复方案

核心原因

  1. 回调调用时机错误:调用getBatchDetails(batch.id, showBatchDetails())时直接执行了showBatchDetails(),导致模态框在接口请求返回数据前就已渲染完成。此时selectedCommodityBatch未赋值,ng-init和ng-value无法正确填充表单;后续数据返回后虽绑定了ng-model,但AngularJS表单验证未触发重新校验,字段仍处于pristine状态。
  2. ng-init和ng-value的使用误区:这两个指令仅在元素初始化时执行一次,无法响应selectedCommodityBatch的后续变化,无法动态更新表单数据。
  3. 变量名混用:代码中updateCommoditybatch和updatedCommoditybatch变量名不一致,导致数据绑定失败。

修复步骤

1. 修正回调传递方式,确保模态框在数据返回后打开

修改$scope.updateCommodityBatch函数,传递回调函数引用而非直接执行:

$scope.updateCommodityBatch=function(batch){
  // 传递函数引用,而非直接调用执行
  getBatchDetails(batch.id, showBatchDetails)
}

2. 移除ng-init和ng-value,直接通过模型赋值填充数据

在showBatchDetails函数中,将接口返回的数据直接赋值给表单绑定的模型:

function showBatchDetails(){
  $scope.currentUserTypeForModals();
  $scope.isUpdateCommodityBatch=true;
  $scope.errorText="";
  // 统一变量名,直接赋值表单模型
  $scope.updatedCommoditybatch = {
    name: $scope.selectedCommodityBatch.dc_commodity.commodity.name,
    batch_id: $scope.selectedCommodityBatch.batch_id,
    price: $scope.selectedCommodityBatch.price,
    availableQuantity: $scope.selectedCommodityBatch.available_quantity,
    minimumOrderQuantity: $scope.selectedCommodityBatch.minimum_order_quantity,
    expiryDate: $scope.selectedCommodityBatch.expiry_date
  };
  $scope.updateCommodityBatchModal= $uibModal.open({
    animation: false,
    ariaLabelledBy: 'modal-title',
    ariaDescribedBy: 'modal-body',
    templateUrl: 'views/CommonModals/updateCommodityBatchModal.html',
    scope: $scope,                
    size: 'lg',     
    show: true,
    keyboard: false,
    backdrop: 'static'    
  });
}

同时修改模态框input元素,删除ng-init和ng-value:

<!-- 示例:商品名称字段 -->
<input type="text" name="commodityname" class="form-control input-sm" 
       placeholder="commodity Name" ng-model="updatedCommoditybatch.name" required>

3. 强制触发表单校验(可选)

若修改后仍存在验证状态未更新的情况,可在模态框打开后手动触发校验:

$scope.updateCommodityBatchModal= $uibModal.open({
  // 原有配置
}).opened.then(function(){
  // 强制触发表单校验,更新状态
  if($scope.UpdateCommodity){
    $scope.UpdateCommodity.$setDirty();
    $scope.UpdateCommodity.$validate();
  }
});

4. 统一变量名

将代码中所有updateCommoditybatch替换为updatedCommoditybatch,避免数据绑定错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 12:05:29