【问题标题】:s:checkbox fieldValue always true in validation before submittings:checkbox fieldValue 在提交前的验证中始终为真
【发布时间】:2016-05-05 21:14:42
【问题描述】:

我在表单处理中使用 Struts 2 <s:checkbox />,以及 AngularJS 和 jQuery。

在提交之前,我需要验证,直到现在我们在项目中这样做:

当我们按下提交按钮时,这个函数被调用:

$scope.processForm('myForm', '<s:url value="/form/validate.action" />', 
                             '<s:url value="/form/save.action" />');

在哪里

processForm(formId, validateUrl, submitUrl)

是我们定义的函数:

$scope.processForm = function(form, validateUrl, submitUrl) {
    window.scroll(0,0);
    ProccessFormService.processStandarForm(form, validateUrl, submitUrl);
};

此外,我们在全球服务中定义了processStandarForm()

angular.module('ourApp').controller('myFormCtrl', 
                                    function($scope, $modal, ProccessFormService) {
...
}

在役:

(function() {   
    angular.module('ourApp').factory('ProccessFormService', ['$http', function($http) {

    processStandarForm: function(form, validateUrl, submitUrl) {        
        this.processForm(form, validateUrl, submitUrl);
    },

    processForm: function(form, validateUrl, submitUrl, success) {
        
        if ((typeof form) == 'string') {
            form = document.getElementById(form);
        }
        
        var data = this.form2Object(form);
        var ctrl = this;
        
        if (data) {
            if (validateUrl) {
                $http({
                    method  : 'POST',
                    url     : validateUrl,
                    data    : $.param(data),  // pass in data as strings
                    headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  
         // set the headers so angular passing info as form data (not request payload)
                }).success(function() {
                    if (!success) {
                        form.action = submitUrl;
                        form.submit();
                    } else {
                        ctrl.submitAjaxForm(submitUrl, data, success)
                    }
                });
            } else if (submitUrl) {
                if (!success) {
                    form.action = submitUrl;
                    form.submit();
                } else {
                    this.submitAjaxForm(submitUrl, data, success)
                }
            }
        }       
    },
}

基本上,我们提交了两次表单,首先是验证,然后是提交。

我不明白的是如果我在action类中调试,在validate()的函数中,&lt;s:checkbox /&gt;的布尔值始终为真,但在submit()函数中,布尔值正确提交,根据它们被选中/未选中。复选框是这样的:

<div class="col-sm-12 form-checkbox">
     <s:checkbox name = "myForm.married" 
             ng-model = "checkboxModel" 
                value = "<s:property value='%{myForm.married}'/>"
            ng-change = "submitCheckbox();" 
              ng-init = "checkboxModel= %{myForm.married}" 
                theme = "simple"  
          ng-disabled = "anotherFunction()" />
</div>

据我了解,&lt;s:checkbox /&gt;中提交的值为fieldValue="xxx",默认为true。所以我这样做是为了在页面加载之前更改每个checkboxfieldValue。尽管所有脚本都已执行,但没有任何改变。我仍然在验证中完全正确。

$(document).ready(function(){
    $( "input:checkbox" ).each(function(){
        var checkbox = $(this);
        var checked = checkbox.prop("checked");//sera false/true
        if (checked == true){
            checkbox.prop("fieldValue", "true");
        } else {
            checkbox.prop("fieldValue", "false");
        }
    });
});

那么,我怎样才能在提交和验证中都获得正确的 boolean 值? Angular 服务是否写错了?我真的很怀疑,但我无法弄清楚这个问题。

【问题讨论】:

  • 值没有到达目的地。
  • 嗨 Roman C,再次感谢。那么我们怎么知道,为什么?你的意思是验证不起作用?但其他输入/选择组合/单选字段在验证中正确获取它们的值。
  • validate 操作?你的方法也叫validate吗?改变它。
  • @Aleksandr M 名字只是为公司信息隐私发明的面具:)。 Action 类有另一个名称,但方法名为 validate()
  • validate 是一个特殊的方法,换成别的吧。

标签: jquery angularjs forms checkbox struts2


【解决方案1】:

怀疑data 未正确序列化,与角度$http() 一起使用。

如果你想模拟 jQuery 中使用的 $.param(),你应该使用内置的序列化器 $httpParamSerializerJQLike

替代 $http 遵循 jQuery 的 param() 的参数序列化程序 方法逻辑。序列化程序还将按字母顺序对参数进行排序。

要将其用于序列化$http 请求参数,请将其设置为 paramSerializer属性:

$http({
  url: myUrl,
  method: 'GET',
  params: myParams,
  paramSerializer: '$httpParamSerializerJQLike'
});

也可以将其设置为默认的paramSerializer $httpProvider.

此外,您可以注入序列化程序并显式使用它,因为 序列化表单数据以进行提交的示例:

.controller(function($http, $httpParamSerializerJQLike) {
  //...

  $http({
    url: myUrl,
    method: 'POST',
    data: $httpParamSerializerJQLike(myData),
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  });

});

另一种从$.param 转换为角度的方法,您可以在Convert $.param in angularjs 中找到

【讨论】:

  • $http() 服务的有用信息!我不知何故想出了罗马的其他东西。请参阅我自己的答案....对不起您花费的时间。
【解决方案2】:

你可能已经从你的拦截器堆栈中删除(或搞砸了:uncheckedValue=true)一些有用的东西,比如Checkbox Interceptor

org.apache.struts2.interceptor.CheckboxInterceptor 在 默认堆栈。它检查提交给操作的每个表单参数 如果它找到一个前缀为 _checkbox 的,它会插入一个值 一个参数,其名称来自 _checkbox 的后缀,如果它 不存在。插入的默认值为 false 但这可以是 通过在拦截器上设置 uncheckedValue 参数进行更改。

这意味着一个复选框可以伴随一个隐藏的输入 同名但前缀为_checkbox,这样如果复选框不是 在表单上检查该操作仍将收到一个值而不是 不为 unchecked 提供值的默认 HTML 操作 复选框。

【讨论】:

  • 谢谢,如果我理解得很好,你的意思是我在某个地方设置了uncheckedValue=true。但我不知道如何设置这个值,据我所知,拦截器保持不变。请告诉我如何在我的项目中找到它,因为完整搜索不会返回任何结果。
  • 那么可能不是这样,但是为了消除疑问,请通过添加拦截器堆栈来更新您的问题。还要指定复选框是否在两个操作中都为真,或者仅在验证一个中
  • 感谢@Andrea Ligios。我没有使用拦截器,至少我发现没有在任何.xml 文件中明确设置拦截器。
【解决方案3】:

我自己已经解决了这个问题。它就在这里:

var data = this.form2Object(form);

注意到form2Object(form)是另一个函数,我对此进行了深入研究,发现这个函数正在序列化表单,手动将其转换为对象,并且没有正确处理&lt;input type="checkbox" /&gt;

form2Object: function(form) {

    var data = null;
    if ((typeof form) == 'string') {
        form = document.getElementById(form);
    }
    if (form) {
        data = new Object();
        for (var i = 0; i < form.elements.length; i++) {
            if ( (form.elements[i].tagName.toUpperCase() == 'INPUT') || form.elements[i].tagName.toUpperCase() == 'TEXTAREA') {
//here it considers `<input type="checkbox" />` as normal `<input />`, and will submit its `value=xxx` in validation, and it will always be `true` due to `<s:checkbox />`. 
//But it will be correct in real submission because before that, we don't go through here.
                data[form.elements[i].name] = form.elements[i].value;
            } else if (form.elements[i].tagName.toUpperCase() == 'SELECT') {
                data[form.elements[i].name] = form.elements[i].value;
            }
        }
    }
    return data;
}

所以我把它改成了这样:

form2Object: function(form) {

    var data = null;

    if ((typeof form) == 'string') {
        form = document.getElementById(form);
    }
    if (form) {
        data = new Object();
        for (var i = 0; i < form.elements.length; i++) {
            if ( (form.elements[i].tagName.toUpperCase() == 'INPUT' &&
                form.elements[i].type.toUpperCase() != 'CHECKBOX')
                    || 
                form.elements[i].tagName.toUpperCase() == 'TEXTAREA') {
                data[form.elements[i].name] = form.elements[i].value;
            } else if (form.elements[i].tagName.toUpperCase() == 'SELECT') {
                data[form.elements[i].name] = form.elements[i].value;
            } else if (form.elements[i].tagName.toUpperCase() == 'INPUT' && 
                    form.elements[i].type.toUpperCase() == 'CHECKBOX') {
                var checkbox = $(form.elements[i]);
                if (checkbox.prop("checked") == true){
                    data[form.elements[i].name] = true;
                } else if (checkbox.prop("checked") == false){
                    data[form.elements[i].name] = false;
                }
            }
        }
    }
    return data;
}

但是,阅读@Roman C 的答案,我意识到使用内置函数序列化表单可能会更好。所以我接受了他的回答。

【讨论】:

    猜你喜欢
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    • 2019-07-12
    • 2016-01-20
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 2016-12-30
    相关资源
    最近更新 更多