If you look at UIInputs, they keep their submitted value during saveSate
and restoreState. As such, once a value has been submitted, the tab can
be unselected (and such decode does nothing for that component) they
keep their submitted value. The current patch in tracker, if you test
it, validates without problems the non currently selected tab if they
were shown in the past. If you have a required input inside tab 1 , goes
from tab1 to tab 2 and try to validate, it can also validate input in
tab 1 without trouble, and, in case of validation error, displays tab1
with it's error message.

So if we provide the web designer with ability to require submit of a
tab content, we have a clean way for the web designer to force
validation of specific tabs.

I agree with you, check must still be done in backing bean. But don't
forget *if you don't call the processValidators() on a UIInput*, you
also don't transmit the submitted value to the local value and *you end
not transmitting value to backing bean*. That's where the main problem
is. Datas entered in tab1, with current release of tomahawk, don't make
their way to the backing bean if tab1 is not currently active. This is
not a problem when tabbed pane is used for alternate ways to fill a
form, but *this is a real problem if you use tabbedpane to split a form
visually*.

>From UIInput:


    public Object saveState(FacesContext context)
    {
        Object values[] = new Object[9];
        values[0] = super.saveState(context);
        values[1] = _immediate;
        values[2] = Boolean.valueOf(_localValueSet);
        values[3] = _required;
        values[4] = _submittedValue;
        values[5] = Boolean.valueOf(_valid);
        values[6] = saveAttachedState(context, _validator);
        values[7] = saveAttachedState(context, _valueChangeListener);
        values[8] = saveAttachedState(context, _validatorList);
        return values;
    }

