Найти компонент по типу в JSF
Мой вопрос связан с этим. Получить все скрытые поля ввода в JSF динамически, но это не то же самое, что я хочу работать с JSF, а не с простым HTML, и при условии, что у меня есть следующее в моем .xhtml
файл:
<h:inputHidden id="name1" value="SomeValue1"/>
<h:inputHidden id="name2" value="SomeValue2"/>
Я разработал небольшой код, где я пытался получить все h:inputHidden
динамически помечает теги и выводит их значения на консоль, но проблема в том, что я не могу придумать, как сделать все динамичным. В моем коде я должен знать форму id
если я хочу перебрать uicomponents, как я могу перебрать все UIComponent
в дереве компонентов? (Я старался UIViewRoot#getChildren()
но я получаю только первые детские).
Вот фрагмент кода:
// formId is the id of my form
List<UIComponent> components = FacesContext.getCurrentInstance().getViewRoot().findComponent("formId").getChildren();
// A List of UIComponent where I am adding my Hidden Inputs
List<UIComponent> hiddenComponents = new ArrayList<UIComponent>();
for (UIComponent component : components) {
// using the hidden inputs type in JSF: HtmlInputHidden
if (component instanceof HtmlInputHidden) {
hiddenComponents.add(component);
}
}
for (UIComponent component : hiddenComponents) {
// Printing the hidden inputs values for demonstration purposes
System.out.println(((HtmlInputHidden)component).getValue());
}
1 ответ
Вам также нужно перебрать детей детей и их детей и так далее. Видите ли, это дерево компонентов.
Вот фрагмент кода служебного метода, который делает это с помощью хвостовой рекурсии:
public static <C extends UIComponent> void findChildrenByType(UIComponent parent, List<C> found, Class<C> type) {
for (UIComponent child : parent.getChildren()) {
if (type.isAssignableFrom(child.getClass())) {
found.add(type.cast(child));
}
findChildrenByType(child, found, type);
}
}
Вот как вы можете использовать это:
UIForm form = (UIForm) FacesContext.getCurrentInstance().getViewRoot().findComponent("formId");
List<HtmlInputHidden> hiddenComponents = new ArrayList<>();
findChildrenByType(form, hiddenComponents, HtmlInputHidden.class);
for (HtmlInputHidden hidden : hiddenComponents) {
System.out.println(hidden.getValue());
}
Или лучше используйте UIComponent#visitTree()
который использует шаблон посетителя. Основное отличие состоит в том, что он также выполняет итерации по таким компонентам, как <ui:repeat>
а также <h:dataTable>
и восстанавливает дочернее состояние для каждой итерации. В противном случае вы бы не получили никакой ценности, когда у вас есть <h:inputHidden>
заключен в такой компонент.
FacesContext context = FacesContext.getCurrentInstance();
List<Object> hiddenComponentValues = new ArrayList<>();
context.getViewRoot().findComponent("formId").visitTree(VisitContext.createVisitContext(context), new VisitCallback() {
@Override
public VisitResult visit(VisitContext visitContext, UIComponent component) {
if (component instanceof HtmlInputHidden) {
hiddenComponentValues.add(((HtmlInputHidden) component).getValue());
return VisitResult.COMPLETE;
} else {
return VisitResult.ACCEPT;
}
}
});
for (Object hiddenComponentValue : hiddenComponentValues) {
System.out.println(hiddenComponentValue);
}
Смотрите также:
- Как собрать значения компонента UIInput внутри компонента UIData в методе действия bean-компонента?
- Как мне присоединить FacesMessage от поддерживающего компонента к определенному полю в пользовательском интерфейсе:repeat?
- Доступ к динамическим компонентам UIC в JSF Managed Bean
- JSF 2 - сохранить все допустимые значения компонентов
В конце концов, вероятно, проще всего связать их со свойством бина обычным способом, если это необходимо внутри <ui:repeat>
:
<h:inputHidden id="name1" value="#{bean.name1}"/>
<h:inputHidden id="name2" value="#{bean.name2}"/>