You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Jose Luis Sanchez <jo...@m-centric.com> on 2010/02/17 18:16:14 UTC

Validating forms inside a loop

Hi all.

I have a multiple form problem .. and after having search and thought 
many on this, can't find a solution.


<table t:type="loop" t:source="receivedMessages" t:value="message" >
<tbody>
<tr style="horizontal-align: middle">
<td style="vertical-align: top; horizontal-align: middle width: 323px;">
<form t:type="form" t:id="edit" context="${message.id}" 
clientValidation="false">
</t:errors>
<input t:type="textfield"    t:id="phone" />
<input    value="Save"   t:id="save"   t:type="submit" />
<input    value="Reject" t:id="reject" t:type="submit" />
</form>
</td>
</tr>
</tbody>
</table>


Well, that's a sample of what i have.

I'll tell my usage :
   When the user clicks Reject, no clientValidation is done. That's why 
i disabled clientvalidation.
   When the user clicks Accept, serverside validation is done against 
real required fields, but as the form id
   is inside a loop, i can't get the validation to show the errors in 
it's own form.


     private Form edit;

     @OnEvent(value=EventConstants.VALIDATE_FORM)
     void validateForm() {
         edit.clearErrors();
         if (phone==null) edit.recordError("Sorry, phone is mandatory");
     }

     While this works, it shows errors on every form ( currently 3 form 
), so i see the famous red-banner thrice.




I can't add edit_0 nor edit_1, because while they are real names in 
rendered tml, they are not before, so tapestry gives me an error.

Is there any way i can fix this ?

Thanks.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Validating forms inside a loop

Posted by Steve Eynon <st...@googlemail.com>.
Hi,

I've put the above into a Mixin, which works fine, but the
implementation is a little "leaky" i.e. the containing component needs
to define it as an Implementation Mixin and set the tracker name /
context in the onPrepareForSubmit event.

I've been trying to change it so that the mixin can be applied to the
form itself and be all containing, such as,

<t:form t:mixins="multitrackerz" ...

Only I need to join, or pipe together the form's tracker parameter
with a parameter (or property) of the mixin, sort of like,

<t:form t:mixins="multitrackerz" t:tracker="multitrackerz.tracker" ...

only that's not possible. Is there another way to accomplish this?

I tried injecting the Form with @InjectContainer in the mixin, but I
can't set parameters there and there is no get / set Tracker on the
Form.

Anyone any ideas?

Steve.


