ICEfaces
  1. ICEfaces
  2. ICE-6659

ice:inputText required validation not happening properly inside portlet

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 2.0.0
    • Fix Version/s: 2.0.1
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      Icefaces 2.0 Mozilla Firefox 3.6.15

      Description

      Hi,

      I have the ice:inputText with a required validation on it. The validation only happens when i click on a ice:commandButton which has immediate=false.
      It does not happen as soon as i move out of the ice:inputText.

      As a side note, once the error messages are displayed(After clicking on the ice:commandButton which has immediate=false), if i enter some data into the required fields, the error messages are gone which is good.

      But the issue as described, the validation does not happen as soon as i move out of the inputText.

      Please let us know if this can be resolved.
      Find the attached xhtml that i used.

        Issue Links

          Activity

          Hide
          Neil Griffin added a comment -

          This can also be reproduced with the Example ICEfaces 2.x Portlet at portletfaces.org:
          http://www.portletfaces.org/portletfaces-bridge/examples/icefaces-2.x-portlet

          Show
          Neil Griffin added a comment - This can also be reproduced with the Example ICEfaces 2.x Portlet at portletfaces.org: http://www.portletfaces.org/portletfaces-bridge/examples/icefaces-2.x-portlet
          Hide
          Deryk Sinotte added a comment -

          A couple of notes:

          1) The behaviour in the demo that Neil submitted looks to be related to the use of singleSubmit rather than partialSubmit. The singleSubmit is triggered by onChange rather than onBlur. Checking the traffic, you can see that nothing is submitted unless a change is actually made to the value of the field. This is the current behaviour of singleSubmit.

          2) The behaviour described by the original reporter looks to be portlet-specific. Adding the same basic code to a normal app works fine. Taking the same markup and putting it in a portlet ends up the the validation messages not being added to the FacesContext.

          I'm going to look next to see if it's just the "required" validation that's a problem or if other built-in validations have the same issue.

          Show
          Deryk Sinotte added a comment - A couple of notes: 1) The behaviour in the demo that Neil submitted looks to be related to the use of singleSubmit rather than partialSubmit. The singleSubmit is triggered by onChange rather than onBlur. Checking the traffic, you can see that nothing is submitted unless a change is actually made to the value of the field. This is the current behaviour of singleSubmit. 2) The behaviour described by the original reporter looks to be portlet-specific. Adding the same basic code to a normal app works fine. Taking the same markup and putting it in a portlet ends up the the validation messages not being added to the FacesContext. I'm going to look next to see if it's just the "required" validation that's a problem or if other built-in validations have the same issue.
          Hide
          Hari Pulijala added a comment -

          I have used partialSubmit=true on the inputText. If it is just portlet specific, are there any work arounds that we can take to solve this issue?

          Show
          Hari Pulijala added a comment - I have used partialSubmit=true on the inputText. If it is just portlet specific, are there any work arounds that we can take to solve this issue?
          Hide
          Deryk Sinotte added a comment -

          No workarounds yet. I only know that the same code works in a non-portlet application but fails to do the validation properly when running in a portlet. We are still investigating.

          Show
          Deryk Sinotte added a comment - No workarounds yet. I only know that the same code works in a non-portlet application but fails to do the validation properly when running in a portlet. We are still investigating.
          Hide
          Neil Griffin added a comment -

          Just wanted to mention that this is also a problem when you use ice:form and partialSubmit=true can be reproduced using the following Example compat portlet at portletfaces.org:
          http://www.portletfaces.org/portletfaces-bridge/examples/icefaces-2.x-compat-portlet

          Show
          Neil Griffin added a comment - Just wanted to mention that this is also a problem when you use ice:form and partialSubmit=true can be reproduced using the following Example compat portlet at portletfaces.org: http://www.portletfaces.org/portletfaces-bridge/examples/icefaces-2.x-compat-portlet
          Hide
          Deryk Sinotte added a comment -

          My original discovery was that there was a failure in the PartialSubmitPhaseListener to find the component that triggered the partial submit. The purpose of the phase listener was to detect which component triggered the partial submit, and then set the "required" attribute of all of the other components to false during validation. When validation was complete, the "required" attribute was set back to it's previous value.

          The inability to find the component that triggered the partial submit meant that all the components in the form (including the one that triggered the partial submit) would have "required" set to false. Therefore no validation was being performed.

          I was able to verify that CoreComponentUtils.findComponent() could not locate the component in the view by changing the comparison from an object comparison to a String comparison of the ids. In other words, while iterating through the components of the form, instead of comparing like this:

          if (input == componentToAvoid) {

          I changed to do it like this:

          if (input.getId().equals((componentID)) {

          While this wasn't acceptable as a fix, it was able to show that validation would occur properly.

          I then tried switching from using CoreComponentUtils.findComponent() method (which is our own algorithm for find components) to the standard JSF method of UIViewRoot.findComponent(). This still didn't work for locating the component we were interested in.

          After discussing with other team members, I did a variety of different searches and what ended up working was removing the "namespace" from the front of the id. In portlets, in order to guarantee that components in different portlets are uniquely identified, the portal provides a portlet "namespace". This value is a container-specific value. In the current version of Liferay, our markup of:

          <ice:inputText id="requiredField" value="#

          {basic.requiredMessage}

          " required="#

          {true}

          " partialSubmit="true"/>

          would render out an id like this:

          A1364:mFormId:requiredField

          By stripping the A1364 from the front of id before performing the search, it was able to find the component.

          The value A1364 represents the portlet namespace. In the PortletFaces bridge, the namespacing is handled by the PortletNamingContainerUIViewRoot, which is basically the container or "body" of the portlet. However, that class is not overriding the getId()/setId() methods (which is a what we used to do with the ice:portlet tag back in ICEfaces 1.8). Because this component id is rendered out by not actually set in the PortletNamingContainerUIViewRoot itself, searches in the component tree fail.

          So the options are to either:

          1) remove the portlet namespace in our code before attempting the search or
          2) have the PortletFaces bridge use the namespace as the id as described above

          I believe 2 is the right way. So we will work with the bridge developer to make this change.

          I did some additional testing using an inputText with required=true and partialSubmit=true nested in a PanelSeries to ensure that the search for the component still worked and was able to verify that it does.

          Show
          Deryk Sinotte added a comment - My original discovery was that there was a failure in the PartialSubmitPhaseListener to find the component that triggered the partial submit. The purpose of the phase listener was to detect which component triggered the partial submit, and then set the "required" attribute of all of the other components to false during validation. When validation was complete, the "required" attribute was set back to it's previous value. The inability to find the component that triggered the partial submit meant that all the components in the form (including the one that triggered the partial submit) would have "required" set to false. Therefore no validation was being performed. I was able to verify that CoreComponentUtils.findComponent() could not locate the component in the view by changing the comparison from an object comparison to a String comparison of the ids. In other words, while iterating through the components of the form, instead of comparing like this: if (input == componentToAvoid) { I changed to do it like this: if (input.getId().equals((componentID)) { While this wasn't acceptable as a fix, it was able to show that validation would occur properly. I then tried switching from using CoreComponentUtils.findComponent() method (which is our own algorithm for find components) to the standard JSF method of UIViewRoot.findComponent(). This still didn't work for locating the component we were interested in. After discussing with other team members, I did a variety of different searches and what ended up working was removing the "namespace" from the front of the id. In portlets, in order to guarantee that components in different portlets are uniquely identified, the portal provides a portlet "namespace". This value is a container-specific value. In the current version of Liferay, our markup of: <ice:inputText id="requiredField" value="# {basic.requiredMessage} " required="# {true} " partialSubmit="true"/> would render out an id like this: A1364:mFormId:requiredField By stripping the A1364 from the front of id before performing the search, it was able to find the component. The value A1364 represents the portlet namespace. In the PortletFaces bridge, the namespacing is handled by the PortletNamingContainerUIViewRoot, which is basically the container or "body" of the portlet. However, that class is not overriding the getId()/setId() methods (which is a what we used to do with the ice:portlet tag back in ICEfaces 1.8). Because this component id is rendered out by not actually set in the PortletNamingContainerUIViewRoot itself, searches in the component tree fail. So the options are to either: 1) remove the portlet namespace in our code before attempting the search or 2) have the PortletFaces bridge use the namespace as the id as described above I believe 2 is the right way. So we will work with the bridge developer to make this change. I did some additional testing using an inputText with required=true and partialSubmit=true nested in a PanelSeries to ensure that the search for the component still worked and was able to verify that it does.
          Hide
          Deryk Sinotte added a comment -

          Resolving as Won't Fix. The PortletFaces bridge developer will be including the UIViewRoot logic where the namespace is also set as the id of the component. I will include a link to the relevant case when it becomes available.

          Show
          Deryk Sinotte added a comment - Resolving as Won't Fix. The PortletFaces bridge developer will be including the UIViewRoot logic where the namespace is also set as the id of the component. I will include a link to the relevant case when it becomes available.
          Hide
          Deryk Sinotte added a comment -

          Neil has applied a fix as per: http://jira.portletfaces.org/browse/BRIDGE-198

          I update and ran the test with the panel series again where I changed the phone outputText to:

          <ice:inputText id="phone" value="#

          {employee.phone}

          " required="true" partialSubmit="true"/>

          and it worked as expected.

          Show
          Deryk Sinotte added a comment - Neil has applied a fix as per: http://jira.portletfaces.org/browse/BRIDGE-198 I update and ran the test with the panel series again where I changed the phone outputText to: <ice:inputText id="phone" value="# {employee.phone} " required="true" partialSubmit="true"/> and it worked as expected.

            People

            • Assignee:
              Deryk Sinotte
              Reporter:
              Hari Pulijala
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: