Converter can't get rich:dataGrid rows as custom parameters - jsf

I need a converter with custom parameters, I've made it and it works well, except when I use it with row elements and I can't understand why, ideas?
Examples
This works well:
<h:outputText value="#{bean.value}">
<cc:converter param="#{bean.attribute}" />
</h:outputText>
also this one:
<h:outputText value="#{bean.value}">
<cc:converter param="fixedValue" />
</h:outputText>
this one doesn't work at all, param is null inside the converter:
<rich:dataGrid value="#{bean.list}" var="row">
<h:outputText value="#{row.value}">
<cc:converter param="#{row.attribute}" />
</h:outputText>
</rich:dataGrid>

See BalusC link. It describes why your converter doesn't work. Converter without parameters works fine inside datatable in JSF 1.2. For simulate conversion you can use getter method in object which represents row like getConvertedValue and move your code from converter into this method. After that in datatable you can call #{row.convertedValue} for displaying the converted value.

Related

Dynamically setting value of a h:selectOneMenu using c:forEach

I'm working on a project that requires me to display and be able to select and store tags to the product. Tags are provided in tree-like structure. I can't assume maximum depth of a tags tree.
I wanted to display tags split by levels, using c:forEach - p:selectManyCheckbox - f:selectItems, and handling selections using p:ajax components.
I use following types to store possible values and selections in Tree object:
HashMap<Long, ArrayList<Tag>> tree;
HashMap<Long, Object[]> selected;
Hashmap keys are equal to "tag level".
In order to display values I use following code for testing:
<p:panelGrid id="tagDisplay" columns="2">
<c:forEach begin="1" end="5" var="idx">
<p:outputLabel value="#{idx}"></p:outputLabel>
<p:selectManyCheckbox value="#{product.tags.selected[1]}">
<f:selectItems value="#{product.tags.tree[1]}" var="tag" itemLabel="#{tag.name}" itemValue="#{tag.id}" />
<p:ajax listener="#{product.selectorListener}" update="tagDisplay" />
</p:selectManyCheckbox>
</c:forEach>
</p:panelGrid>
Code seemed to work fine, though displayed five times.
Now I'm stuck trying to dynamically bind Hashmaps to selectors. As I replaced "1" with "idx", I got no results.
I tried to use ui-repeat with a dummy table, but then I lost panelgrid structure.
Any help will be appreciated!
My environment - Websphere 8.5, JSF 2.2, Primefaces 5.2
The <c:forEach begin end> is only for static iteration, not for dynamic iteration.
You'd better iterate over #{product.tags.tree} itself in <c:forEach items>. Each iteration over a Map will give Map.Entry back which in turn has getKey() and getValue() methods.
<p:panelGrid ...>
<c:forEach items="#{product.tags.tree}" var="entry" varStatus="loop">
<p:outputLabel value="#{loop.index}"></p:outputLabel>
<p:selectManyCheckbox value="#{product.tags.selected[entry.key]}">
<f:selectItems value="#{entry.value}" ... />
...
</p:selectManyCheckbox>
</c:forEach>
</p:panelGrid>
That said, must it really be a HashMap? Don't you rather want a fixed ordered LinkedHashMap?

Filtering issues (no change in contents) in datatable primefaces 3.5, sorting works

Primefaces 3.5 doesn't seem to filter data at all from the datatable, oddly enough it somehow reorders them as I type, so, there must be some AJAX calls firing, but obviously not the right ones.
<h:panelGroup id="table-wrapper-component">
<prime:dataTable
rendered="#{artifactSelectionBackingBean.visibleComps}"
value="#{artifactSelectionBackingBean.components}"
var="tagInfoObject" emptyMessage="No tags found with given criteria"
filteredValue="#{artifactSelectionBackingBean.filteredComponents}">
<prime:ajax event="filter" global="false" />
<prime:column sortBy="#{tagInfoObject.tagId}"
headerText="Identifier" filterMatchMode="contains" filterBy = "#{tagInfoObject.tagId}">
<h:outputText value="#{tagInfoObject.tagId}" />
</prime:column>
<prime:column sortBy="#{tagInfoObject.type.tagTypeId}"
headerText="Tag Identifier" filterMatchMode="contains" filterBy ="#{tagInfoObject.type.tagTypeId}">
<h:outputText value="#{tagInfoObject.type.tagTypeId}" />
</prime:column>
<prime:column sortBy="#{tagInfoObject.title}" headerText="Title" filterMatchMode="contains" filterBy="#{tagInfoObject.title}">
<h:outputText value="#{tagInfoObject.title}" />
</prime:column>
<prime:column filterBy="#{tagInfoObject.description}"
filterMatchMode="contains" sortBy="#{tagInfoObject.description}"
styleClass="wrap" headerText="Component Description">
<h:outputText value="#{tagInfoObject.description}" />
</prime:column>
</prime:dataTable>
</h:panelGroup>
Any help is appreciated! All the Beans and method calls exist and return the appropriate data, just that the filtering doesn't seem to work at all.
Also, note that sorting functions properly only filtering does not!
The issue was that you always need to wrap any filtering/sorting attributes in a data table with an h:form tag. This is not explicitly specified in the documentation of PrimeFaces, however, it is in the showcase here. I wrapped the whole thing in form tags.
So, don't forget to wrap your data tables in a form if you want any type of interaction provided by primefaces.
Your managed Bean Code will do a lot of good
Post your managed bean code.
May be you have not set the value for artifactSelectionBackingBean.filteredComponents in the managed bean