On 18 February 2010 06:19, jose luis sanchez
<jo...@m-centric.com> wrote:
> Wow, you really saved my day !
> Thanks !
> El 17/02/2010, a las 23:09, Josh Canfield escribió:
>
>> The problem is that you really only have one instance of the Form
>> component, and so only one instance of the ValidationTracker. I poked
>> around and wasn't able to find an easier way to do this.
>>
>> Don't use ${} when passing the context.
>>        <t:form t:id="edit" clientValidation="false" context="message.id">
>>
>> I used the index of the loop for the context. You can modify to use
>> the message.id
>>
>>    @Component(parameters = {"tracker=tracker"})
>>    private Form _edit;
>>
>>    @Persist(PersistenceConstants.FLASH)
>>    private Map<Integer, ValidationTracker> _indexedTrackers;
>>
>>    /**
>>     * Holds the tracker created when the form is posted and we don't
>> know which form is being processed
>>     */
>>    private ValidationTracker _tmpTracker;
>>
>> @OnEvent(EventConstants.PREPARE_FOR_SUBMIT)
>>    void onPrepareForSubmitFromEdit(int index) {
>>        _formIndex = index;
>>    }
>>
>> @OnEvent(value = EventConstants.VALIDATE_FORM)
>>    void validateForm() {
>> // don't clear the errors here. Clear them after render, otherwise you
>> lose edited value tracking
>>        if (name == null) {
>>            _edit.recordError("Sorry, name is mandatory");
>>        }
>>    }
>>
>> public ValidationTracker getTracker() {
>>        if (_indexedTrackers == null) _indexedTrackers = new
>> HashMap<Integer, ValidationTracker>();
>>        if (_formIndex == null) {
>>            // it's a post and we haven't gotten to the part of the
>> action where the fields are processed
>>            if (_tmpTracker == null) _tmpTracker = new ValidationTrackerImpl();
>>            return _tmpTracker;
>>        }
>>        if (_tmpTracker != null) {
>>            // We have a temp tracker and a form index so we have now
>> processed the input fields
>>            // so we can store the temp in the map and clear it.
>>            _indexedTrackers.put(_formIndex, _tmpTracker);
>>            _tmpTracker = null;
>>        }
>>
>>        // Make sure we have a tracker for all the forms
>>        if (_indexedTrackers.get(_formIndex) == null)
>> _indexedTrackers.put(_formIndex, new ValidationTrackerImpl());
>>
>>        return _indexedTrackers.get(_formIndex);
>>    }
>>
>>    public void setTracker(ValidationTracker tracker) {
>>        if (_indexedTrackers == null) _indexedTrackers = new
>> HashMap<Integer, ValidationTracker>();
>>        if (_formIndex == null) {
>>            // We don't know which form this is for. This gets called
>> at the very end of the action
>>            // so you probably have a bug if this is getting called
>>            throw new RuntimeException("This shouldn't happen");
>>        }
>>        _indexedTrackers.put(_formIndex, tracker);
>> // Remember the trackers for the render.
>>        setIndexedTrackers(_indexedTrackers);
>>    }
>>
>>    public void setIndexedTrackers(Map<Integer, ValidationTracker>
>> indexedTrackers) {
>>        _indexedTrackers = indexedTrackers;
>>    }
>>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Validating forms inside a loop

Posted by jose luis sanchez <jo...@m-centric.com>.
Wow, you really saved my day !
Thanks !
El 17/02/2010, a las 23:09, Josh Canfield escribió:

