You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2009/11/30 20:31:28 UTC

svn commit: r885554 - in /myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html: HtmlButtonRendererBase.java HtmlLinkRendererBase.java

Author: lu4242
Date: Mon Nov 30 19:31:27 2009
New Revision: 885554

URL: http://svn.apache.org/viewvc?rev=885554&view=rev
Log:
MYFACES-2417 h:commandButton and h:commandLink now can be rendered outside a form (Thanks to Jakob Korherr for this patch)

Modified:
    myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java
    myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java?rev=885554&r1=885553&r2=885554&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlButtonRendererBase.java Mon Nov 30 19:31:27 2009
@@ -101,15 +101,17 @@
 
         ResponseWriter writer = facesContext.getResponseWriter();
         
-        // If we have javascript enabled, and autoscroll is enabled, 
+        // commandButton does not need to be nested in a form since JSF 2.0
+        FormInfo formInfo = findNestingForm(uiComponent, facesContext);
+        
+        // If we are nested in a form, and we have javascript enabled, and autoscroll is enabled, 
         // we should write the form submit script
         // (define oamSetHiddenInput, oamClearHiddenInput, oamSubmitForm)
         // because oamSetHiddenInput is called on onclick function
-        if (JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
+        if (formInfo != null && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext())
+                && MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll())
         {        
-            if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll()) {
-                HtmlRendererUtils.renderFormSubmitScript(facesContext);
-            }
+            HtmlRendererUtils.renderFormSubmitScript(facesContext);
         }
 
         writer.startElement(HTML.INPUT_ELEM, uiComponent);
@@ -155,7 +157,7 @@
              HtmlRendererUtils.hasClientBehavior(ClientBehaviorEvents.ACTION, behaviors, facesContext)))
         {
             //TODO add the behavior attched rendering here
-            String onClick = buildBehaviorizedOnClick(uiComponent, behaviors, facesContext, writer);
+            String onClick = buildBehaviorizedOnClick(uiComponent, behaviors, facesContext, writer, formInfo);
             if (onClick.length() != 0) {
                 writer.writeAttribute(HTML.ONCLICK_ATTR, onClick.toString(), null);
             }
@@ -171,7 +173,7 @@
         }
         //fallback into the pre 2.0 code to keep backwards comptability with libraries which rely on internals
         else if (JavascriptUtils.isJavascriptAllowed(externalContext)) {
-            StringBuffer onClick = buildOnClick(uiComponent, facesContext, writer);
+            StringBuffer onClick = buildOnClick(uiComponent, facesContext, writer, formInfo);
             if (onClick.length() != 0) {
                 writer.writeAttribute(HTML.ONCLICK_ATTR, onClick.toString(), null);
             }
@@ -197,8 +199,10 @@
 
         writer.endElement(HTML.INPUT_ELEM);
         
-        HtmlFormRendererBase.renderScrollHiddenInputIfNecessary(
-            findNestingForm(uiComponent, facesContext).getForm(), facesContext, writer);
+        if (formInfo != null)
+        {
+            HtmlFormRendererBase.renderScrollHiddenInputIfNecessary(formInfo.getForm(), facesContext, writer);
+        }
         
         // render the UIParameter children of the commandButton (since 2.0)
         for (UIComponent child : uiComponent.getChildren())
@@ -219,7 +223,8 @@
         }
     }
 
-    protected String buildBehaviorizedOnClick(UIComponent uiComponent, Map<String, List<ClientBehavior>> behaviors, FacesContext facesContext, ResponseWriter writer) {
+    protected String buildBehaviorizedOnClick(UIComponent uiComponent, Map<String, List<ClientBehavior>> behaviors, 
+                                              FacesContext facesContext, ResponseWriter writer, FormInfo nestedFormInfo) {
         //TODO fetch parameters from the button
 
         //we can omit autoscroll here for now maybe we should check if it is an ajax behavior and omit it only in this case
@@ -232,20 +237,19 @@
             userOnClick.append(';');
         }
 
-        FormInfo formInfo = findNestingForm(uiComponent, facesContext);
-        if (formInfo == null) {
-            throw new IllegalArgumentException("Component " + uiComponent.getClientId(facesContext) + " must be embedded in an form");
-        }
-        String formName = formInfo.getFormName();
-
         StringBuffer rendererOnClick = new StringBuffer();
-        if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext())) {
-            //call the script to clear the form (clearFormHiddenParams_<formName>) method
-            HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(rendererOnClick, formName);
-        }
-
-        if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll()) {
-            HtmlRendererUtils.appendAutoScrollAssignment(rendererOnClick, formName);
+        
+        if (nestedFormInfo != null) 
+        {
+            String formName = nestedFormInfo.getFormName();
+            if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext())) {
+                //call the script to clear the form (clearFormHiddenParams_<formName>) method
+                HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(rendererOnClick, formName);
+            }
+    
+            if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll()) {
+                HtmlRendererUtils.appendAutoScrollAssignment(rendererOnClick, formName);
+            }
         }
 
         //TODO make parameter resolution here
