How to dynamically pass arguments to messages in the resource bundle - jsf

I would like to retrieve the message information from the i18n bundle (messages.properties in seam), but I am not sure how to pass the declare / pass the jobCount variable dynamically in my xhtml
The existing code looks like this.
<s:decorate template="/layout/panel-name.xhtml">
<ui:define name="label">User has been assigned #{jobCount} jobs</ui:define>
</s:decorate>

I think this should work:
<h:outputFormat value="#{msg.yourMessage}">
<f:param value="#{myBean.jobCount}" />
</h:outputFormat>

I found this fragment of code:
#{interpolator.interpolate(messages['myMessage'],jobCount)}
I think this is what you're searching for. Messages and placeHolders
Otherwise you can use string concatenation (ugly) if it's a static message:
<s:decorate template="/layout/panel-name.xhtml">
<ui:define name="label">#{messages['myMessage']} #{jobCount}</ui:define>
</s:decorate>
Or if it's a dynamic message and you're using h:message
Use this syntax in the message properties:
myMessage= User has been assigned {1} jobs
And then when you create the message in the bean
#Name("myBean")
public class Bean {
#In(create = true) FacesMessages facesMessages;
#In Map messages;
public String action() {
// Action here
facesMessages.add(messages.get("myMessage"), jobCount);
}
}

Related

JSF 2 - calling a listener with object parameter from composite component

I have the following question:
I defined my own custom component this way:
<composite:interface componentType="myComponent">
<composite:attribute name="listener" method-signature="void action(java.lang.Object)"/>
...
more attributues
</composite:interface>
Now, in my view, i try to pass a listener with a specific cellphone object that was passed to the view via ui:param tag:
<ui:include src="page.xhtml" >
<ui:param name="currentCellphone" value="#{cellphone}" />
</ui:include>
and then, in the page.xhtml view, i try to do:
<my:myComponent ... listener = "#{backbeanController.backbeanMethod(currentCellphone)}">
Now, if the backbeanmethod is expecting to get a cellphone object as a parameter, when it's gets to the function, the parameter is null. But!, if it's excepted to get string for example, and i send it a string instead of myCellphone object, is works just fine.
I can't pass the myCellphone parameter properly to the backbean. any ideas? Thank you very much.
You can't pass complex object as a parameter, you can just pass a string, say "Id" of the object. Then you have to reconstruct the object but you can use session map like in this example :
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
sessionMap.put("controller", controller);
and call it
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
MyController controller = (MyController) sessionMap.get("controller");
You can read the complete example in Primefaces forum alse see Other link
Hope that helped you.

Dynamic allowed types in PrimeFaces fileUpload

My allowedTypes in PrimeFaces p:fileUpload are not static.They depend on some parameter which is passed as request parameter to the page. So how to change allowedTypes dynamically according to that request parameter.
I just tried it with defining the allowedTypes via a bean property and that is working for me.
So define a allowedTypes property in you bean
public String getAllowedTypes() {
return "/(gif|png)$/";
}
and call it in your page
<p:fileUpload fileUploadListener="#{fileUploadView.handleFileUpload}" mode="advanced" dragDropSupport="false"
update="rocomessages" sizeLimit="100000" fileLimit="3" allowTypes="#{fileUploadView.allowedTypes}" />
I have another idea. Create a String function with parameter(s), this can be used when the types must be dynamics.
This could be the String function in your Bean:
public String getAllowedTypes(String someData) {
if (value.equals("My special types")) {
return "/(\\.|\\/)(json)$/";
}
return "/(\\.|\\/)(ZIP|zip)$/";
}
and, like this, you call ir in the page:
<p:fileUpload allowTypes="#{MyBean.allowedTypes(MyBean.anotherString)}" />
Note: you can use Switch instead of IF in getAllowedTypes function, this must be understand for another uses.

In JSF2.0, how do I write out cookies in facelets?