> The problem is that you really only have one instance of the Form
> component, and so only one instance of the ValidationTracker. I poked
> around and wasn't able to find an easier way to do this.
> 
> Don't use ${} when passing the context.
>        <t:form t:id="edit" clientValidation="false" context="message.id">
> 
> I used the index of the loop for the context. You can modify to use
> the message.id
> 
>    @Component(parameters = {"tracker=tracker"})
>    private Form _edit;
> 
>    @Persist(PersistenceConstants.FLASH)
>    private Map<Integer, ValidationTracker> _indexedTrackers;
> 
>    /**
>     * Holds the tracker created when the form is posted and we don't
> know which form is being processed
>     */
>    private ValidationTracker _tmpTracker;
> 
> @OnEvent(EventConstants.PREPARE_FOR_SUBMIT)
>    void onPrepareForSubmitFromEdit(int index) {
>        _formIndex = index;
>    }
> 
> @OnEvent(value = EventConstants.VALIDATE_FORM)
>    void validateForm() {
> // don't clear the errors here. Clear them after render, otherwise you
> lose edited value tracking
>        if (name == null) {
>            _edit.recordError("Sorry, name is mandatory");
>        }
>    }
> 
> public ValidationTracker getTracker() {
>        if (_indexedTrackers == null) _indexedTrackers = new
> HashMap<Integer, ValidationTracker>();
>        if (_formIndex == null) {
>            // it's a post and we haven't gotten to the part of the
> action where the fields are processed
>            if (_tmpTracker == null) _tmpTracker = new ValidationTrackerImpl();
>            return _tmpTracker;
>        }
>        if (_tmpTracker != null) {
>            // We have a temp tracker and a form index so we have now
> processed the input fields
>            // so we can store the temp in the map and clear it.
>            _indexedTrackers.put(_formIndex, _tmpTracker);
>            _tmpTracker = null;
>        }
> 
>        // Make sure we have a tracker for all the forms
>        if (_indexedTrackers.get(_formIndex) == null)
> _indexedTrackers.put(_formIndex, new ValidationTrackerImpl());
> 
>        return _indexedTrackers.get(_formIndex);
>    }
> 
>    public void setTracker(ValidationTracker tracker) {
>        if (_indexedTrackers == null) _indexedTrackers = new
> HashMap<Integer, ValidationTracker>();
>        if (_formIndex == null) {
>            // We don't know which form this is for. This gets called
> at the very end of the action
>            // so you probably have a bug if this is getting called
>            throw new RuntimeException("This shouldn't happen");
>        }
>        _indexedTrackers.put(_formIndex, tracker);
> // Remember the trackers for the render.
>        setIndexedTrackers(_indexedTrackers);
>    }
> 
>    public void setIndexedTrackers(Map<Integer, ValidationTracker>
> indexedTrackers) {
>        _indexedTrackers = indexedTrackers;
>    }
> 
> 
> 
> On Wed, Feb 17, 2010 at 9:16 AM, Jose Luis Sanchez
> <jo...@m-centric.com> wrote:
>> Hi all.
>> 
>> I have a multiple form problem .. and after having search and thought many
>> on this, can't find a solution.
>> 
>> 
>> <table t:type="loop" t:source="receivedMessages" t:value="message" >
>> <tbody>
>> <tr style="horizontal-align: middle">
>> <td style="vertical-align: top; horizontal-align: middle width: 323px;">
>> <form t:type="form" t:id="edit" context="${message.id}"
>> clientValidation="false">
>> </t:errors>
>> <input t:type="textfield"    t:id="phone" />
>> <input    value="Save"   t:id="save"   t:type="submit" />
>> <input    value="Reject" t:id="reject" t:type="submit" />
>> </form>
>> </td>
>> </tr>
>> </tbody>
>> </table>
>> 
>> 
>> Well, that's a sample of what i have.
>> 
>> I'll tell my usage :
>>  When the user clicks Reject, no clientValidation is done. That's why i
>> disabled clientvalidation.
>>  When the user clicks Accept, serverside validation is done against real
>> required fields, but as the form id
>>  is inside a loop, i can't get the validation to show the errors in it's own
>> form.
>> 
>> 
>>    private Form edit;
>> 
>>    @OnEvent(value=EventConstants.VALIDATE_FORM)
>>    void validateForm() {
>>        edit.clearErrors();
>>        if (phone==null) edit.recordError("Sorry, phone is mandatory");
>>    }
>> 
>>    While this works, it shows errors on every form ( currently 3 form ), so
>> i see the famous red-banner thrice.
>> 
>> 
>> 
>> 
>> I can't add edit_0 nor edit_1, because while they are real names in rendered
>> tml, they are not before, so tapestry gives me an error.
>> 
>> Is there any way i can fix this ?
>> 
>> Thanks.
>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: users-help@tapestry.apache.org
>> 
>> 
> 
> 
> 
> -- 
> --
> http://www.bodylabgym.com - a private, by appointment only, one-on-one
> health and fitness facility.
> --
> http://www.ectransition.com - Quality Electronic Cigarettes at a
> reasonable price!
> --
> TheDailyTube.com. Sign up and get the best new videos on the internet
> delivered fresh to your inbox.
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Validating forms inside a loop

Posted by Josh Canfield <jo...@gmail.com>.
The problem is that you really only have one instance of the Form
component, and so only one instance of the ValidationTracker. I poked
around and wasn't able to find an easier way to do this.

Don't use ${} when passing the context.
        <t:form t:id="edit" clientValidation="false" context="message.id">

I used the index of the loop for the context. You can modify to use
the message.id

    @Component(parameters = {"tracker=tracker"})
    private Form _edit;

    @Persist(PersistenceConstants.FLASH)
    private Map<Integer, ValidationTracker> _indexedTrackers;

    /**
     * Holds the tracker created when the form is posted and we don't
know which form is being processed
     */
    private ValidationTracker _tmpTracker;

