使用JSP文档(JSPX)在元素上有条件地设置属性

使用JSP文档(JSPX)在元素上有条件地设置属性,jsp,xhtml,webforms,jspx,Jsp,Xhtml,Webforms,Jspx,在HTML表单中,可以通过在按钮上定义“disabled”属性来禁用按钮,该属性具有以下任意值: <button name="btn1" disabled="disabled">Hello</button> 你好 如果要启用按钮,则该属性不应存在,因为没有可将禁用属性设置为使按钮保持启用状态的定义值 当我想在使用JSP文档(jspx)时启用/禁用按钮时,这会给我带来问题。由于JSP文档必须是格式良好的XML文档,我看不到任何有条件地包含此属性的方法,因为以下内容是不合

在HTML表单中,可以通过在按钮上定义“disabled”属性来禁用按钮,该属性具有以下任意值:

<button name="btn1" disabled="disabled">Hello</button>
你好 如果要启用按钮,则该属性不应存在,因为没有可将禁用属性设置为使按钮保持启用状态的定义值

当我想在使用JSP文档(jspx)时启用/禁用按钮时,这会给我带来问题。由于JSP文档必须是格式良好的XML文档,我看不到任何有条件地包含此属性的方法,因为以下内容是不合法的:

<button name="btn1" <%= (isDisabled) ? "disabled" : "" %/> >Hello</button>
你好 虽然我可以使用JSTL if标记复制标记两次以获得所需的效果,但在我的特定情况下,我在按钮上声明了超过15个属性(AJAX的许多javascript事件处理程序属性),因此复制标记将使JSP非常混乱

如何在不牺牲JSP可读性的情况下解决这个问题?是否有任何自定义标记可以通过操作输出DOM向父级添加属性?

我实际上不使用JSP(我回答了一次,然后在理解“必须使用有效的XML”时将其删除)。我能想到的最干净的是:

<% if (isDisabled) { %>
  <button name="btn1" disabled="disabled">Hello</button>
<% } else { %>
  <button name="btn1">Hello</button>
<% } %>

