Вставка динамических атрибутов в весенний тег из пользовательского тега

У меня есть пользовательский тег 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 делает то же самое?)

Другие вопросы по тегам