【问题标题】:XPages SSJS Action GroupXPages SSJS 行动组
【发布时间】:2017-06-26 09:03:01
【问题描述】:

我有一个点击按钮的操作组。第一个动作,做一些验证,第二个动作抛出一个确认(你想保存吗?)如果是,第三个动作开始做一些其他的事情。

我遇到的问题是,如果第一个操作的验证失败,我不希望其他 2 个操作运行,所以我不应该得到任何确认等。

如果验证失败,我尝试过中断,并返回 false,但似乎都不起作用。我确定我遗漏了一些明显的东西,并且患有星期一综合症,但我似乎无法解决!

下面的事件处理程序代码,谢谢:

        <xp:eventHandler event="onclick" submit="true"
        refreshMode="complete">
        <xp:this.action>
            <xp:actionGroup>

                <xp:executeScript>
                    <xp:this.script><![CDATA[#{javascript:for (var i = 1; i < viewScope.rows+1; i++) {
print("Starting Array.....");

var fieldName:string = "ObjectiveSelfAssessment" +i;
var fieldName2:string = "ObjectiveDetails" +i;
print ("Field Name: " + fieldName);

var fieldValue = document1.getItemValueString(fieldName);   
var fieldValue2 = document1.getItemValueString(fieldName2); 

print ("Field Value: " + fieldValue);
if (fieldValue =="" || fieldValue==null){
    print("Assessment Empty");
    if(!fieldValue2 =="" || !fieldValue2 == null){
        print("Objective Empty");
        //Do validation
        var o = {};
        o.title = "Validation Failed";
        o.body = "You must enter self assessment details for each objective";
        o.alertIcon = "fa-thumbs-down fa-lg";
        o.autoClose = true;
        o.alertType = "danger";
        requestScope.put("alertServer",o);
        //requestScope.put("validated",false);
        return false;
        break;
    }           
}
}
}]]></xp:this.script>
                </xp:executeScript>
                <xp:confirm>
                    <xp:this.message><![CDATA[#{javascript:"Are you sure you want to submit your self assessment?"}]]></xp:this.message>
                </xp:confirm>

                <xp:executeScript>
                    <xp:this.script><![CDATA[#{javascript:document1.replaceItemValue("rows",viewScope.rows);
//document1.replaceItemValue("status","Self Assessment Completed");
document1.save();
var o = {};
o.title = "Document Saved";
o.body = "This document has been succesfully submitted";
o.alertIcon = "fa-thumbs-up fa-lg";
o.autoClose = true;
o.alertType = "success";
requestScope.put("alertServer",o);
}]]></xp:this.script>
                </xp:executeScript>
            </xp:actionGroup>
        </xp:this.action>
    </xp:eventHandler>

更新 1:操作组的条件代码:

<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
    <xp:this.action>
        <xp:actionGroup>
            <xp:this.condition><![CDATA[#{javascript:for (var i = 1; i < viewScope.rows+1; i++) {
print("Starting Array.....");

var fieldName:string = "ObjectiveSelfAssessment" +i;
var fieldName2:string = "ObjectiveDetails" +i;
print ("Field Name: " + fieldName);

var fieldValue = document1.getItemValueString(fieldName);   
var fieldValue2 = document1.getItemValueString(fieldName2); 

print ("Field Value: " + fieldValue);
if (fieldValue =="" || fieldValue==null){
    print("Assessment Empty");
    if(!fieldValue2 =="" || !fieldValue2 == null){
        print("Objective Empty");
        var o = {};
        o.title = "Validation Failed";
        o.body = "You must enter self assessment details for each objective";
        o.alertIcon = "fa-thumbs-down fa-lg";
        o.autoClose = true;
        o.alertType = "danger";
        requestScope.put("alertServer",o);
        print("FALSE");
        return false;
        break;
    }else{
        print("TRUE");
        return true;
    }               
  }
}
}]]></xp:this.condition>

            <xp:confirm>
                <xp:this.message><![CDATA[#{javascript:"Test11111"}]]></xp:this.message>
            </xp:confirm>
            <xp:executeScript>
                <xp:this.script><![CDATA[#{javascript:document1.replaceItemValue("rows",viewScope.rows);
//document1.replaceItemValue("status","Self Assessment Completed");
document1.save();
var o = {};
o.title = "Document Saved";
o.body = "This document has been succesfully submitted";
o.alertIcon = "fa-thumbs-up fa-lg";
o.autoClose = true;
o.alertType = "success";
requestScope.put("alertServer",o);}]]></xp:this.script>
            </xp:executeScript>
        </xp:actionGroup>
    </xp:this.action></xp:eventHandler>

【问题讨论】:

    标签: xpages xpages-ssjs


    【解决方案1】:

    Paul,我已经接受了您的回答 reg 进行更多手动编码,因为这就是我采用的方法。我正在提交一个答案,以便我可以使用代码格式显示我的解决方案....

    我现在做我的验证客户端 - 获取孩子等的原因是我动态创建/删除字段,这些字段显示为我的文本框的重复控件,所以我不知道元素 ID ......

    var objcolparent = document.getElementById("ObjColOuter").children[0];
    var sacolparent = document.getElementById("SAColOuter").children[0];
    var rows = sacolparent.getElementsByTagName("TEXTAREA").length;
    
    for (var i = 0; i < rows; i++) {
    var saValue = sacolparent.getElementsByTagName("TEXTAREA")[i].value;
    if(saValue ==""){
        var objValue = objcolparent.getElementsByTagName("TEXTAREA")[i].value;
        if(!objValue==""){
            // Validation failed, do client side bootalert
            var o = {};
            o.title = "Validation Failed";
            o.body = "You must enter self assessment details for each objective";
            o.alertIcon = "fa-thumbs-down fa-lg";
            o.alertType = "danger";
            bootAlert.show('alertServer',JSON.stringify(o))
            return false;
            break;
        }
    }
    }
    
    if(confirm("Are you sure you want to submit your self assessment?")){
      return true;
    }else{
      return false;
    }
    

    如果验证成功,它会继续运行我的服务器端内容:

    document1.replaceItemValue("rows",viewScope.rows);
    document1.replaceItemValue("status","Self Assessment Completed");
    document1.save();
    var o = {}
    o.title = "Document Saved";
    o.body = "This document has been succesfully submitted";
    o.alertIcon = "fa-thumbs-up fa-lg";
    o.autoClose = true;
    o.alertType = "success";
    requestScope.put("alertServer",o)
    

    感谢所有贡献的人!

    【讨论】:

      【解决方案2】:

      操作组对于基本的、最少编码的操作很有用。但是,正如您所看到的,“更容易”的点击式、配置驱动的操作意味着灵活性更难。手动编码可能看起来更难,但更容易灵活。如果您在 XPage 上添加确认操作、预览它并查看源代码,它会告诉您手动编码需要使用什么功能。当我大约七年前查看 XSP 类时,我认为使用的函数是 XSP.confirm() 相当于一个基本的 JavaScript confirm() 调用。使用它可以使您的代码更具可读性,并使灵活性更容易。

      【讨论】:

      • 嗨 Paul,不是 XSP.confirm() 客户端吗?我想要在 SSJS 代码块之间进行确认。我得到 [ReferenceError] 'XSP' not found。即使只是使用 confirm() 我得到 [ReferenceError] 'confirm' not found?
      • 是的。我假设你所有的代码都是客户端的。如果没有,您需要考虑事件的顺序 - 您希望在 服务器 上运行代码,然后从 浏览器 获取用户输入,然后再提交回 server 执行更多操作。希望这清楚地表明您不能在 server-side 代码的 single 操作组中完成所有这些操作;-)
      • 新方法 - 我验证 SSJS,然后 onComplete,调用自定义模式,用户根据他们想要实现的目标单击按钮。我唯一的问题是 onComplete 总是运行。有没有办法阻止它?在这种情况下,如果验证失败。我尝试在 SSJS 中使用 break 和 return false,但 onComplete 代码仍然运行......
      • view.postScript()从SSJS发布CSJS
      • Paul,我之前尝试过 view.postScript(),但在尝试进行简单确认时出现错误 [ReferenceError] 'confirm' not found.... 我的代码结尾是:}else { 打印(“真”); // 显示模态 view.postScript(confirm("您确定要提交您的自我评估吗?")); //返回真; } } } }]]>
      【解决方案3】:

      您可以向您的 actionGroup 添加条件。这是一个简单的例子:

      <xp:eventHandler event="onclick" submit="true" refreshMode="complete">
          <xp:this.action>
              <xp:actionGroup condition="#{javascript:myCondition()}">
                  xp:confirm>
                      <xp:this.message><![CDATA[#{javascript:"Are you sure you want to submit your self assessment?"}]]></xp:this.message>
                  </xp:confirm>
                  <xp:executeScript>
                      ...
                  </xp:executeScript>
              </xp:actionGroup>
          </xp:this.action>
      </xp:eventHandler>
      

      因此,在您的情况下,您只需将第一个操作添加为条件,并根据操作组中的逻辑是否必须运行,让它返回 true 或 false。

      【讨论】:

      • 您好,我已将第一部分添加为确认框操作组的条件,但是现在,当我加载页面时,我的验证消息会立即出现。此外,当我第一次点击我的按钮时,它按预期工作,我得到验证,没有确认框,但是在第 2 次、第 3 次、第 4 次等点击时,条件似乎不再运行,我总是得到确认盒子。我已经用条件代码更新了我的问题......有什么想法吗?
      【解决方案4】:

      有一个解决方案,但它涉及实现一系列元素来正确支持这种情况。但是当它启动时,我相信它会很有帮助。

      您的问题在某种程度上与blog post of mine 有关。 为了在您的具体情况下为您提供帮助,我将尝试在这里总结所有活动部分。希望你喜欢阅读...

      第一个元素:服务器端辅助方法

      如果您在验证阶段之外进行验证,则没有真正的方法可以让客户知道出了什么问题,或者更好的是,它可能会与您想要保留的最终流程断开连接(您的情况)。因此,您首先要做的是创建一种告诉客户的方式。首先我们用一个简单的辅助方法构建一个静态类:

      public enum Helper {
          ;
      
          public static void setErrorHeader(HttpServletResponse response, PhaseId phaseId) {
              response.setHeader("Application-Error", phaseId.toString());
          }
      }
      

      稍后我们将调用此方法将验证“标记”为失败

      第二个元素:客户端辅助方法

      我们需要一个 JavaScript 函数来帮助我们利用最终添加的响应标头(通过 JS 库将此函数添加到您的 XPage)。

      var helper = {
          isBadRequest : function(xhr) {
              return xhr.getResponseHeader("Application-Error") !== null;
          }
      }
      

      第三个元素:增强的事件处理程序

      要以正确的方式开始,我们必须利用事件处理程序参数:

      <xp:button id="myButton" value="Three-step action">
          <xp:eventHandler
              id="myEventHandlerId"
              event="onclick"
              submit="false"
              action="#{myBean.makeItFlow}"
              script="threeStep('validate', 'threeStepSave(arguments[1].xhr)')"/>
      </xp:button>
      

      eventHandler 具有如上所述定义的属性非常重要:

      • id:用于稍后抓取事件处理程序
      • submit="false": 不提交表单,我们手动提交
      • action:包含对将被调用的服务器端 bean 方法的引用。我使用了名称myBean.makeItFlow。我假设您知道如何使用托管 bean
      • script:“真实”动作发生的地方

      此时,在脚本属性中,我们调用 XPages 客户端 javascript 方法来执行帖子 - XSP.partialRefreshPost() - 我们手动传递各种参数。在这种情况下,我选择避免将所有必要的脚本与事件保持一致。在页面底部可以添加以下辅助函数:

      <xp:scriptBlock
          value="
          function threeStep(param, onCompleteFunc) {
              var execId = '#{id:containerId}';
              var refreshId = '#{id:containerId}';
              var eventHandlerId = '#{id:myEventHandlerId}';
      
              var opts = {
                  execId: execId,
                  params: { '$$xspsubmitid': eventHandlerId, action: param },
                  onError : 'console.log(arguments[0])'
              };
      
              if (onCompleteFunc) {
                  opts.onComplete = onCompleteFunc;
              }
      
              XSP.partialRefreshPost(refreshId, opts);
          }
      
          function threeStepSave(xhr) {
              if (helper.isBadRequest(xhr)) {
                  return alert('Validation failed');
              }
      
              if (!confirm('Do you want to continue?')) return;
      
              threeStep('save');
          }" />
      

      方法的第一个参数是要刷新的id。然后我们有一个对象,其属性定义:

      • param:我们要传递的参数以调整服务器端方法的行为
      • onCompleteFunc:将在服务器端方法评估结束时调用的客户端javascript(js必须是字符串,将被评估)
      • var execId:将与 POST 一起提交的块(以及范围)
      • var refreshId:要刷新的区块
      • var eventHandlerId:对事件处理程序 ID 的非常重要的引用

      第四个元素:bean 动作方法

      现在,我们通过 Java bean 定义按钮背后的所有动作逻辑。我决定使用 1 种特定方法来响应事件处理程序传递的 action 参数值。

      public void makeItFlow() {
          FacesContext facesContext = FacesContext.getCurrentInstance();
          ExternalContext externalContext = facesContext.getExternalContext();
          String action = (String) externalContext.getRequestParameterMap().get("action");
      
          if ("validate".equals(action)) {
              // Your logic
              boolean failed = false;
      
              // When validation fails add the error response header
              if (failed) {
                  HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
                  Helper.setErrorHeader(response, PhaseId.INVOKE_APPLICATION);
              }
          } else if ("save".equals(action)) {
              // Let's save this thing
          }
      }
      

      我正在添加一个简短的视频,说明它的行为方式(在示例中,我添加了一些额外的代码以使各个阶段变得明显)

      https://youtu.be/JayzcGex-rQ

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-26
        • 1970-01-01
        相关资源
        最近更新 更多