En l'instant précis du 13/06/07 17:54, Andrew Robinson s'exprimait en
ces termes:
> What is the purpose of calling the validators on the components in the
> non-selected tab? I don't see why this is necessary, as there will
> never be submitted values from the components inside those tabs, and
> thus always valid, and thus calling the validators just wastes CPU
> time.
>
> Remember, the required attribute simply means that the user must give
> a value (it must not be empty), but that does not mean that the
> browser has to send a value. So required only throws a validation
> error ONLY if the user submitted an empty string. If you want to make
> sure a required value is set, the backing bean developer MUST check it
> and not depend on the view.
>
> On 6/13/07, David Delbecq <[EMAIL PROTECTED]> wrote:
>> Hello,
>>
>> thanks for pointing me this expected behaviour of UIInput.
>>
>> To resume situation,
>> (1) tabbed pane should call the processValidators of each of his child
>> according to specs (which it does not right now)
>> (2) tabbed pane should, however, keep backward compatibility with old
>> behaviour to not break existing apps (obviously)
>> (3) UIInputs inside tabs should only process their validation if they
>> have a submitted value (JSF specs)
>> (4) submitted value should in now way be set other way than from the
>> normal JSF processDecode() of the component (JSF specs)
>> (5) there should be a way to force a tab or all tab, including never
>> showed ones, to validate (possibility of complete form review for user).
>>
>> The current proposed patch does call processValidators() on all children
>> tabs (point 1) except for tabs (default) where the processValidators
>> property is set to false (point 2). Because not yet submitted tab
>> contents don't have submitted value, they take responsability to not
>> process validation according to UIInput specifications (meeting point
>> 3). So far so good. To allow web developper to force a user to enter
>> datas inside a specific tab (and achieve yet not achieved point 5), we
>> can certainly not force full JSF tree or setting submittted value
>> (point 4)
>>
>>
>> I propose this amendment to my submitted patch, i am sure you will admit
>> it is going to respect jsf specs and do things cleanly:
>>
>> Have tabs able to handle the "required" attribute (default false for
>> point 2), they could then ensure their content was at least submitted
>> once (tab was visited). This can easily be done by having tab renderer
>> output a hidden html field and, upon decode() of tab, if we see the
>> hidden field, we mark this tab as submitted once. We can safelty assume
>> the content of tab (UIInputs) now have submitted values where
>> appropriate because it comes from a normal JSF submit operation. If tabs
>> allows also validator childs, web designer could do even more complex
>> validation task (like, "if check box xyz is checked in tab1, then tab5
>> must be filled)
>>
>> For example, this would lead to this kind of code:
>>
>> for a new originally emtpy user data to fill, web designer could do this
>> way:
>>     <t:panelTabbedPane serverSideTabSwitch="true" id="pane">
>>         <t:panelTab label="personal" processValidators="true"
>> required="true">
>>             firstname:<h:inputText id="firstname"
>> value="#{newUser.first}" required="true"/>
>>             lastname:<h:inputText id="lastname" value="#{newUser.last}"
>> required="true"/>
>>         </t:panelTab>
>>         <t:panelTab label="contact" processValidators="true"
>> required="true">
>>             <h:inputText id="email" value="#{newUser.email}"
>> required="true"><f:validator validatorId="validemail" /></h:inputText>
>>         </t:panelTab>
>>         <t:panelTab label="optional datas" processValidators="true">
>>             ....
>>         </t:panelTab>
>>     </t:panelTabbedPane>
>>
>> Optional datas content will only be validated if it was submitted once
>> (not required), but user will have to submit the first two tabs to
>> success. If he never submited the second tab, for example, upon
>> validation he would receive a message like this: 'the tab named
>> <contact> must be filled' and contact tab would be selected.
>>
>> Now, during edition of existing, the web designer may assume that
>> existing datas are correct and there is no need to force user to visit
>> all tabs each time he want to change a typo in his firstname. The
>> edition could be this:
>>    <t:panelTabbedPane serverSideTabSwitch="true" id="pane">
>>         <t:panelTab label="personal" processValidators="true">
>>             firstname:<h:inputText id="firstname" value="#{user.first}"
>> required="true"/>
>>             lastname:<h:inputText id="lastname" value="#{user.last}"
>> required="true"/>
>>         </t:panelTab>
>>         <t:panelTab label="contact" processValidators="true">
>>             <h:inputText id="email" value="#{user.email}"
>> required="true"><f:validator validatorId="validemail" /></h:inputText>
>>         </t:panelTab>
>>         <t:panelTab label="optional datas" processValidators="true">
>>             ....
>>         </t:panelTab>
>>     </t:panelTabbedPane>
>>
>> And classical 'validate current only' tabs could be done the classical
>> way, without setting a processValidator or required attribute, or
>> setting it to false.
>>
>> Note: i also suggest to rename the processValidators property to
>> something shorter and less confusing in code. "checkValid" for example.
>>
>> Am sure we get in the correct direction with this.
>> Regards,
>> David Delbecq
>>
>> En l'instant précis du 12/06/07 22:22, Andrew Robinson s'exprimait en
>> ces termes:
>> > Thanks for the correction David, I should have checked the
>> > specification myself, sorry for the rabbit trail. The reason as
>> > mentioned before that validation does not take place for non-rendered
>> > components is not that it isn't called on those components, but rather
>> > there is no submitted value for components that have not been
>> > rendered.
>> >
>> > As mentioned before, calling the validators on the hidden tabs will
>> > not usually change the behavior as UIInput components that do not have
>> > a submitted value are considered valid automatically
>> > (http://tinyurl.com/2z2mjj) since the validate function falls out if
>> > there is no submitted value.
>> >
>> > On 6/12/07, David Delbecq <[EMAIL PROTECTED]> wrote:
>> >>
>> >>  Maybe am badly reading the specifications?:
>> >>
>> >>
>> >> 2.2.3 Process Validations
>> >>
>> >>  ....
>> >>  During the Process Validations phase of the request processing
>> >> lifecycle,
>> >> the JSF
>> >>  implementation must call the processValidators() method of the
>> >> UIViewRoot
>> >>  of the tree. This will normally cause the processValidators()
>> method of
>> >> each
>> >>  component in the tree to be called recursively, as described in
>> the API
>> >> reference for
>> >>  the UIComponent.processValidators() method. Note that
>> >>  EditableValueHolder components whose immediate property is set to
>> true
>> >>  will have had their conversion and validation processing performed
>> >> during
>> >> Apply
>> >>  Request Values phase.
>> >>  ....
>> >>
>> >>  From this point, we get to the way the tabbed pane must implement
>> >> processValidators() to conform specifications, reading the api
>> docs  of
>> >> UIComponent as the specs tells us to do:
>> >>
>> >>
>> >> public abstract void
>> >> processValidators(javax.faces.context.FacesContext context)
>> >>
>> >>  Perform the component tree processing required by the Process
>> >> Validations
>> >> phase of the request processing lifecycle for all facets of this
>> >> component,
>> >> all children of this component, and this component itself, as
>> follows.
>> >>  - If the rendered property of this UIComponent is false, skip
>> further
>> >> processing.
>> >>  - Call the processValidators() method of all facets and children of
>> >> this
>> >> UIComponent, in the order determined by a call to
>> >> getFacetsAndChildren().
>> >>
>> >>  This clearly mention the "rendered property". Tabbed Pane must
>> not skip
>> >> further processing and must call processValidators() for all it's
>> >> facets and
>> >> children! Those children are mainly made of tab components. All those
>> >> tabs
>> >> have rendered property set to true, so they themself also must calls
>> >> processValidators() on their children and facets. Now if the tabs
>> >> would have
>> >> their rendered property to false, they would skip validation of
>> >> themselves
>> >> and their content, but this is not the case.
>> >>
>> >>  As for the getRendersChildren() you mentioned, it's unrelated. It
>> >> appear
>> >> twice in specs, "8.2 Renderer" and "9.2.8 Interoperability with JSP
>> >> Template
>> >> Text and Other Tag Libraries". Nothing suggest it has to do with
>> >> processValidators() behaviour. I think you are mixing the validation
>> >> and the
>> >> rendering phase.
>> >>
>> >>
>> >>  Maybe i missed some parts of specs, i don't know them by heart and
>> >> am far
>> >> from having the inside knowledge of myfaces developpers. But am still
>> >> not
>> >> convinced there is a good reason to not validate the not currently
>> >> active
>> >> tabs. Of course backward compatibility must be preserved.
>> >>
>> >>  Kind regards,
>> >>  David Delbecq
>> >>
>> >>  Andrew Robinson a écrit :
>> >> Whether a component is rendered or not is NOT based on the result of
>> >>  UIComponent.isRendered(), it is based on if UIComponent.isRendered()
>> >>  is true AND the renderer chooses to render it AND all parents of
>> that
>> >>  component are rendered. The second part of that rule is just as
>> >>  important as the first. The litmus test, is: a component is rendered
>> >>  if the renderer outputs content for this component to the response
>> >>  writer.
>> >>
>> >>  By this definition, the components in the non-selected tab are not
>> >>  rendered (it doesn't matter what the isRendered() flag is) and
>> >>  therefore should not be decoded, validated or updated.
>> >>
>> >>  This is the reason why the getRendersChildren() method exists, so
>> that
>> >>  renderers may choose to overwrite how the children are rendered.
>> >>
>> >>  In fact, there is nothing in the JSF specification that I am
>> aware of
>> >>  the *requires* a renderer to pay any attention to the
>> >>  UIComponent.isRendered() flag, especially for children components.
>> >>  isRendered() is more of a design pattern than a requirement (note
>> that
>> >>  UIComponentBase will only call the renderer's encode method, if
>> >>  isRendered is true, but that doesn't mean that component will be
>> >>  rendered by the renderer, it only means that the encodeBegin,
>> >>  encodeChildren, and encodeEnd will be called on the renderer).
>> >>
>> >>  On 6/12/07, David Delbecq <[EMAIL PROTECTED]> wrote:
>> >>
>> >> I agree with you, component values should be set by their renderer
>> and
>> >>  the component having isRendered() to false (along with their childs)
>> >>  should not be part of validation process.
>> >>
>> >>  Concerning the tabbedpane, it's just a laying-out component, showing
>> >> one
>> >>  part of the form at a time. But, at all moments, the tabs have
>> >>  isRendered() set to true. And they are rendered! The active one with
>> >>  full visible content, the inactive one resume as a button header. As
>> >>  they have isRendered() to true, they should, according to JSF specs,
>> >>  validate themselves and call the validation process on their
>> immediate
>> >>  children.
>> >>
>> >>  The whole question is there. Should an inactive tab have
>> isRendered()
>> >>  return false or true? It currently returns true.
>> >>
>> >>  Now the fact component without submitted value do not validate
>> may be a
>> >>  problem, depending on the details of JSF specs.
>> >>  Andrew Robinson a écrit :
>> >>  > Manually setting the submitted value on components that do not
>> have a
>> >>  > submitted value really goes against JSF standards.
>> >>  >
>> >>  > The fact that UIInput.java doesn't throw a validation error if
>> >>  > isRequired is true and getSubmittedValue() is null I think is a
>> >>  > shortcoming/bug in the JSF specification (or at least in MyFaces's
>> >>  > implementation), but I strongly feel against forcing the
>> setting of
>> >>  > submitted values on components, as that is the job of the
>> renderer of
>> >>  > that component (or the component itself), not parents of that
>> >>  > component.
>> >>  >
>> >>  > As for not validating renderer components, as I mentioned earlier,
>> >>  > that is the "way it is supposed to be". Components not rendered by
>> >> the
>> >>  > renderer, should not be validated. JSF validation should not
>> replace
>> >>  > backing bean validation, it should simple enhance it (that also
>> >> covers
>> >>  > the use case of hacking around validation by removing submitted
>> >> values
>> >>  > or removing elements on the client).
>> >>  >
>> >>  > On 6/12/07, David Delbecq <[EMAIL PROTECTED]> wrote:
>> >>  >> Hello everyone
>> >>  >>
>> >>  >> I did a bit of investigations on how to force validation of all
>> >> tabs,
>> >>  >> including those never yet rendered. It seems blocked by a
>> >> characteristic
>> >>  >> of validation: Validation will be completly bypassed on most
>> >> components
>> >>  >> if there has never been a _submittedValue for that component.
>> >> This is
>> >>  >> important because that mean the user behind his web browser
>> has the
>> >>  >> possibity to completly bypass validation of required fields.
>> If you
>> >>  >> require a valid client number for a message contact form, for
>> >> example,
>> >>  >> user can simply remove this field from DOM tree to ignore this
>> >> (Note:
>> >>  >> this is different to not filling entry).
>> >>  >>
>> >>  >> Note: i could bypass  without troubles validation there:
>> >>  >>
>> >> http://example.irian.at/example-simple-20070612/sample1.jsf
>> >>  >> using this simple javascript command in url bar:
>> >>  >>
>> >>
>> javascript:document.getElementById('form1').removeChild(document.getElementById('form1:number1'))
>>
>> >>
>> >>  >>
>> >>  >>
>> >>  >> Is it expected feature of validation or a bug in myface?
>> >>  >>
>> >>  >> If it's expected behaviour, then to ensure all tabs get
>> validated we
>> >>  >> could
>> >>  >> during decode of panel, scan tree below each non active tab,
>> >> (stopping
>> >>  >> at !isRendered() components to respect specs)
>> >>  >> for each EditableValueHolder which does not have yet a submitted
>> >> value,
>> >>  >> set the submited value to the converted value of model (this
>> is like
>> >>  >> doing a encode/decode but all server side).
>> >>  >>
>> >>  >> [EMAIL PROTECTED] wrote:
>> >>  >> Hi,
>> >>  >>  submitted patch wouldn't break old apps (it has default of NOT
>> >>  >> validating not-selected tabs).
>> >>  >>
>> >>  >> But it has limitation:
>> >>  >> it can validate only so far visited/rendered tabs (and only
>> >>  >> visited/rendered subcomponents)
>> >>  >>
>> >>  >> Limitation comes from the way TabbedPane is rendered:
>> >>  >> it renders only active tab in server-side tabbing (lines
>> 552-555 in
>> >>  >> HtmlTabbedPaneRenderer).
>> >>  >> This seems to be chosen for being less evil than messing with
>> >> rendered
>> >>  >> attribute in all tabs after change of selected tab [should be
>> >> consulted
>> >>  >> with original commiter].
>> >>  >>
>> >>  >> Is there any method in MyFaces allowing to create component
>> tree w/o
>> >>  >> actually rendering it?
>> >>  >> This would allow this kind of validation. (I fear that would
>> >> require to
>> >>  >> alter way rendering is functioning - decoupling rendering into
>> >> creating
>> >>  >> tree and actual rendering).
>> >>  >>
>> >>  >> With regards,
>> >>  >> Zdenek
>> >>  >>
>> >>
>> >>
>> >>
>>
>>

Reply via email to