Условно установить атрибут для элемента с помощью JSP Documents (JSPX)

В формах HTML кнопки можно отключить, определив для них атрибут "disabled" с любым значением:

<button name="btn1" disabled="disabled">Hello</button>

Если кнопка должна быть включена, атрибут не должен существовать, поскольку нет определенного значения, для которого можно установить атрибут disabled, который бы оставил кнопку включенной.

Это вызывает у меня проблемы, когда я хочу включить / отключить кнопки при использовании JSP Documents (jspx). Так как документы JSP должны быть правильно сформированными документами XML, я не вижу способа условно включить этот атрибут, поскольку что-то вроде следующего недопустимо:

<button name="btn1" <%= (isDisabled) ? "disabled" : "" %/> >Hello</button>

Хотя я мог дважды повторить тег, используя тег JSTL if, чтобы получить желаемый эффект, в моем конкретном случае у меня было более 15 атрибутов, объявленных на кнопке (множество атрибутов обработчика событий javascript для AJAX), поэтому дублирование тега приведет к JSP очень грязный.

Как я могу решить эту проблему, не жертвуя удобочитаемостью JSP? Существуют ли какие-либо пользовательские теги, которые могут добавлять атрибуты к родителю, манипулируя выходным DOM?

9 ответов

Решение

Я использую пользовательский тег JSP с динамическими атрибутами. Вы используете это так:

<util:element elementName="button" name="btn1" disabled="$(isDisabled ? 'disabled' : '')"/>

По сути, этот тег генерирует элемент XML с elementName и помещает все атрибуты, присутствующие в теге, но пропускает пустые.

Сам тег довольно легко реализовать, моя реализация всего 44 строки.

Вы можете использовать <jsp:text> тег для решения этой проблемы с использованием действительного XML:

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

Это, очевидно, более многословно, чем некоторые другие решения. Но он полностью автономен: никаких пользовательских тегов не требуется. Кроме того, он легко масштабируется на столько атрибутов, сколько вам нужно.

@alex отличное решение для использования троичного оператора. Я добавляю некоторые из моих примеров, что благодаря вам я просто изменил результат условия, если true, записывает атрибут, иначе ничего не пишет

заполнить список и выбрать используемое значение, избегая c: если

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

проверить при запуске переключатель, чтобы избежать c:if:

<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' : ''} />

Я думаю, что с момента последнего поста прошло некоторое время, но я столкнулся с точно такой же проблемой <select><option selected="selected"> тэги, т.е. динамически объявляя, какая опция выбрана. Чтобы решить эту проблему, я сделал специальный 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>

Использование нотации скриптлета не будет работать для документов JSP (.jspx)

Читая об автоматическом конвертере JSP в JSPX, я наткнулся на <jsp:element> а также <jsp:attribute> теги. Если я правильно понимаю, вы должны быть в состоянии сделать что-то вроде

<jsp:element name="button">
  <jsp:attribute name="someAttribute">value</jsp:attribute>
</jsp:element>

и иметь выходную мощность двигателя JSP

<button someAttribute="value"/>

или что-то типа того. Единственная проблема, указанная на странице выше, заключается в том, что это не очень хорошо работает с условными конструкциями. Автор конвертера работал над тем, чтобы создать несколько вспомогательных тегов, которые вы можете посмотреть на загрузку исходного кода, я думаю. Надеюсь, это поможет.

Правильный способ сделать это с чистым JSP:

<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>

Ключ в том, чтобы использовать omit атрибут на <jsp:attribute> - если выражение оценивается как true тогда атрибут вообще не будет обрабатываться.

Создайте библиотеку тегов (.tagx), затем используйте тег scriptlet.

См. http://code.google.com/p/jatl/wiki/JSPExample

<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1">
<jsp:directive.page import="com.googlecode.jatl.Html"/>
<jsp:directive.page import="com.evocatus.product.data.AttributeValue"/>
<jsp:directive.page import="com.evocatus.domain.Product"/>

<jsp:scriptlet>
//<![CDATA[
    final Product p = (Product) request.getAttribute("product");
        new Html(out) {{
           for (AttributeValue v : p.summaryAttributeValues()) {
                   p();
                        strong().text(v.getLabel()).end();
                        text(": " + v.getValue());
                   endAll();
           }
        }};
//]]>
</jsp:scriptlet>

</jsp:root>

Да, это обман... но он выполняет свою работу. Плюс вы можете сделать действительно неприятную сложную рекурсию для древовидных структур таким образом.

Я также разместил другое решение в своем блоге и gist.github, в котором используется несколько библиотек tagx: http://adamgent.com/post/8083703288/conditionally-set-an-attribute-on-an-element-with-jspx

Я реализовал его как /questions/2453940/uslovno-ustanovit-atribut-dlya-elementa-s-pomoschyu-jsp-documents-jspx/2453962#2453962 и инкапсулировал /questions/2453940/uslovno-ustanovit-atribut-dlya-elementa-s-pomoschyu-jsp-documents-jspx/2453960#2453960, чтобы его можно было повторно использовать как тег.

<%@ 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.

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

Результат будет отображаться как

<input 
    name="myDate"
    id="myDate"
    type="date"
    required/>

Я только что боролся с той же проблемой. Я пытался с помощью <jsp:attribute name="disabled"/> внутри <c:if>, но компилятор пытается присоединить отключенный атрибут к c:if элемент, который терпит неудачу. Но я обнаружил, что это работает (stripes:submit это элемент для создания кнопки типа submit в полосах):

<stripes:submit name="process" value="Hello">
   <jsp:attribute name="disabled">
       <c:if test="${x == 0}">disabled</disabled>
   </jsp:attribute>
</stripes:submit>

Кажется, что jsp:attribute не будет создавать атрибут вообще, если тело содержит только пробелы, поэтому вы либо получите disabled="disabled" или вообще ничего

Это будет работать только в том случае, если вы используете какой-либо taglib для генерации кнопки, а элемент tag должен поддерживать атрибут disabled (передавая его в базовый элемент HTML). Вы не можете использовать jsp:attribute добавить атрибут к необработанному элементу HTML.

Синтаксис <% = blah%> не является допустимым XML, необходимым для документов JSP. У вас есть 2 варианта:

  1. Заменить <% = (isDisabled)? "disabled": ""%> с (isDisabled)? "disabled": ""
  2. Используйте Core taglib и EL (убедитесь, что isDisabled помещен в область видимости страницы) следующим образом:
<С: выбрать>
  "отключено"
  <С: в противном случае>""

Надеюсь, это поможет:)

Я на самом деле не использую JSP (и я ответил один раз, затем удалил его, когда понял, что нужно "с помощью действительного XML"). Самое чистое, что я могу придумать, это:

<% if (isDisabled) { %>
  <button name="btn1" disabled="disabled">Hello</button>
<% } else { %>
  <button name="btn1">Hello</button>
<% } %>
Другие вопросы по тегам