I know how to write out individual cookies from facelets:
JSF:
<h:outputText value="#{facesContext.externalContext.requestCookieMap['TESTCOOKIE'].value}" />
Outputs:
MyCookieValue
I have been able to write out map, but the output is not the values but a reference to the value.
JSF:
<h:outputText value="#{facesContext.externalContext.requestCookieMap}" />
Output:
{DEFAULTUSERNAME=javax.servlet.http.Cookie#36a236a2,
TESTCOOKIE=javax.servlet.http.Cookie#36b436b4,
JSESSIONID=javax.servlet.http.Cookie#36d836d8}
You don't need such a long value expression to access your cookies in JSF 2.0, there is an implicit object named cookie which references the cookie map and it's equivalent to facesContext.externalContext.requestCookieMap.
So, following code:
<h:outputText value="#{cookie['TESTCOOKIE'].value}" />
should output the same as:
<h:outputText value="#{facesContext.externalContext.requestCookieMap['TESTCOOKIE'].value}" />
Now, if you want to iterate through all of them, my recommendation is to use backing bean:
#RequestScoped
#ManagedBean(name = "triky")
public class TrikyBean {
public List getCookies() {
FacesContext context = FacesContext.getCurrentInstance();
Map cookieMap = context.getExternalContext().getRequestCookieMap();
return new ArrayList(cookieMap.values());
}
}
And then use it like this
<ui:repeat value="#{triky.cookies}" var="ck">
#{ck.name}: #{ck.value}<br/>
</ui:repeat>
Clarification: This comes from the fact that the <ui:repeat /> tag will only accept java.util.List in its value attribute, otherwise it will create its own ListModel with just one element inside. Besides, the collection given by the default implementation of the values() method in a java.util.Map is not a java.util.List but a java.util.Set, so, the <ui:repeat/> tag was using that set as the only element of its own list model and when iterating through that list model the number of elements was just one and none of them were actually cookies.
Maps have a values() method that returns a collection of all elements. I think you need a stronger EL engine than the default to do method invocation outside of getters to do that though, like JBoss EL or JUEL (both of which i strongly recommend for any java ee 6 project).
The alternative is doing method invocation in java and supplying a getter like this:
myBean.java
public Collection getCookies(){
return FacesContext.getCurrentInstance().getExternalContext().getRequestCookieMap().values();
}
And iterating over the collection in your markup
<ui:repeat value="#{myBean.cookies}" var="cookie">
<p>#{cookie.name}: #{cookie.value</p>
</ui:repeat>
Haven't tried this out but something similar will work. You might have to replace the Collection with a List, not sure if ui:repeat supports Collections.
EDIT: as per the comment below, you could try this:
<ui:repeat value="#{facesContext.externalContext.requestCookieMap.values()}" var="cookie">
<p>#{cookie.name}: #{cookie.value</p>
</ui:repeat>

JSF-2 Custom tag to change the styleClass for the child's element

I use JSF 2. I need to write a custom tag which changes the style class for messages inside of it.
So if I have such code:
<my:errorGrid errorClass="#{richBean.erClass}" >
<my:inputField id="pid1" value="#{richBean.pid}" fsType="pid">
</my:inputField>
<h:message for="pid1" ajaxRendered="true"/>
</my:errorGrid>
Error message should be outputted with additional styleClass. The name of this styleClass is taken from the attribute errorClass of the custom tag my:errorGrid
As I undrstand I need to use vcp:body tag in template and process children in encodeChildren() method. Please, could anybody provide me some hints how to realize it? Maybe some advice or links.
Why not using a composite component?
errorGrid.xhtml
<composite:interface>
<composite:attribute name="errorClass"/>
</composite:interface>
<composite:implementation>
<my:inputField id="pid1" value="#{richBean.pid}" fsType="pid">
</my:inputField>
<h:message for="pid1" ajaxRendered="true" errorClass="#{cc.attrs.errorClass}"/>
</composite:implementation>
If you have a classical component though, you simply have to call HtmlMessage.setErrorClass() with your error class before rendering. e.g:
for (UIComponent child : getChildren()){
if(child instanceof HtmlMessage) {
HtmlMessage msgComp = (HtmlMessage) child;
msgComp.setErrorClass(getErrorClass());
}
}

JSF Temporary Variable

Is there a way to temporarily save the value of calcuation in a JSF page?
I want to do the following without calculating twice:
<h:outputText value="#{complexModel.currencyAmount.currency}">
<h:outputText value="#{complexModel.currencyAmount.amount}">
I've tried using the alias bean but I get an error saying java.lang.IllegalArgumentException - row is unavailable.
e.g.
<t:aliasBean id="bean" alias="#{bean}" value="#{complexModel.currencyAmount}">
<h:outputText value="#{bean.currency}">
<h:outputText value="#{bean.amount}">
</t:aliasBean>
Thanks.
Two ways (at least):
Using lazy-init field of your complexModel. something like:
private Currency currencyAmount;
public Currency getCurrencyAmount() {
if (currencyAmount == null) {
currencyAmount = calculateCurrencyAmount();
}
return currencyAmount;
}
Using the JSTL <c:set> tag:
(the namespace first)
xmlns:c="http://java.sun.com/jstl/core"
then
<c:set var="varName" value="#{complexModel.currencyAmount}" />
And then the calculated value will be accessible through #{varName}.
In JSF 2.0,you can use <ui:param/> which it's powerful.
<ui:param name="foo" value="#{zhangsan.foo}"/>

Resources