jsr344-experts@javaserverfaces-spec-public.java.net

[jsr344-experts] Spec Issue 1060 Updated Proposal

From: Çağatay Çivici <cagatay.civici_at_gmail.com>
Date: Tue, 13 Nov 2012 16:09:07 +0200

Dear Volunteers,

Please review the updated proposal for spec issue 1060 - Clear Input Values. Proposal is also attached as a text file.

SECTION: Introduction

ACTION: Please read this for background

EditableValueHolders that subclass UIInput save their input as the local
value during the process validations phase (this is saved as part of the
view state). The local value is later to be used to update the model
during the update model phase, and then it is cleared. However, when
validation fails, the component's local value is not cleared. In many
cases, this is exactly correct because we want to allow the user to
correct their mistake, and having the invalid value there as a reference
is helpful. Sometimes, this is not the desired behavior, though. The
page author cannot reset the value of the component by updating the
model values since the component uses the local value instead of
resolving the model values.

Sample scenario is as follows:

<h:form>
    <h:messages />

    <h:inputText id="firstname" value="#{bean.firstname}" required="true"/>
    <h:inputText id="surname" value="#{bean.surname}" required="true"/>

    <h:commandButton value="Ajax Save">
            <f:ajax render="@form" execute="@form"/>
    </h:commandButton>
    <h:commandButton value="Non-Ajax Save" />

    <h:commandButton value="Ajax Reset" actionListener="#{bean.reset}">
            <f:ajax render="@form" execute="@this"/>
    </h:commandButton>
    <h:commandButton value="Non-Ajax Reset" actionListener="#{bean.reset}" immediate="true"/>

</h:form>

@ManagedBean
public class Bean {
    private String firstname, surname;

    //getter-setter

public void reset() {
   firstname = null;
   surname = null;
}
}

Steps to reproduce:

- Click the ajax save or non-ajax save without filling input fields to
get a validation error

- Click reset or non-ajax buttons, although reset method is executed on
bean, input components still show old value as they retrieve it from the
state.


SECTION: Known Solutions

ACTION: Please add if you are aware of any other solution

PrimeFaces

    Provides a resetInput tag and a programmatic way, uses a tree visitor.

    http://www.primefaces.org/showcase-labs/ui/resetInput.jsf

PrimeFaces Extensions

    A resetInput tag and uses a preRenderView event to reset.

    http://fractalsoft.net/primeext-showcase-mojarra/views/resetInput.jsf

MyFaces Trinidad

    An action listener.

    http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_resetActionListener.html

Omnifaces

    An action listener/phase listener for ajax cases.

    http://showcase-omnifaces.rhcloud.com/showcase/eventlisteners/ResetInputAjaxActionListener.xhtml


SECTION: Proposed Solution

ACTION: Please read this section and comment for feedback.

resetInput attribute in f:ajax

    This part fixes the case for ajax requests. Most of the time,
    page author would like to reset what is being updated just like
    in Ajax Reset button in the sample code. If f:ajax resets the
    components to update by going through
    PartialViewContext.getRenderIds() component values will be reset
    and model values will be used to display. Sample;

    <h:commandButton value="Ajax Reset">
            <f:ajax render="@form" execute="@this" resetInput="true|false"/>
    </h:commandButton>

    For backward compatibility, default value of the resetInput
    attribute should be false. I know we don't want to add another
    context-param but consider javax.faces.RESET_INPUT (false by
    default) to globally override the resetInput attribute
    setting. Still page authors can override the global setting per
    component.

    Even though this functionality is integrated with f:ajax, the
    approach for resetting EditableValueHolders might be similar to
    to the PrimeFaces Extension solution.

                Modifications Required

                - Modify f:ajax to describe resetInput attribute

                - Modify jsf.js request to describe resetInput option
                and what it is called like
                javax.faces.partial.resetInput

                - Modify partialViewContext to have a isResetInput()
                which describes how to get the value from the incoming
                request

                - Modify spec section render response partial processing
                2.2.6.1 to describe how to ask
                partialviewcontext.isResetInput() and if so to get the
                value of renderIds and call UIViewRoot.resetInput
                passing that value.

ResetInput Tag

    This tag goes in core namespace named <f:resetInput /> to cover
    non-ajax requests. This is the solution used in PrimeFaces and
    MyFaces Trinidad.

    <h:commandButton value="Non-Ajax Reset" immediate="true">
        <f:resetInput render="firstname surname or an ancestor" />
    </h:commandButton>

    Modifications Required

    - Define a new tagHandler called f:resetInput with a render
    attribute that is the same as in ajax case.

    - And then a "for" attribute for the purpose of composite
    components. (Similar to all of the other attached object
    handlers)

    - This tag handler causes an action listener to get attached to
    the component and this particular action listener calls
    UIViewRoot.reset with the values retrieved from the render
    attribute.

Programmatic API

Programmatic API is provided for flexibility in case page authors
would like to decide when to reset. It is different than f:ajax
since it brings flexibility for conditional reset calls. This API is
used by the ResetInput Tag described in previous section.

UIViewRoot.resetValues(String clientIds as varargs)

