The c:choose and c:when tags you are using are JSTL tags, not JSF tags. This means they are evaluated at build time, rather than at render time. When you post back, the component tree does not get rebuilt, rather it get's re-rendered, and the c: tags don't get re-evaluated.
The and tags you are using are JSTL tags, not JSF tags. This means they are evaluated at build time, rather than at render time. When you post back, the component tree does not get rebuilt, rather it get's re-rendered, and the tags instead of the See this write-up for more details: drewdev.blogspot.com/2008/03/build-time-... It is very important to remember that you cannot have components "re-appear" on post back of a JSF form.
This is because a JSF component tree should never be altered between having its state saved and when its state is restored. This is very important, so let me say again, a JSF component tree should never be altered between having its state saved and when its state is restored.
Thank you Brian. I tried to implement field-component. Xhtml following your advice.
I also read through your blog article (nice but difficult for me just now). I edited the question with your suggestion, but it still does not work:-( – Fekete Kamosh Jun 10 '10 at 7:55 I added title attribute to h:inputText to show that in Render response phase new value (cc.attrs. FieldValue) is not applied to h:inputText attributes.
For the first time fill in " Field content is " title is " Then try to clear content->Store. Field content is empty but title is still " This is what puzzles me. – Fekete Kamosh Jun 10 '10 at 11:00 It seems that value sent in http request is applied only to "value" attribute of h:inputText and not to any other attribute of h:inputText tag.Am I right?
Is it correct behaviour? – Fekete Kamosh Jun 10 '10 at 12:04 The tag set an attribute of the inputText element, not an attribute of the custom component. I think you can achieve you're desired effect in a standard way by using an `' tag.
– Brian Leathem Jun 10 '10 at 14:43.
I did some investigation and debugging in the last two days and this is my result. First of all, I simplified example to omit composite component and to have it as simple as possible. Managed bean (TesterBean2.
Java) package cz. Test; import javax.faces.bean. ManagedBean; import javax.faces.bean.
RequestScoped; @ManagedBean @RequestScoped public class TesterBean2 { // Simple DataStore (in real world EJB) private static String storedSomeValue = null; private String someValue; public TesterBean2() { } public String storeValue() { storedSomeValue = someValue; return "index"; } public String eraseValue() { storedSomeValue = null; return "index"; } public String getSomeValue() { someValue = storedSomeValue; return someValue; } public void setSomeValue(String someValue) { this. SomeValue = someValue; } } Testing page (index. Xhtml) Testing page Where is the problem?
I think it is problem of com.sun.faces. Renderkit_html_basic. TextRenderer and its method getEndTextToRender: protected void getEndTextToRender(FacesContext context, UIComponent component, String currentValue) throws IOException { ResponseWriter writer = context.
GetResponseWriter(); assert(writer! = null); boolean shouldWriteIdAttribute = false; boolean isOutput = false; String style = (String) component.getAttributes(). Get("style"); String styleClass = (String) component.getAttributes().
Get("styleClass"); String dir = (String) component.getAttributes(). Get("dir"); String lang = (String) component.getAttributes(). Get("lang"); String title = (String) component.getAttributes().
Get("title"); if (component instanceof UIInput) { writer. StartElement("input", component); writeIdAttributeIfNecessary(context, writer, component); writer. WriteAttribute("type", "text", null); writer.
WriteAttribute("name", (component. GetClientId(context)), "clientId"); // only output the autocomplete attribute if the value // is 'off' since its lack of presence will be interpreted // as 'on' by the browser if ("off". Equals(component.getAttributes().
Get("autocomplete"))) { writer. WriteAttribute("autocomplete", "off", "autocomplete"); } // render default text specified if (currentValue! = null) { writer.
WriteAttribute("value", currentValue, "value"); } // Rest of code omitted } A currentValue parameter is explicitly passed into this method called from com.sun.faces.renderkit. Html_basic. HtmlBasicRenderer.
EncodeEnd @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { rendererParamsNotNull(context, component); if (!shouldEncode(component)) { return; } ResponseWriter writer = context. GetResponseWriter(); assert(writer! = null); // NOTICE currentValue getter String currentValue = getCurrentValue(context, component); if (logger.
IsLoggable(Level. FINE)) { logger. Log(Level.
FINE, "Value to be rendered {0}", currentValue); } // NOTICE currentValue getEndTextToRender(context, component, currentValue); } and if we look closer at a method getCurrentValue() /** * @param context the FacesContext for the current request * @param component the UIComponent whose value we're interested in * * @return the value to be rendered and formats it if required. Sets to * empty string if value is null. */ protected String getCurrentValue(FacesContext context, UIComponent component) { if (component instanceof UIInput) { Object submittedValue = ((UIInput) component).
GetSubmittedValue(); if (submittedValue! = null) { // value may not be a String... return submittedValue.toString(); } } String currentValue = null; Object currentObj = getValue(component); if (currentObj! = null) { currentValue = getFormattedValue(context, component, currentObj); } return currentValue; } the property returned by getSubmittedValue() is filled in Restore View phase (if Process validation phase skips to Render response phase).
As a consequence we get "updated" value which was passed from user only for value attribute, the rest remain unaltered. In case of successful Process Validation phase, which does not cause direct skip to Render Response phase (if user fills in any not null value), a new constructor of HtmlInputText is called and style, title etc. Attributes are filled from the scratch. These attributes are filled from managed bean which was updated with proper data in phase Update Model Values.
OK, this is not a bug, but the feature. It only affirms my thesis that something smells in the sentence: "If the request is a postback and errors were encountered during the apply request values phase, process validations phase, or update model values phase, the original page is rendered during Render response phase". Any clue how to solve this situation if I really long for yellow background for mandatory fields?
Updated project is here: http://www.221b.cz/so/JSFTester2.zip.
I have finally managed to get the validation to work. I used validator which has access to UIComponent. In case of failed validation special style is applied to the component.
This style is also taken into consideration in Render response phase. So how does it behave? View is restored including style style="#{empty testerBean2.
SomeValue? 'background-color: yellow;' : ''}" Validation does not pass. So testerBean2.
SomeValue is not updated (as Update Model Values phase is skipped) but constant style is set into h:inputText using RequiredValidator - component. SetValueExpression("style", new ValueExpressionLiteral("background-color: yellow;", String. Class)); In Render Response yellow background is applied even if testerBean.
SomeValue has not been updated as Required Validator has already set constant new ValueExpressionLiteral("background-color: yellow;", String. Class) I have implemented own required validator (inspired by Bashan's validator from http://www.codereye.com/2009/12/validating-empty-text-field-using-jsf.html). RequiredValidator.
Java package cz. Test; import javax.faces.application. FacesMessage; import javax.faces.component.
UIComponent; import javax.faces.context. FacesContext; import javax.faces.validator. Validator; import javax.faces.validator.
ValidatorException; import org.apache.el. ValueExpressionLiteral; public class RequiredValidator implements Validator { public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { if (value == null || "". Equals(value.toString().trim())) { FacesMessage message = new FacesMessage(); String messageStr = (String) component.getAttributes().
Get("message"); if (messageStr == null) { messageStr = "Please enter data"; } message. SetDetail(messageStr); message. SetSummary(messageStr); message.
SetSeverity(FacesMessage. SEVERITY_ERROR); component. SetValueExpression("style", new ValueExpressionLiteral("background-color: yellow;", String.
Class)); throw new ValidatorException(message); } else { component. SetValueExpression("style", new ValueExpressionLiteral("", String. Class)); } } } The line I added: component.
SetValueExpression("style", new ValueExpressionLiteral("background-color: yellow;", String. Class)); to force JSF trigger validation for empty fields (web. Xml): .... javax.faces.
VALIDATE_EMPTY_FIELDS true .... to register validator with JSF (faces-config. Xml): RequiredValidator cz.test. RequiredValidator and web page using required validator and TesterBean2 (index.
Xhtml): Testing page NOTICE: There cannot be used required attribute in h:inputText. It would outrun required validator.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.