JSF2 Building Dynamic EL Expressions

I am working on creating a dynamic table using JSTL forEach and a h:dataTable and have all of the controls and potential error message showing nicely, but am now stuck on getting the value set for each of the control. I will need to create (I think) a dynamic EL expression to set the value, but have not been able to get any of my versions to work. I was hoping to build out the expression using c:out, but found out that that tag is not available in JSF2.
So, is it possible to build a dynamic expression in the page?
How can I set the expression in the backing bean if the control hasn't been built yet ?
<h:dataTable id="dtDetails" styleClass="slate_table" value="#{remediationDetail.eventList}" var="dataItem">
<c:forEach items="#{remediationDetail.eventHeaders}" var="key">
<h:column>
<f:facet name="header">#{key.fieldDefinition.fieldConfiguration.customLabel}</f:facet>
<h:inputText value="" id="txtNumber" styleClass="remediation_textbox error_marker" title="#{remediationDetail.errorMessages(dataItem.id, key.fieldDefinition.id)}">
<f:convertNumber maxFractionDigits="0" maxIntegerDigits="19"/>
</h:column>
</c:forEach>
</h:dataTable>
As always, any help or direction is appreciated.
Regards,
Mike
I was not being able to create a Dynamic EL Expression. So, I ended using the index of the c:forEach to help define what values I am looking for. The only catch for this result is that I would be expecting the data that I am about to display to have the same number of positions in the array.
<c:forEach items="#{remediationDetail.eventHeaders}" var="key" varStatus="looper">
<h:column>
<f:facet name="header">#{key.fieldDefinition.fieldConfiguration.customLabel}</f:facet>
<h:inputText id="txtNumber" value="#{dataItem.entityList[looper.index].val}">
<f:convertNumber maxFractionDigits="0" maxIntegerDigits="19"/>
</h:inputText>
</h:column>
</c:forEach>
In my case the following helped to build dynamic EL.
<ui:param name="beanName" value="myBackedBean"/>
<ui:param name="propertyName" value="field1"/>
<ui:param name="nestedPropertyName" value="field1"/>
<p:inputTextarea value="#{sessionScope[beanName][propertyName][nestedPropertyName]}"/>
Inspired of this topic

Custom data types in Facelets JSF 2 Expression Language

How to display a custom property using facelet expression language?
For example:
<h:outputText value="#{contact.customTypeProperty}" />
where customTypeProperty is of type CustomClass, and I want to display the String returned by its toString()?
That should already be the default behaviour. You don't need to change anything on the given code example, assuming that the toString() method is properly implemented on the CustomClass. However, if it returns HTML, you'd need to add escape="false" to the output text to prevent JSF from auto-escaping it (which it does in order to prevent XSS attacks on user-controlled input):
<h:outputText value="#{contact.customTypeProperty}" escape="false" />
This is however not necessarily the best practice. You should control the presentation in the view side, not in a toString() in the model side. For example, assuming that CustomClass has in turn two properties foo and bar and you'd like to present it in a table:
<h:panelGrid columns="2">
<h:outputText value="Foo" />
<h:outputText value="#{contact.customTypeProperty.foo}" />
<h:outputText value="Bar" />
<h:outputText value="#{contact.customTypeProperty.bar}" />
</h:panelGrid>
If you did this to avoid code repetition, then you should actually be using an include file or a tag file. See also When to use <ui:include>, tag files, composite components and/or custom components?

combining rich:inplaceInput with rich:suggestionbox

We want to pre-fill our richfaces suggestion-box with a inplace text.
Are there any recommendations on how to do this? I think, simple replacement of h:inputText to rich:inplaceInput will not work.
<h:inputText id="field" value="#{form.field}" required="true" /><rich:in
<rich:suggestionbox id="suggestionBoxId" for="field" suggestionAction="#{suggestion.autocomplete}" var="result" fetchValue="#{result.zip} #{result.cityName}" minChars="3">
<h:column>
<h:outputText value="#{result.text}" />
</h:column>
</rich:suggestionbox>
If I understand the question correctly, you could simply define form.field as whatever you want to pre-fill with in the #PostConstruct method of the form bean. Or even the constructor, really.

Resources