The implementation uses a TreeVisitor with a ResetInputVisitCallback
and this callback checks if the component is a en
EditableValueHolder and if so calls resetValue().

Regards,

Cagatay Civici
PrimeFaces Lead
JSF EG Member
Prime Teknoloji
www.prime.com.tr



SECTION: Introduction

ACTION: Please read this for background

EditableValueHolders that subclass UIInput save their input as the local
value during the process validations phase (this is saved as part of the
view state). The local value is later to be used to update the model
during the update model phase, and then it is cleared. However, when
validation fails, the component's local value is not cleared. In many
cases, this is exactly correct because we want to allow the user to
correct their mistake, and having the invalid value there as a reference
is helpful. Sometimes, this is not the desired behavior, though. The
page author cannot reset the value of the component by updating the
model values since the component uses the local value instead of
resolving the model values.

Sample scenario is as follows:

<h:form>
       <h:messages />

       <h:inputText id="firstname" value="#{bean.firstname}" required="true"/>
       <h:inputText id="surname" value="#{bean.surname}" required="true"/>

       <h:commandButton value="Ajax Save">
               <f:ajax render="@form" execute="@form"/>
       </h:commandButton>
       <h:commandButton value="Non-Ajax Save" />

       <h:commandButton value="Ajax Reset" actionListener="#{bean.reset}">
               <f:ajax render="@form" execute="@this"/>
       </h:commandButton>
       <h:commandButton value="Non-Ajax Reset" actionListener="#{bean.reset}" immediate="true"/>

</h:form>

@ManagedBean
public class Bean {
       private String firstname, surname;

       //getter-setter

   public void reset() {
      firstname = null;
      surname = null;
   }
}

Steps to reproduce:

- Click the ajax save or non-ajax save without filling input fields to
get a validation error

- Click reset or non-ajax buttons, although reset method is executed on
bean, input components still show old value as they retrieve it from the
state.


SECTION: Known Solutions

ACTION: Please add if you are aware of any other solution

PrimeFaces

       Provides a resetInput tag and a programmatic way, uses a tree visitor.

       http://www.primefaces.org/showcase-labs/ui/resetInput.jsf

PrimeFaces Extensions

       A resetInput tag and uses a preRenderView event to reset.

       http://fractalsoft.net/primeext-showcase-mojarra/views/resetInput.jsf

MyFaces Trinidad

       An action listener.

       http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_resetActionListener.html

Omnifaces

       An action listener/phase listener for ajax cases.

       http://showcase-omnifaces.rhcloud.com/showcase/eventlisteners/ResetInputAjaxActionListener.xhtml


SECTION: Proposed Solution

ACTION: Please read this section and comment for feedback.

resetInput attribute in f:ajax

       This part fixes the case for ajax requests. Most of the time,
       page author would like to reset what is being updated just like
       in Ajax Reset button in the sample code. If f:ajax resets the
       components to update by going through
       PartialViewContext.getRenderIds() component values will be reset
       and model values will be used to display. Sample;

       <h:commandButton value="Ajax Reset">
               <f:ajax render="@form" execute="@this" resetInput="true|false"/>
       </h:commandButton>

       For backward compatibility, default value of the resetInput
       attribute should be false. I know we don't want to add another
       context-param but consider javax.faces.RESET_INPUT (false by
       default) to globally override the resetInput attribute
       setting. Still page authors can override the global setting per
       component.

       Even though this functionality is integrated with f:ajax, the
       approach for resetting EditableValueHolders might be similar to
       to the PrimeFaces Extension solution.

                Modifications Required

                - Modify f:ajax to describe resetInput attribute

                - Modify jsf.js request to describe resetInput option
                and what it is called like
                javax.faces.partial.resetInput

                - Modify partialViewContext to have a isResetInput()
                which describes how to get the value from the incoming
                request

                - Modify spec section render response partial processing
                2.2.6.1 to describe how to ask
                partialviewcontext.isResetInput() and if so to get the
                value of renderIds and call UIViewRoot.resetInput
                passing that value.

ResetInput Tag

       This tag goes in core namespace named <f:resetInput /> to cover
       non-ajax requests. This is the solution used in PrimeFaces and
       MyFaces Trinidad.

       <h:commandButton value="Non-Ajax Reset" immediate="true">
           <f:resetInput render="firstname surname or an ancestor" />
       </h:commandButton>

       Modifications Required

       - Define a new tagHandler called f:resetInput with a render
       attribute that is the same as in ajax case.

       - And then a "for" attribute for the purpose of composite
       components. (Similar to all of the other attached object
       handlers)

       - This tag handler causes an action listener to get attached to
       the component and this particular action listener calls
       UIViewRoot.reset with the values retrieved from the render
       attribute.

Programmatic API

   Programmatic API is provided for flexibility in case page authors
   would like to decide when to reset. It is different than f:ajax
   since it brings flexibility for conditional reset calls. This API is
   used by the ResetInput Tag described in previous section.

   UIViewRoot.resetValues(String clientIds as varargs)

   The implementation uses a TreeVisitor with a ResetInputVisitCallback
   and this callback checks if the component is a en
   EditableValueHolder and if so calls resetValue().