@@ -259,7 +263,8 @@
 
     }
 
-    protected StringBuffer buildOnClick(UIComponent uiComponent, FacesContext facesContext, ResponseWriter writer)
+    protected StringBuffer buildOnClick(UIComponent uiComponent, FacesContext facesContext, 
+                                        ResponseWriter writer, FormInfo nestedFormInfo)
         throws IOException
     {
         /* DUMMY STUFF
@@ -289,31 +294,28 @@
             DummyFormUtils.setWriteDummyForm(facesContext, true);
         }
         */
-        FormInfo formInfo = findNestingForm(uiComponent, facesContext);
-        if (formInfo == null)
-        {
-            throw new IllegalArgumentException("Component " + uiComponent.getClientId(facesContext) + " must be embedded in an form");
-        }
-        String formName = formInfo.getFormName();
-        UIComponent nestingForm = formInfo.getForm();
-        
         StringBuffer onClick = new StringBuffer();
-        String commandOnClick = (String)uiComponent.getAttributes().get(HTML.ONCLICK_ATTR);
+        String commandOnClick = (String) uiComponent.getAttributes().get(HTML.ONCLICK_ATTR);
 
         if (commandOnClick != null)
         {
             onClick.append(commandOnClick);
             onClick.append(';');
         }
-
-        if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext()))
+        
+        if (nestedFormInfo != null)
         {
-            //call the script to clear the form (clearFormHiddenParams_<formName>) method
-            HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(onClick, formName);
-        }
-
-        if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll()) {
-            HtmlRendererUtils.appendAutoScrollAssignment(onClick, formName);
+            String formName = nestedFormInfo.getFormName();
+    
+            if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext()))
+            {
+                //call the script to clear the form (clearFormHiddenParams_<formName>) method
+                HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(onClick, formName);
+            }
+    
+            if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll()) {
+                HtmlRendererUtils.appendAutoScrollAssignment(onClick, formName);
+            }
         }
 
         //The hidden field has only sense if isRenderClearJavascriptOnButton is

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java?rev=885554&r1=885553&r2=885554&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java Mon Nov 30 19:31:27 2009
@@ -76,13 +76,16 @@
         {
             String clientId = component.getClientId(facesContext);
             FormInfo formInfo = findNestingForm(component, facesContext);
-            String reqValue = (String) facesContext.getExternalContext().getRequestParameterMap().get(
-                HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo));
-            if (reqValue != null && reqValue.equals(clientId))
+            if (formInfo != null)
             {
-                component.queueEvent(new ActionEvent(component));
+                String reqValue = (String) facesContext.getExternalContext().getRequestParameterMap().get(
+                        HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo));
+                if (reqValue != null && reqValue.equals(clientId))
+                {
+                    component.queueEvent(new ActionEvent(component));
 
-                RendererUtils.initPartialValidationAndModelUpdate(component, facesContext);
+                    RendererUtils.initPartialValidationAndModelUpdate(component, facesContext);
+                }
             }
             if (component instanceof ClientBehaviorHolder &&
                     !HtmlRendererUtils.isDisabled(component))
