В формах HTML кнопки можно отключить, определив для них атрибут disabled с любым значением:
<button name = "btn1" disabled = "disabled">Hello</button>
Если кнопка должна быть активирована, атрибут не должен существовать, поскольку нет определенного значения, которое можно было бы установить для атрибута disabled, которое оставило бы кнопку включенной.
Это вызывает у меня проблемы, когда я хочу включить / отключить кнопки при использовании документов JSP (jspx). Поскольку документы JSP должны быть правильно сформированными XML-документами, я не вижу никакого способа условно включить этот атрибут, поскольку что-то вроде следующего недопустимо:
<button name = "btn1" <%= (isDisabled) ? "disabled" : "" %/> >Hello</button>
Хотя я мог дважды реплицировать тег с помощью тега JSTL if для получения желаемого эффекта, в моем конкретном случае у меня есть более 15 атрибутов, объявленных на кнопке (множество атрибутов обработчика событий javascript для AJAX), поэтому дублирование тега приведет к тому, что JSP очень запутанный.
Как я могу решить эту проблему, не жертвуя читабельностью JSP? Существуют ли какие-либо настраиваемые теги, которые могут добавлять атрибуты к родительскому объекту, манипулируя выходным DOM?





На самом деле я не использую JSP (и однажды я ответил, а затем удалил его, когда понял, что «должен быть действительным XML»). Самое чистое, что я могу придумать, это следующее:
<% if (isDisabled) { %>
<button name = "btn1" disabled = "disabled">Hello</button>
<% } else { %>
<button name = "btn1">Hello</button>
<% } %>
Синтаксис <% = blah%> не является допустимым XML, необходимым для документов JSP. У вас есть 2 варианта:
<c:choose>
<c:when test = "${isDisabled}">"disabled"</c:when>
<c:otherwise>""</c:otherwise>
</c:choose>
Надеюсь, это поможет :)
Но где бы эти теги были размещены? Вы по-прежнему не сможете поместить их в раздел атрибутов тега кнопки, так как это все равно будет недопустимым XML, а размещение их внутри элемента приведет к добавлению некоторого количества CDATA.
Читая про автоматический Конвертер jsp в jspx, я наткнулся на теги <jsp:element> и <jsp:attribute>. Если я правильно понимаю, вы сможете сделать что-то вроде
<jsp:element name = "button">
<jsp:attribute name = "someAttribute">value</jsp:attribute>
</jsp:element>
и иметь вывод двигателя jsp
<button someAttribute = "value"/>
или что-то вроде того. Единственная проблема, указанная на странице выше, заключается в том, что это не очень хорошо работает с условными конструкциями. Автор конвертера поработал над этим, создав несколько вспомогательных тегов, которые, я думаю, вы можете посмотреть, загрузив исходный код. Надеюсь, это поможет.
Собственно, это, вероятно, <jspx: element> и так далее. Инструмент JSP2X записывает их как пользовательские теги в ваш WEB-INF для использования в преобразованных файлах JSP.
Я использую собственный тег JSP с динамическими атрибутами. Вы используете это так:
<util:element elementName = "button" name = "btn1" disabled = "$(isDisabled ? 'disabled' : '')"/>
По сути, этот тег создает элемент XML с elementName и помещает все атрибуты, присутствующие в теге, но пропускает пустые.
Сам тег довольно легко реализовать, моя реализация занимает всего 44 строки.
Не могли бы вы опубликовать код для этого? Думаю, это было бы очень поучительно.
Похоже, это будет лучший ответ, который я получу, жаль, что нет возможности сделать это с правильным синтаксисом XML без необходимости писать собственные теги, однако ...
Если вы посмотрите на инструмент JSP2X, он удалит теги для <jspx: element>, <jspx: attribute> и <jspx: body> (для тела элемента). Это еще одна альтернатива, которую можно использовать с более сложными конструкциями.
отличное решение для использования тернарного оператора. вниз мой пример.
Вы можете использовать тег <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>
Это явно более подробное решение, чем некоторые другие решения. Но это полностью автономный: никаких специальных тегов не требуется. Кроме того, это легко масштабируется для любого количества атрибутов, которое вам нужно.
Если вы проголосовали против, оставьте комментарий, почему. Это дает мне возможность улучшить ответ.
Так много отрицательных голосов за этот ответ, но на самом деле никто не говорит, почему. :-(
Я не знаю, почему кто-то проголосовал против этого ответа, но я считаю, что это лучший подход, который мне подходит.
Я не голосовал против, но этот подход затрудняет чтение самого JSP, особенно если это повторяется снова и снова, и вы теряете проверку XML с правильными тегами.
@ArchimedesTrajano Вы правы - и я уже указывал на преимущества и недостатки этого подхода. Если удобочитаемость важна, вам следует использовать собственный тег. Весь вопрос показывает, почему использование jspx - не лучшая идея!
Я предполагаю, что с момента последнего сообщения об этом прошло некоторое время, но я столкнулся с той же проблемой с тегами <select><option selected = "selected">, то есть с динамическим объявлением, какой вариант выбран. Чтобы решить эту проблему, я сделал собственный тег x; Подробности выложил в другом ответь здесь
Я пришел к выводу, что хороших ярлыков не существует; Выражения 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)
Ах, но тег скриптлета будет работать code.google.com/p/jatl/wiki/JSPExample ... Одна из причин, по которой я написал эту библиотеку (см. Ссылку).
Я только что боролся с той же проблемой. Я попытался использовать <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", либо вообще ничего.
Это будет работать только в том случае, если вы используете какую-то библиотеку тегов для создания кнопки, а элемент тега должен поддерживать атрибут disabled (передавая его в базовый элемент HTML). Вы не можете использовать jsp:attribute для добавления атрибута к необработанному элементу HTML.
у меня не работает ... атрибут создается, даже если тело тега пусто. Я думаю, это зависит от того, какой JSP вы используете (я использую смолу 3.0.24)
Создайте библиотеку тегов (.tagx), затем используйте тег скриптлета.
См. 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/conditional-set-an-attribute-on-an-element-with-jspx
@Алекс отличное решение для использования тернарного оператора. Я добавляю часть своего примера, что благодаря вам я просто изменил результат условия, если оно истинно, записывает атрибут, иначе ничего не пишу
для заполнения списка и выбора используемого значения, избегая 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>
чтобы проверить при запуске переключатель, чтобы избежать 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' : ''} />
Можно ли изменить language.code == usedLanguage для проверки наличия language.code в каком-либо списке? Я хочу проверить что-то вроде: someList.contains(language.code), но это не удается.
Я реализовал его как https://stackoverflow.com/a/207882/242042 и инкапсулировал https://stackoverflow.com/a/775295/242042, чтобы его можно было повторно использовать как тег.
<%@ 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:
<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, тогда атрибут вообще не будет отображаться.
Как указано в вопросе, хотя это будет работать, это более беспорядочно, чем мне хотелось бы, особенно с 15+ атрибутами, общими между двумя ветвями оператора if.