你好
你好
语法不是JSP文档所需的合法XML。您有两种选择:

  • 替换为(已禁用)?“已禁用”:”
  • 使用核心标记库和EL(确保isDisabled被放入页面范围),如下所示:
  • “残疾” ""
    希望能有所帮助:)

    在阅读有关自动密码的文章时,我遇到了
    标签。如果我理解正确的话,你应该可以做类似的事情

    <jsp:element name="button">
      <jsp:attribute name="someAttribute">value</jsp:attribute>
    </jsp:element>
    
    
    价值
    
    并具有jsp引擎输出

    <button someAttribute="value"/>
    
    
    

    或者类似的。上面一页指出的唯一问题是,这似乎不能很好地处理条件构造。转换器的作者解决了创建一些helper标记的问题,我想您可以看看下载的源代码。希望对您有所帮助。

    我使用带有动态属性的自定义JSP标记。您可以这样使用它:

    <util:element elementName="button" name="btn1" disabled="$(isDisabled ? 'disabled' : '')"/>
    
    
    
    基本上,这个标记所做的是生成一个带有elementName的XML元素,并将所有属性放在标记中,但跳过空属性

    标记本身很容易实现,我的实现只有44行长。

    您可以使用
    标记使用有效的XML解决此问题:

    <jsp:text><![CDATA[<button name="btn1"]]></jsp:text>
        <c:if test="${isDisabled}"> disabled="disabled"</c:if>
        >
        Hello!
    <jsp:text><![CDATA[</button>]]></jsp:text>
    
    
    disabled=“disabled”
    >
    你好
    ]]>
    

    这显然比其他一些解决方案更冗长。但是它是完全独立的:不需要定制标签。此外,它可以轻松地扩展到所需的任意多个属性。

    我想自从上次发布这篇文章以来已经过了一段时间,但我遇到了与
    标记完全相同的问题,即动态声明选择了哪个选项。为了解决这个问题,我制作了一个定制的tagx;我在另一个网站上公布了细节

    我得出的结论是没有好的捷径;EL和JSP表达式只能存在于XML元素属性内部(以及正文内容中)。所以你必须做以下几件事

    <c:choose>
        <c:when test="${isDisabled}"><button name="btn1" disabled="disabled">Hello</button></c:when>
        <c:otherwise><button name="btn1">Hello</button></c:otherwise>
    </c:choose>
    
    
    你好
    你好
    

    使用scriptlet表示法对JSP文档(.jspx)不起作用。

    我刚刚遇到了同样的问题。我尝试在
    内部使用
    ,但编译器试图将disabled属性附加到失败的
    c:if
    元素。但我发现这确实有效(
    stripes:submit
    是创建stripes中submit类型按钮的元素):

    
    残废
    
    如果正文只包含空格,那么
    jsp:attribute
    似乎根本不会创建属性,因此您要么得到
    disabled=“disabled”
    ,要么什么都没有

    只有当您使用某种taglib来生成按钮,并且tag元素必须支持disabled属性(将其传递给底层HTML元素)时,这才有效。不能使用
    jsp:attribute
    向原始HTML元素添加属性。

    创建标记库(.tagx),然后使用scriptlet标记

    
    //
    
    是的,这是作弊。。。但它完成了任务。另外,你可以用这种方法对树结构进行非常复杂的递归

    我还在我的博客和gist.github上发布了另一个解决方案,它使用了大量的tagx库:

    @alex
    使用三元运算符是一个很好的解决方案。我添加了一些示例,感谢您,我只是更改了条件的结果,如果为true,则写入属性,否则不写入任何内容

    要填充列表并选择使用的值,请避免c:if

    <select id="selectLang" name="selectLang" >
    <c:forEach var="language" items="${alLanguages}" >
        <option value="${language.id}" ${language.code == usedLanguage ? 'selected' : ''} >${language.description}</option>
    </c:forEach>
    
    
    ${language.description}
    

    要在启动时检查单选按钮以避免c:如果:

    <input type="radio" id="id0" value="0" name="radio" ${modelVar == 0 ? 'checked' : ''} />
    <input type="radio" id="id1" value="1" name="radio" ${modelVar == 1 ? 'checked' : ''} />
    <input type="radio" id="id2" value="2" name="radio" ${modelVar == 2 ? 'checked' : ''} />
    
    
    
    我实现了它,并对其进行了封装,以便可以将其作为标记重用

    <%@ tag
      display-name="element"
      pageEncoding="utf-8"
      description="similar to jsp:element with the capability of removing attributes that are blank, additional features depending on the key are documented in the tag."
      trimDirectiveWhitespaces="true"
      dynamic-attributes="attrs"
    %>
    <%@ attribute
      name="tag"
      description="Element tag name.  Used in place of `name` which is a common attribute in HTML"
      required="true"
    %>
    <%-- key ends with Key, use i18n --%>
    <%-- key starts with x-bool- and value is true, add the key attribute, no value  --%>
    <%-- key starts with x-nc- for no check and value is empty, add the key attribute, no value  --%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <jsp:text><![CDATA[<]]></jsp:text>
    <c:out value="${tag} " />
    <c:forEach var="attr" begin="0" items="${attrs}">
      <c:choose>
        <c:when test='${fn:endsWith(attr.key, "Key")}'>
          ${attr.key}=<fmt:message key="${attr.value}" />
        </c:when>
        <c:when test='${fn:startsWith(attr.key, "x-bool-") && attr.value == "true"}'>
          <c:out value="${fn:substringAfter(attr.key, 'x-bool-')}" />
        </c:when>
        <c:when test='${fn:startsWith(attr.key, "x-bool-") && attr.value != "true"}'>
        </c:when>
        <c:when test='${fn:startsWith(attr.key, "x-nc-")}'>
          <c:out value="${fn:substringAfter(attr.key, 'x-nc-')}" />="<c:out value='${attr.value}' />"
        </c:when>
        <c:when test='${not empty attr.value}'>
          <c:out value="${attr.key}" />="<c:out value='${attr.value}' />"
        </c:when>
      </c:choose>
      <c:out value=" " />
    </c:forEach>
    <jsp:doBody var="bodyText" />
    <c:choose>
      <c:when test="${not empty fn:trim(bodyText)}">
        <jsp:text><![CDATA[>]]></jsp:text>
          ${bodyText}
        <jsp:text><![CDATA[<]]></jsp:text>
          <c:out value="/${tag}" />
        <jsp:text><![CDATA[>]]></jsp:text>
      </c:when>
      <c:otherwise>
        <jsp:text><![CDATA[/>]]></jsp:text>
      </c:otherwise>
    </c:choose>
    
    
    ${attr.key}=
    =""
    =""
    ]]>
    ${bodyText}
    ]]>
    ]]>
    
    要使用它,请将其放入taglib tagdir中

    <%@ taglib tagdir="/WEB-INF/tags" prefix="xyz"%>
    ...
    <xyz:element tag="input"
      type="date"
      id="myDate"
      name="myDate"
      x-bool-required="true"
    />
    
    
    ...
    
    输出将呈现为

    
    
    使用pureJSP的正确方法是:

    <jsp:element name="button">
      <jsp:attribute name="name">btn1</jsp:attribute>
      <jsp:attribute name="disabled" omit="${not isDisabled}">disabled</jsp:attribute>
      <jsp:body>Hello</jsp:body>
    </jsp:element>
    
    
    btn1
    残废
    你好
    

    关键是要在
    上使用
    省略
    属性-如果表达式的计算结果为
    true
    ,则该属性将一点也不重。

    如问题中所述,虽然这会起作用,但比我希望的更混乱,特别是if语句的两个分支之间共有15个以上的属性。这些标记将放在哪里?您仍然无法将它们放在按钮标记的属性部分,因为这仍然是无效的XML,而将它们放在元素中只会导致som
    <%@ tag
      display-name="element"
      pageEncoding="utf-8"
      description="similar to jsp:element with the capability of removing attributes that are blank, additional features depending on the key are documented in the tag."
      trimDirectiveWhitespaces="true"
      dynamic-attributes="attrs"
    %>
    <%@ attribute
      name="tag"
      description="Element tag name.  Used in place of `name` which is a common attribute in HTML"
      required="true"
    %>
    <%-- key ends with Key, use i18n --%>
    <%-- key starts with x-bool- and value is true, add the key attribute, no value  --%>
    <%-- key starts with x-nc- for no check and value is empty, add the key attribute, no value  --%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <jsp:text><![CDATA[<]]></jsp:text>
    <c:out value="${tag} " />
    <c:forEach var="attr" begin="0" items="${attrs}">
      <c:choose>
        <c:when test='${fn:endsWith(attr.key, "Key")}'>
          ${attr.key}=<fmt:message key="${attr.value}" />
        </c:when>
        <c:when test='${fn:startsWith(attr.key, "x-bool-") && attr.value == "true"}'>
          <c:out value="${fn:substringAfter(attr.key, 'x-bool-')}" />
        </c:when>
        <c:when test='${fn:startsWith(attr.key, "x-bool-") && attr.value != "true"}'>
        </c:when>
        <c:when test='${fn:startsWith(attr.key, "x-nc-")}'>
          <c:out value="${fn:substringAfter(attr.key, 'x-nc-')}" />="<c:out value='${attr.value}' />"
        </c:when>
        <c:when test='${not empty attr.value}'>
          <c:out value="${attr.key}" />="<c:out value='${attr.value}' />"
        </c:when>
      </c:choose>
      <c:out value=" " />
    </c:forEach>
    <jsp:doBody var="bodyText" />
    <c:choose>
      <c:when test="${not empty fn:trim(bodyText)}">
        <jsp:text><![CDATA[>]]></jsp:text>
          ${bodyText}
        <jsp:text><![CDATA[<]]></jsp:text>
          <c:out value="/${tag}" />
        <jsp:text><![CDATA[>]]></jsp:text>
      </c:when>
      <c:otherwise>
        <jsp:text><![CDATA[/>]]></jsp:text>
      </c:otherwise>
    </c:choose>
    
    <%@ taglib tagdir="/WEB-INF/tags" prefix="xyz"%>
    ...
    <xyz:element tag="input"
      type="date"
      id="myDate"
      name="myDate"
      x-bool-required="true"
    />
    
    <jsp:element name="button">
      <jsp:attribute name="name">btn1</jsp:attribute>
      <jsp:attribute name="disabled" omit="${not isDisabled}">disabled</jsp:attribute>
      <jsp:body>Hello</jsp:body>
    </jsp:element>