@@ -167,10 +170,15 @@
 
         if (component instanceof UICommand)
         {
-                renderCommandLinkEnd(facesContext, component);
+            FormInfo formInfo = findNestingForm(component, facesContext);
+            
+            renderCommandLinkEnd(facesContext, component, formInfo);
 
-            HtmlFormRendererBase.renderScrollHiddenInputIfNecessary(
-                findNestingForm(component, facesContext).getForm(), facesContext, facesContext.getResponseWriter());
+            if (formInfo != null)
+            {
+                HtmlFormRendererBase.renderScrollHiddenInputIfNecessary(
+                        formInfo.getForm(), facesContext, facesContext.getResponseWriter());
+            }
         }
         else if (component instanceof UIOutcomeTarget)
         {
@@ -196,7 +204,10 @@
         ResponseWriter writer = facesContext.getResponseWriter();
         Map<String, List<ClientBehavior>> behaviors = null;
 
-        if (HtmlRendererUtils.isDisabled(component))
+        // h:commandLink can be rendered outside a form, but with warning (jsf 2.0 TCK)
+        FormInfo formInfo = findNestingForm(component, facesContext);
+        
+        if (HtmlRendererUtils.isDisabled(component) || formInfo == null)
         {
             writer.startElement(HTML.SPAN_ELEM, component);
             if (component instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
@@ -228,7 +239,7 @@
                 if (component instanceof ClientBehaviorHolder)
                 {
                     behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
-                    renderBehaviorizedJavaScriptAnchorStart(facesContext, writer, component, clientId, behaviors);
+                    renderBehaviorizedJavaScriptAnchorStart(facesContext, writer, component, clientId, behaviors, formInfo);
                     if (!behaviors.isEmpty())
                     {
                         HtmlRendererUtils.writeIdAndName(writer, component, facesContext);
@@ -243,14 +254,14 @@
                 }
                 else
                 {
-                    renderJavaScriptAnchorStart(facesContext, writer, component, clientId);
+                    renderJavaScriptAnchorStart(facesContext, writer, component, clientId, formInfo);
                     HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
                     anchorAttrsToRender = HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_ONCLICK_WITHOUT_STYLE;
                 }
             }
             else
             {
-                renderNonJavaScriptAnchorStart(facesContext, writer, component, clientId);
+                renderNonJavaScriptAnchorStart(facesContext, writer, component, clientId, formInfo);
                 HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
                 anchorAttrsToRender = HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_STYLE;
             }
@@ -268,26 +279,21 @@
         {
             writer.writeText(value.toString(), JSFAttr.VALUE_ATTR);
         }
+        
+        // render warning message for a h:commandLink with no nesting form
+        if (formInfo == null)
+        {
+            writer.writeText(": This link is deactivated, because it is not embedded in a JSF form.", null);
+        }
     }
 
     protected void renderJavaScriptAnchorStart(FacesContext facesContext,
                                                ResponseWriter writer,
                                                UIComponent component,
-                                               String clientId)
+                                               String clientId,
+                                               FormInfo formInfo)
         throws IOException
     {
-        //Find form
-        FormInfo formInfo = findNestingForm(component, facesContext);
-        if (formInfo == null)
-        {
-            String path = RendererUtils.getPathToComponent(component);
-            String msg = "Link is not embedded in a form. Change component/tag '" + clientId + "' from javax.faces.*/<h:tagName /> " +
-                "to org.apache.myfaces.*/<t:tagName />, or embed it in a form.  This is not a bug. " +
-                "Please see: http://wiki.apache.org/myfaces/Upgrading_to_Tomahawk_1.1.3 " +
-                "The path to this component is " + path + ". If you need to render a special form and a JSF-form's attributes are not enough," +
-                "consider using the s:form tag of the MyFaces sandbox.";
-            throw new IllegalArgumentException(msg);
-        }
         UIComponent nestingForm = formInfo.getForm();
         String formName = formInfo.getFormName();
 
@@ -361,22 +367,10 @@
             ResponseWriter writer,
             UIComponent component,
             String clientId,
-            Map<String, List<ClientBehavior>> behaviors)
+            Map<String, List<ClientBehavior>> behaviors,
+            FormInfo formInfo)
     throws IOException
     {
-        FormInfo formInfo = findNestingForm(component, facesContext);
-        
-        if (formInfo == null)
-        {
-            String path = RendererUtils.getPathToComponent(component);
-            String msg = "Link is not embedded in a form. Change component/tag '" + clientId + "' from javax.faces.*/<h:tagName /> " +
-                "to org.apache.myfaces.*/<t:tagName />, or embed it in a form.  This is not a bug. " +
-                "Please see: http://wiki.apache.org/myfaces/Upgrading_to_Tomahawk_1.1.3 " +
-                "The path to this component is " + path + ". If you need to render a special form and a JSF-form's attributes are not enough," +
-                "consider using the s:form tag of the MyFaces sandbox.";
-            throw new IllegalArgumentException(msg);
-        }
-
         String commandOnclick;
         if (component instanceof HtmlCommandLink)
         {
@@ -539,7 +533,8 @@
     protected void renderNonJavaScriptAnchorStart(FacesContext facesContext,
                                                   ResponseWriter writer,
                                                   UIComponent component,
-                                                  String clientId)
+                                                  String clientId,
+                                                  FormInfo formInfo)
         throws IOException
     {
         ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
@@ -565,7 +560,7 @@
                 hrefBuf.append('&');
             }
         }
-        String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(findNestingForm(component, facesContext));
+        String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo);
         hrefBuf.append(hiddenFieldName);
         hrefBuf.append('=');
         hrefBuf.append(clientId);
@@ -857,11 +852,11 @@
         }
     }
 
-    protected void renderCommandLinkEnd(FacesContext facesContext, UIComponent component)
+    protected void renderCommandLinkEnd(FacesContext facesContext, UIComponent component, FormInfo formInfo)
             throws IOException
     {
         ResponseWriter writer = facesContext.getResponseWriter();
-        if (HtmlRendererUtils.isDisabled(component))
+        if (HtmlRendererUtils.isDisabled(component) || formInfo == null)
         {
 
             writer.endElement(HTML.SPAN_ELEM);