Вставка динамических атрибутов в весенний тег из пользовательского тега
У меня есть пользовательский тег JSP, который выводит поле ввода формы пружины (плюс другие элементы макета). Что мне нужно сделать, так это уметь принимать динамические атрибуты и использовать их в поле ввода как есть.
Например использования:
<mytag:myinputtag arbitraryAttribute="value"/>
Должен выводить
<input:form arbitraryAttribute="value" />
К сожалению, он не работает должным образом, потому что он генерирует неопределенную форму: исключение тега ввода. Ниже приведен код, который я использовал:
<%@ tag dynamic-attributes="attributes" %>
<c:set var="expandedAttributes">
<c:forEach var="a" items="${ attributes }">
${a.key}="${a.value}"<%= " " %>
</c:forEach>
</c:set>
<form:input (...) ${expandedAttributes} />
Я могу понять, почему это не работает должным образом из-за порядка разрешения EL expr и тегов. Поэтому я также проверил, чтобы вводить напрямую с помощью скриптлетов
<form:input (...) <%= (String)jspContext.getAttribute("expandedAttributes")%> --%>
Поэтому мне нужно решение этой проблемы, так как я не могу просмотреть все атрибуты, которые могут быть добавлены к входным данным. Поэтому я подумал о следующих возможностях:
- С помощью
<input
вместо<form:input
Это означает, что я должен точно скопировать пружинный код для атрибута "путь" (не очень хорошая идея) - Расширьте форму: введите тег, скопируйте динамические атрибуты в атрибуты по умолчанию и выполните стандартное отображение тега (не знаю, возможно ли это решение, и если Spring изменит свою реализацию тега ввода, он больше не сможет работать должным образом)
- Перечисляя все атрибуты, которые мне нужны, это делает код тега огромным и менее обслуживаемым
Я хотел бы знать, может быть, есть лучшее решение, о котором я не думаю, или же вообще возможна вторая возможность.
Спасибо
1 ответ
После месяца работы над этой проблемой я подумал о том, чтобы сдать и удалить файл тегов alltogheter.
Нет реализации, позволяющей мне вводить атрибуты так, как я хочу, поэтому я изменил подход и попытался сгенерировать тег, который генерирует тело, а затем оценивает его. Также этот подход не работает, потому что jsp и теги компилируются перед выполнением, и поэтому невозможно внедрить код JSP в тело тега.
Итак, я нашел решение, которое в настоящее время работает, и оно выглядит так:
Я создал свой собственный тег ввода, который простирается от весны InputTag.java
, Этот тег принимает специальный атрибут dynAttrs
типа java.util.Map
; это динамические атрибуты, переданные из моего родительского тега. Остальные допустимые / принятые атрибуты тега такие же, как и у входного тега Spring.
Тогда в writeTagContent
метод, который я проверяю, если dynAttrs
доступны и для каждого атрибута я делаю:
- если атрибут является полем класса, используйте
PropertyAccessor
установить значение (например,onClick
) - если атрибут не является полем класса (или поле недоступно для записи), он будет добавлен в динамические атрибуты (например,
data-customData
)
С этого момента я просто вызываю super.writeTagContent() и вуаля, весна делает всю магию за меня!
Пример использования:
<my:customTextField path="model.path" attr1="val1" attr2="val2" disabled="true"/>
это будет преобразовано в
<div class="bla bla bla">
<my:input path="model.path" disabled="true" dynAttrs="[{attr1,val1},{attr2,val2}]"/>
</div>
и вниз по течению превращается в
<div class="bla bla bla">
<form:input path="model.path" disabled="disabled" attr1="val1" attr2="val2"/>
</div>
и тогда будет отображаться как
<div class="bla bla bla">
<input id="model.path" name="model.path" disabled="disabled" attr1="val1" attr2="val2"/>
</div>
Поэтому я могу динамически вводить любое количество динамических атрибутов во время выполнения во входной тег Spring!
ПРИМЕЧАНИЕ. Поскольку я не увлекаюсь этим подходом, я подготовил еще две реализации этого решения:
используйте Apache Common BeanUtils.populate для непосредственного заполнения тега dynAttrs, но управление ошибками в этом случае может быть критическим.
кэшируйте в hashmap все доступные поля в этом теге и обновите их вручную с помощью
field.setValue(this,dynAttrs.get(attrName))
(должно быть быстрее, так как не нужно извлекать поле при каждом вызове, но, возможно,PropertyAccessor
делает то же самое?)