@OnEvent(EventConstants.PREPARE_FOR_SUBMIT)
    void onPrepareForSubmitFromEdit(int index) {
        _formIndex = index;
    }

@OnEvent(value = EventConstants.VALIDATE_FORM)
    void validateForm() {
// don't clear the errors here. Clear them after render, otherwise you
lose edited value tracking
        if (name == null) {
            _edit.recordError("Sorry, name is mandatory");
        }
    }

 public ValidationTracker getTracker() {
        if (_indexedTrackers == null) _indexedTrackers = new
HashMap<Integer, ValidationTracker>();
        if (_formIndex == null) {
            // it's a post and we haven't gotten to the part of the
action where the fields are processed
            if (_tmpTracker == null) _tmpTracker = new ValidationTrackerImpl();
            return _tmpTracker;
        }
        if (_tmpTracker != null) {
            // We have a temp tracker and a form index so we have now
processed the input fields
            // so we can store the temp in the map and clear it.
            _indexedTrackers.put(_formIndex, _tmpTracker);
            _tmpTracker = null;
        }

        // Make sure we have a tracker for all the forms
        if (_indexedTrackers.get(_formIndex) == null)
_indexedTrackers.put(_formIndex, new ValidationTrackerImpl());

        return _indexedTrackers.get(_formIndex);
    }

    public void setTracker(ValidationTracker tracker) {
        if (_indexedTrackers == null) _indexedTrackers = new
HashMap<Integer, ValidationTracker>();
        if (_formIndex == null) {
            // We don't know which form this is for. This gets called
at the very end of the action
            // so you probably have a bug if this is getting called
            throw new RuntimeException("This shouldn't happen");
        }
        _indexedTrackers.put(_formIndex, tracker);
// Remember the trackers for the render.
        setIndexedTrackers(_indexedTrackers);
    }

    public void setIndexedTrackers(Map<Integer, ValidationTracker>
indexedTrackers) {
        _indexedTrackers = indexedTrackers;
    }



On Wed, Feb 17, 2010 at 9:16 AM, Jose Luis Sanchez
<jo...@m-centric.com> wrote:
> Hi all.
>
> I have a multiple form problem .. and after having search and thought many
> on this, can't find a solution.
>
>
> <table t:type="loop" t:source="receivedMessages" t:value="message" >
> <tbody>
> <tr style="horizontal-align: middle">
> <td style="vertical-align: top; horizontal-align: middle width: 323px;">
> <form t:type="form" t:id="edit" context="${message.id}"
> clientValidation="false">
> </t:errors>
> <input t:type="textfield"    t:id="phone" />
> <input    value="Save"   t:id="save"   t:type="submit" />
> <input    value="Reject" t:id="reject" t:type="submit" />
> </form>
> </td>
> </tr>
> </tbody>
> </table>
>
>
> Well, that's a sample of what i have.
>
> I'll tell my usage :
>  When the user clicks Reject, no clientValidation is done. That's why i
> disabled clientvalidation.
>  When the user clicks Accept, serverside validation is done against real
> required fields, but as the form id
>  is inside a loop, i can't get the validation to show the errors in it's own
> form.
>
>
>    private Form edit;
>
>    @OnEvent(value=EventConstants.VALIDATE_FORM)
>    void validateForm() {
>        edit.clearErrors();
>        if (phone==null) edit.recordError("Sorry, phone is mandatory");
>    }
>
>    While this works, it shows errors on every form ( currently 3 form ), so
> i see the famous red-banner thrice.
>
>
>
>
> I can't add edit_0 nor edit_1, because while they are real names in rendered
> tml, they are not before, so tapestry gives me an error.
>
> Is there any way i can fix this ?
>
> Thanks.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>



-- 
--
http://www.bodylabgym.com - a private, by appointment only, one-on-one
health and fitness facility.
--
http://www.ectransition.com - Quality Electronic Cigarettes at a
reasonable price!
--
TheDailyTube.com. Sign up and get the best new videos on the internet
delivered fresh to your inbox.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org