попытайтесь написать составной компонент, который позволяет вводить mutttiple текстовые входы. Я прочитал, что можно определить компонент поддержки для составного компонента, поэтому мне не нужно писать рендерер или обработчик. Я не мог понять, как делегировать действия, объявленные в xhtml в составной компонент компонента. Наверное, я еще не совсем понял концепцию этого. Кто-нибудь имеет Идею?Invoke ActionListener компонента Backing в составном компоненте
Я использую Tomcat 7, EL 2,2, Весна 3, Mojarra 2.1.7
Это так, как я хотел бы использовать компонент:
<custom:multiInput value="#{backingBean.inputList}"/>
Где BackingBean.java содержит список объектов:
@Component
@Scope(value="view")
public class BackingBean {
...
private List<Foo> inputList;
....
}
Составной компонент multiInput.xhtml выглядит Тхи s:
<cc:interface componentType="MultiInput">
<cc:attribute name="value" required="true" type="java.util.List" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<h:dataTable value="#{cc.attrs.rows}" var="row">
<h:column>
<!-- here will be a selector component in order to select a foo object -->
</h:column>
<h:column>
<h:commandButton value="Remove Row">
<f:ajax execute=":#{cc.clientId}" render=":#{cc.clientId}" listener="#{cc.removeRow(row)}" />
</h:commandButton>
</h:column>
<h:column>
<h:commandButton value="Add Row" rendered="#{cc.lastRow}">
<f:ajax execute=":#{cc.clientId}" render=":#{cc.clientId}" listener="#{cc.addEmptyRow()}" />
</h:commandButton>
</h:column>
</h:dataTable>
</div>
</cc:implementation>
А вот компонент подложки MultiInput.java:
@FacesComponent(value="MultiInput")
public class MultiInput extends UIInput implements NamingContainer, Serializable{
...
@Override
public String getFamily() {
return "javax.faces.NamingContainer";
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
initRowsFromValueAttribute();
super.encodeBegin(context);
}
public void removeRow(MultiInputRow row) {
// why is this method is never reached when clicking remove button?
}
public void addEmptyRow() {
// why is this method is never reached when clicking add button?
}
public ListDataModel<MultiSelectRow> getRows() {
return (ListDataModel<MultiSelectRow>) getStateHelper().eval(PropertyKeys.rows, null);
}
private void setRows(ListDataModel<MultiSelectRow> rows) {
getStateHelper().put(PropertyKeys.rows, rows);
}
...
}
Теперь - removeRow
и addEmptyRow
никогда не вызывается на MultiInput. Запрос ajax запускается, но где-то он теряется. Зачем?
Есть ли 'rendered' атрибут композит или любой из его родителей? Если да, то вы на 100% оцениваете «истину» во время отправки формы? См. Также http://stackoverflow.com/questions/2118656/hcommandlink-hcommandbutton-is-not-being-invoked У вас кстати довольно красные сельди в коде. Будьте осторожны при упрощении/переименовании. – BalusC
thx @BalusC, я обновил образец, чтобы у него было меньше «красных сельдей» (надеюсь). да, я проверил, что все атрибуты «обработанные» родительские компоненты оцениваются как «истинные». но то, что заставляет меня задаться вопросом, - это пункт 4 в [stackoverflow.com/questions/2118656/...](http://stackoverflow.com/questions/2118656/hcommandlink-hcommandbutton-is-not-being-invoked). кажется, что компонент поддержки не сохраняется. каждый раз, когда я нажимаю кнопку «Удалить» или «Добавить», «CompositeComponentTagHandler.createComponent» создаст новый экземпляр компонента поддержки MultiInput. но почему? – fischermatte
Я создал такие компоненты раньше, и они отлично работают. Я копировал ваш точный код (я просто заменил 'Foo' и' MultiSelectRow' на 'Object' для простоты), и он отлично работает. Ваша конкретная проблема возникает в другом месте, которая пока не показана в коде, опубликованном до сих пор. Возможно, вложенная форма. Возможно, атрибут 'rendered', который оценил' false'. Кто знает. Единственное различие заключается в том, что я не использую Spring и поэтому просто использовал стандартные аннотации JSF для компонента. – BalusC