Author: dan.j.allen
Date: 2010-06-17 19:07:42 -0400 (Thu, 17 Jun 2010)
New Revision: 13231
Modified:
examples/trunk/booking-simplified/src/main/java/org/jboss/seam/faces/component/UIInputContainer.java
examples/trunk/booking-simplified/src/main/webapp/register.xhtml
Log:
xval ajax
Modified:
examples/trunk/booking-simplified/src/main/java/org/jboss/seam/faces/component/UIInputContainer.java
===================================================================
---
examples/trunk/booking-simplified/src/main/java/org/jboss/seam/faces/component/UIInputContainer.java 2010-06-17
23:07:20 UTC (rev 13230)
+++
examples/trunk/booking-simplified/src/main/java/org/jboss/seam/faces/component/UIInputContainer.java 2010-06-17
23:07:42 UTC (rev 13231)
@@ -24,6 +24,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -36,7 +37,7 @@
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
-import javax.faces.component.UIInput;
+import javax.faces.component.UIForm;
import javax.faces.component.UIMessage;
import javax.faces.component.UINamingContainer;
import javax.faces.component.UIViewRoot;
@@ -117,6 +118,10 @@
*/
public static final String COMPONENT_TYPE =
"org.jboss.seam.faces.InputContainer";
+ public static final String DYNAMIC_AJAX_BEHAVIOR =
"org.jboss.seam.faces.DYNAMIC_AJAX_BEHAVIOR";
+
+ public static final String FORM_TOKEN = "@form";
+
protected static final String HTML_ID_ATTR_NAME = "id";
protected static final String HTML_CLASS_ATTR_NAME = "class";
protected static final String HTML_STYLE_ATTR_NAME = "style";
@@ -267,9 +272,11 @@
}
// temporary workaround for state saving bug; remove any ClientBehaviors added
dynamically
+ // this needs to be less aggressive...need to track exactly what we added
for (EditableValueHolder i : elements.getInputs())
{
- if (i instanceof ClientBehaviorHolder)
+ if (i instanceof ClientBehaviorHolder &&
+ ((UIComponent) i).getAttributes().remove(DYNAMIC_AJAX_BEHAVIOR) != null)
{
Map<String, List<ClientBehavior>> b = ((ClientBehaviorHolder)
i).getClientBehaviors();
for (String k : b.keySet())
@@ -336,7 +343,18 @@
{
if (elements == null)
{
- elements = new InputContainerElements(getId(), getAttributes());
+ UIComponent node = getParent();
+ UIForm form = null;
+ while (node != null)
+ {
+ if (node instanceof UIForm)
+ {
+ form = (UIForm) node;
+ break;
+ }
+ node = node.getParent();
+ }
+ elements = new InputContainerElements(getId(), form != null ? ":" +
form.getClientId() : null, getAttributes());
}
// NOTE we need to walk the tree ignoring rendered attribute because it's
@@ -475,6 +493,7 @@
public class InputContainerElements
{
private String containerId;
+ private String formId;
private Map<String, Object> attributes;
private String propertyName;
private HtmlOutputLabel label;
@@ -483,10 +502,11 @@
private boolean validationError = false;
private boolean requiredInput = false;
- public InputContainerElements(final String containerId, final Map<String,
Object> attributes)
+ public InputContainerElements(final String containerId, final String formId, final
Map<String, Object> attributes)
{
this.containerId = containerId;
this.attributes = attributes;
+ this.formId = formId;
}
public HtmlOutputLabel getLabel()
@@ -518,13 +538,20 @@
if (ajaxEvent != null)
{
Map<String, List<ClientBehavior>> behaviors =
bh.getClientBehaviors();
- if (!behaviors.containsKey(ajaxEvent))
+ // QUESTION should we clear or honor what is present?
+ if (behaviors.containsKey(ajaxEvent))
{
- AjaxBehavior ajax = new AjaxBehavior();
- ajax.setRender(Arrays.asList(containerId));
- bh.addClientBehavior(ajaxEvent.toLowerCase(), ajax);
+ behaviors.get(ajaxEvent).clear();
}
+ ((UIComponent) input).getAttributes().put(DYNAMIC_AJAX_BEHAVIOR,
ajaxEvent);
+ AjaxBehavior ajax = new AjaxBehavior();
+ ajax.setRender(Arrays.asList(containerId));
+ bh.addClientBehavior(ajaxEvent.toLowerCase(), ajax);
}
+ else
+ {
+ interpolateAjaxTargets(bh);
+ }
}
if (input.isRequired() || isRequiredByConstraint(input, validator, context))
{
@@ -549,6 +576,35 @@
}
}
+ private void interpolateAjaxTargets(ClientBehaviorHolder bh)
+ {
+ Map<String, List<ClientBehavior>> behaviors =
bh.getClientBehaviors();
+ for (List<ClientBehavior> behaviorsForEvent : behaviors.values())
+ {
+ for (ClientBehavior b : behaviorsForEvent)
+ {
+ if (b instanceof AjaxBehavior)
+ {
+ AjaxBehavior a = (AjaxBehavior) b;
+ Collection<String> original = a.getExecute();
+ Collection<String> translated = new ArrayList<String>();
+ for (String o : original)
+ {
+ translated.add(o.replace(FORM_TOKEN, formId));
+ }
+ a.setExecute(translated);
+ original = a.getRender();
+ translated = new ArrayList<String>();
+ for (String o : original)
+ {
+ translated.add(o.replace(FORM_TOKEN, formId));
+ }
+ a.setRender(translated);
+ }
+ }
+ }
+ }
+
public List<UIMessage> getMessages()
{
return messages;
Modified: examples/trunk/booking-simplified/src/main/webapp/register.xhtml
===================================================================
--- examples/trunk/booking-simplified/src/main/webapp/register.xhtml 2010-06-17 23:07:20
UTC (rev 13230)
+++ examples/trunk/booking-simplified/src/main/webapp/register.xhtml 2010-06-17 23:07:42
UTC (rev 13231)
@@ -30,7 +30,8 @@
<h:form id="registrationForm" prependId="false">
<fieldset>
-
+ <h:outputScript name="jsf.js" library="javax.faces"
target="head"/>
+
<!-- manually append Ajax behavior -->
<p:input id="username">
<h:inputText id="input"
value="#{newUser.username}"
@@ -40,21 +41,32 @@
</p:input>
<!-- automatically append Ajax behavior -->
- <p:input id="name" ajax="default">
+ <p:input id="name" ajax="blur">
<h:inputText id="input"
value="#{newUser.name}"/>
</p:input>
- <p:input id="email" ajax="default">
+ <p:input id="email" ajax="blur">
<h:inputText id="input"
value="#{newUser.email}"/>
</p:input>
- <p:input id="password" ajax="default">
+ <p:input id="password" ajax="blur">
<h:inputSecret id="input"
value="#{newUser.password}" redisplay="true"/>
</p:input>
- <p:input id="confirmPassword" ajax="default">
- <h:inputSecret id="input"
value="#{registrar.confirmPassword}" redisplay="true"/>
+ <p:input id="confirmPassword">
+ <h:inputSecret id="input"
value="#{registrar.confirmPassword}" redisplay="true">
+ <f:ajax event="blur"
+ execute="@this @form:password:input
@form:passwordCheck"
+ render="confirmPassword @form:password
:messages"/>
+ </h:inputSecret>
</p:input>
+
+ <ui:remove><!--
+ <p:input id="confirmPassword">
+ <h:inputSecret id="input"
value="#{registrar.confirmPassword}" redisplay="true">
+ <f:ajax event="blur" execute="@form"
render="@form :messages"/>
+ </h:inputSecret>
+ </p:input>--></ui:remove>
<div class="buttonBox">
<h:commandButton id="register" value="Register"
action="#{registrar.register}"/>
@@ -64,7 +76,7 @@
</fieldset>
- <s:validateForm validatorId="confirmPasswordValidator"
+ <s:validateForm id="passwordCheck"
validatorId="confirmPasswordValidator"
fields="newPassword=password:input
confirmPassword=confirmPassword:input"/>
</h:form>