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."); }); }
问题原因及修复方案
核心原因
- 回调调用时机错误:调用
getBatchDetails(batch.id, showBatchDetails())时直接执行了showBatchDetails(),导致模态框在接口请求返回数据前就已渲染完成。此时selectedCommodityBatch未赋值,ng-init和ng-value无法正确填充表单;后续数据返回后虽绑定了ng-model,但AngularJS表单验证未触发重新校验,字段仍处于pristine状态。 ng-init和ng-value的使用误区:这两个指令仅在元素初始化时执行一次,无法响应selectedCommodityBatch的后续变化,无法动态更新表单数据。- 变量名混用:代码中
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
相关产品推荐
相关产品推荐

