You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by bo...@apache.org on 2024/02/08 13:28:26 UTC

(myfaces-tobago) branch main updated: fix(behavior): Avoid error msg when using cc:clientBehavior with targ… (#4858)

This is an automated email from the ASF dual-hosted git repository.

bommel pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git


The following commit(s) were added to refs/heads/main by this push:
     new 4057d8ad65 fix(behavior): Avoid error msg when using cc:clientBehavior with targ… (#4858)
4057d8ad65 is described below

commit 4057d8ad65666cd0c419159eca4fb30bdcc37ba6
Author: Bernd Bohmann <bo...@apache.org>
AuthorDate: Thu Feb 8 14:28:21 2024 +0100

    fix(behavior): Avoid error msg when using cc:clientBehavior with targ… (#4858)
    
    * fix(behavior): Avoid error msg when using cc:clientBehavior with target attribute and f:ajax and @this
    issue: TOBAGO-2287
---
 .../renderer/TobagoClientBehaviorRenderer.java     |  6 ++--
 .../apache/myfaces/tobago/util/ComponentUtils.java | 41 +++++++++++++++++++---
 .../src/test/resources/renderer/button/ajax.html   |  2 +-
 .../Composite_Components.xhtml                     |  6 ++++
 .../resources/demo-components/inputAsText.xhtml    |  1 +
 5 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java
index 7d307edca4..a100c11a12 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java
@@ -106,10 +106,10 @@ public class TobagoClientBehaviorRenderer extends jakarta.faces.render.ClientBeh
       }
 
       executeIds = ComponentUtils.evaluateClientIds(facesContext, uiComponent, execute.toArray(new String[0]));
-      if (executeIds != null) {
-        executeIds = executeIds + " " + clientId;
-      } else {
+      if (executeIds == null) {
         executeIds = clientId;
+      } else if (!executeIds.contains(clientId)) {
+        executeIds = executeIds + " " + clientId;
       }
       if (uiComponent instanceof AbstractUICommand) { // <f:ajax> inside of a command
         final AbstractUICommand command = (AbstractUICommand) uiComponent;
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java
index 442f775601..8c8c5aee66 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java
@@ -648,6 +648,30 @@ public final class ComponentUtils {
    * </p>
    */
   public static UIComponent findComponent(final UIComponent from, final String relativeId) {
+    return findComponent(FacesContext.getCurrentInstance(), from, relativeId);
+  }
+    /**
+     * <p>
+     * The search depends on the number of prefixed colons in the relativeId:
+     * </p>
+     * <dl>
+     * <dd>number of prefixed colons == 0</dd>
+     * <dt>fully relative</dt>
+     * <dd>number of prefixed colons == 1</dd>
+     * <dt>absolute (still normal findComponent syntax)</dt>
+     * <dd>number of prefixed colons == 2</dd>
+     * <dt>search in the current naming container (same as 0 colons)</dt>
+     * <dd>number of prefixed colons == 3</dd>
+     * <dt>search in the parent naming container of the current naming container</dt>
+     * <dd>number of prefixed colons &gt; 3</dd>
+     * <dt>go to the next parent naming container for each additional colon</dt>
+     * </dl>
+     * <p>
+     * If a literal is specified: to use more than one identifier the identifiers must be space delimited.
+     * </p>
+     */
+  public static UIComponent findComponent(
+      final FacesContext facesContext, final UIComponent from, final String relativeId) {
     UIComponent from1 = from;
     String relativeId1 = relativeId;
     final int idLength = relativeId1.length();
@@ -659,8 +683,9 @@ public final class ComponentUtils {
 
     // Figure out how many colons
     int colonCount = 0;
+    char separatorChar = UINamingContainer.getSeparatorChar(facesContext);
     while (colonCount < idLength) {
-      if (relativeId1.charAt(colonCount) != UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance())) {
+      if (relativeId1.charAt(colonCount) != separatorChar) {
         break;
       }
       colonCount++;
@@ -692,9 +717,15 @@ public final class ComponentUtils {
     final List<String> result = new ArrayList<>(componentIds.length);
     for (final String id : componentIds) {
       if (!StringUtils.isBlank(id)) {
-        final String clientId = evaluateClientId(context, component, id);
-        if (clientId != null) {
-          result.add(clientId);
+        if (id.startsWith("@this:") && id.endsWith(component.getId())) {
+          // case for cc:clientBehavior with targets attribute
+          // @this:<id>)
+          result.add(component.getClientId(context));
+        } else {
+          final String clientId = evaluateClientId(context, component, id);
+          if (clientId != null) {
+            result.add(clientId);
+          }
         }
       }
     }
@@ -710,7 +741,7 @@ public final class ComponentUtils {
    */
   public static String evaluateClientId(
       final FacesContext context, final UIComponent component, final String componentId) {
-    final UIComponent partiallyComponent = ComponentUtils.findComponent(component, componentId);
+    final UIComponent partiallyComponent = ComponentUtils.findComponent(context, component, componentId);
     if (partiallyComponent != null) {
       final String clientId = partiallyComponent.getClientId(context);
       if (partiallyComponent instanceof AbstractUISheet) {
diff --git a/tobago-core/src/test/resources/renderer/button/ajax.html b/tobago-core/src/test/resources/renderer/button/ajax.html
index aad008ba7b..d23b199efc 100644
--- a/tobago-core/src/test/resources/renderer/button/ajax.html
+++ b/tobago-core/src/test/resources/renderer/button/ajax.html
@@ -15,4 +15,4 @@
  * limitations under the License.
 -->
 
-<button type='button' id='id' name='id' class='tobago-button btn btn-secondary tobago-auto-spacing'><tobago-behavior event='click' client-id='id' execute='id id' render='id' reset-values='reset-values'></tobago-behavior><span>button</span></button>
+<button type='button' id='id' name='id' class='tobago-button btn btn-secondary tobago-auto-spacing'><tobago-behavior event='click' client-id='id' execute='id' render='id' reset-values='reset-values'></tobago-behavior><span>button</span></button>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/5500-compositeComponent/Composite_Components.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/5500-compositeComponent/Composite_Components.xhtml
index 5e4493256e..095fd84321 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/5500-compositeComponent/Composite_Components.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/5500-compositeComponent/Composite_Components.xhtml
@@ -19,6 +19,7 @@
 
 <ui:composition template="/main.xhtml"
                 xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:f="http://xmlns.jcp.org/jsf/core"
                 xmlns:dc="jakarta.faces.composite/demo-components"
                 xmlns:tc="http://myfaces.apache.org/tobago/component"
                 xmlns:ui="jakarta.faces.facelets">
@@ -64,4 +65,9 @@
       <dc:inputAsTextPanelWrapper id="splitLayoutNotRendered" value="this should NOT be rendered" rendered="false"/>
     </tc:splitLayout>
   </tc:section>
+  <tc:section label="clientBehavior">
+    <dc:inputAsText id="clientBehavior">
+      <f:ajax event="change" execute="@this" render="clientBehavior" />
+    </dc:inputAsText>
+  </tc:section>
 </ui:composition>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/resources/demo-components/inputAsText.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/resources/demo-components/inputAsText.xhtml
index 4e68353cae..a4fb244863 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/resources/demo-components/inputAsText.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/resources/demo-components/inputAsText.xhtml
@@ -24,6 +24,7 @@
   <cc:attribute name="label"/>
   <cc:attribute name="value"/>
   <cc:attribute name="asText" default="false"/>
+  <cc:clientBehavior name="change" event="change" targets="in"/>
 </cc:interface>
 <cc:implementation>
   <tc:in id="in" label="#{cc.attrs.label}" value="#{cc.attrs.value}" rendered="#{!cc.attrs.asText}"/>