Quantcast

T5 Select Menu with Other Option

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

T5 Select Menu with Other Option

George Christman
Hello, I'm trying to add an "other" option to my select menu and have the other option trigger a zone reload when selected. You can find a UI example here " http://drupal.org/node/330740 ". I'm currently using T5.2.5 with hibernate. My user interface uses two AjaxFormLoops, one nested inside the other and finally the select menu within the nested AjaxFormLoop.

<t:AjaxFormLoop t:id="lineItem" source="purchaseRequest.lineItems" value="lineItem" encoder="encoderLineItem">
<t:AjaxFormLoop t:id="lineItemFunding" context="lineItem.tempId" source="lineItem.lineItemFundings" value="lineItemFunding" encoder="encoderLineItemFunding">
<t:Select t:id="newFunding" value="lineItemFunding.funding" model="fundingModel" zone="fundingZone" blankOption="always" blankLabel="Funding Source"/>
</t:AjaxFormLoop>
</t:AjaxFormLoop>

I want to manually add the "other" option to the select menu and not save it to the database.  I'm doing this with the following code within the onPrepare method.

    @Persist
    @Property
    private List<Funding> _fundings;

    @Property
    @Persist
    private PurchaseRequest purchaseRequest;

void onPrepareFromPR() {

purchaseRequest = new PurchaseRequest();

        _fundings = session.createCriteria(Funding.class).add(Restrictions.eq("purchaseRequest.id", purchaseRequest.getId())).list();

        funding = new Funding();
        funding.setName("other");
        funding.setId(-1);
        _fundings.add(funding);

        fundingModel = selectModelFactory.create(_fundings, "label");
}

and lastly, I'm using the onValueChanged method to hand the AJAX request

    public Object onValueChanged(Funding funding) {
        if(funding != null && funding.getName().equals("other")) {
            return fundingZone.getBody();
        }
        return null;
    }

I get the following error [ERROR]entities.Funding Unable to convert client value '-1' into an entity instance.

I would like to add I'm building a purchaseRequest object with a one to many Funding Object as well as a one to many lineItem object. Both the Funding Object and the LineItem object have a one to many with a LineItemFunding Object. When I use the ValueEncoder with a UUID and the Funding object, the onValueChanged method returns the funding label, however the object doesn't get commited with the purchaseRequest.lineItem.lineItemFunding.

See both examples below of the two ValueEncoders.

Attempt 1

@SuppressWarnings("unchecked")
    public ValueEncoder getSelectEncoder() {
        return new ValueEncoder<Funding>() {
            public String toClient(Funding value) {
                Long key = value.getTempId();
                return key.toString();
            }

            public Funding toValue(String keyAsString) {
                Long key = new Long(keyAsString);
                for (Funding holder : purchaseRequest.getFundings()) {

                    if (holder.getTempId() == key) {
                        return holder;
                    }
                }
                return null;
            }
        };
    }

Attempt 2

    @Persist
    @Property
    private List<Funding> _fundings;

@SuppressWarnings("unchecked")
    public ValueEncoder getSelectEncoder() {
        return new ValueEncoder<Funding>() {
            public String toClient(Funding value) {
                Long key = value.getTempId();
                return key.toString();
            }

            public Funding toValue(String keyAsString) {
                Long key = new Long(keyAsString);
                for (Funding holder : _fundings) {

                    if (holder.getTempId() == key) {
                        return holder;
                    }
                }
                return null;
            }
        };
    }


I almost feel the Select component should have an other parameter option with the ability to provide it with any custom text that can be picked up by the onValueChanged in order to easily return a zone and further enrich our interfaces.

Any help with this issue would be greatly appreciated.

Cheers,
George
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

Thiago H de Paula Figueiredo
Hi!


On Fri, 24 Jun 2011 09:44:42 -0300, gchristman <[hidden email]>  
wrote:

> Hello, I'm trying to add an "other" option to my select menu and have the
> other option trigger a zone reload when selected.

> I get the following error [ERROR]entities.Funding Unable to convert  
> client value '-1' into an entity instance.

This is probably done by the ValueEncoder tapestry-hibernate automatically  
uses.

> I almost feel the Select component should have an other parameter option
> with the ability to provide it with any custom text that can be picked  
> up by the onValueChanged in order to easily return a zone and further  
> enrich our interfaces.

Take a look at the blankOption and blankLabel parameters of the Select  
component.

--
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, Ars Machina Tecnologia da Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

George Christman
Hi Thiago,

You are correct with it being done by the ValueEncoder tapestry-hibernate automatically which is why I'm receiving that error. Not entirely sure how to get around it.

I'm using the blankOption="always", blankLabel="Funding Source" parameters already. I guess I'm not clear with what your suggesting. When the other option is present and selected, I need to return a zone in order to create a new entry, but not be able to commit the other option to the db. Blanklabel still needs to be present with the other option.

Any other thoughts?

Cheers,
George
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

Thiago H de Paula Figueiredo
On Fri, 24 Jun 2011 10:23:53 -0300, George Christman  
<[hidden email]> wrote:

> Hi Thiago,

Hi!

> You are correct with it being done by the ValueEncoder tapestry-hibernate
> automatically which is why I'm receiving that error. Not entirely sure  
> how to get around it.

I'd get the Funding ValueEncoder from ValueEncoder source, create a  
wrapper a wrapper around it that checks for -1 id's and returning a  
special Funding object.

--
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, Ars Machina Tecnologia da Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

George Christman
Would you mind elaborating a bit on getting the Funding ValueEncoder from ValueEncoder source, or point me to an example? I'm not very familiar with the ValueEncoder and not finding much doc on your method.  

Thanks Thiago.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

Thiago H de Paula Figueiredo
On Fri, 24 Jun 2011 10:57:43 -0300, George Christman  
<[hidden email]> wrote:

> Would you mind elaborating a bit on getting the Funding ValueEncoder from
> ValueEncoder source, or point me to an example? I'm not very familiar  
> with the ValueEncoder and not finding much doc on your method.

Something like this (not tested):

<select t:type="Select" ... t:encoder="fundingEncoder"/>

final private static Funding OTHER = new Funding();
final private static String OTHER_ID = "-1";

@Inject
private ValueEncoderSource valueEncoderSource;

public ValueEncoder<Funding> getFundingEncoder() {
        final ValueEndcoder<Funding> encoder =  
valueEncoderSource.getValueEncoder(Funding.class);
        return new FundingValueEncoder(encoder);
}

final private static FundingValueEncoder implements ValueEncoder<Funding> {
        final private ValueEncoder<Funding> delegate;
        public FundingValueEncoder(ValueEncoder<Funding> delegate) {
                this.delegate = delegate;
        }
        public String toClient(Funding value) {
                if (value == OTHER) {
                        return OTHER_ID;
                }
                else {
                        return delegate.toClient(value);
                }
        }
        public Funding toValue(String clientValue) {
                if (OTHER_ID.equals(clientValue) {
                        return OTHER;
                }
                else {
                        return delegate.toValue(clientValue);
                }
        }
}

--
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, Ars Machina Tecnologia da Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

George Christman
In reply to this post by George Christman
Other than a few typos, code compiled and worked, however doesn't seem to be solving the issue. I'll show you exactly what I'm doing, maybe I'm missing something small. The value never seems to equal OTHER in your method. I really appreciate everything thus far. Thanks !

tml

<t:AjaxFormLoop t:id="lineItem" source="purchaseRequest.lineItems" value="lineItem" encoder="encoderLineItem">
<t:TextField value="lineItem.name"/>

<t:AjaxFormLoop t:id="lineItemFunding" context="lineItem.tempId" source="lineItem.lineItemFundings" value="lineItemFunding" encoder="encoderLineItemFunding">
    <t:Select t:id="newFunding" value="lineItemFunding.funding" model="fundingModel" zone="fundingZone" encoder="selectEncoder" blankOption="always" blankLabel="Funding Source"/>
</t:AjaxFormLoop>

</t:AjaxFormLoop>

class

    @PageActivationContext
    private PurchaseRequest _purchaseRequest;

    @Property
    @Persist
    private PurchaseRequest purchaseRequest;

    @Property
    private LineItemFunding lineItemFunding;

    @Property
    private Funding funding;

    @Property
    @Persist
    private SelectModel fundingModel;

    @Inject
    private SelectModelFactory selectModelFactory;    

    @Inject
    private ValueEncoderSource valueEncoderSource;

    final private static String NEW_FUNDING_NAME = "+ Add New Funding";
    final private static Funding OTHER = new Funding();
    final private static String OTHER_ID = "-1";

    void setupRender() {
        if(_purchaseRequest == null) {
            purchaseRequest = new PurchaseRequest();
        } else {
            purchaseRequest = _purchaseRequest;
        }
       
    }

    void onPrepareFromPR() {

        List<Funding> _fundings = session.createCriteria(Funding.class).add(Restrictions.eq("purchaseRequest.id", purchaseRequest.getId())).list();

        funding = new Funding();
        funding.setName(NEW_FUNDING_NAME);
        funding.setId(OTHER_ID);
        _fundings.add(funding);

        fundingModel = selectModelFactory.create(_fundings, "label");

    }

    public Object onValueChanged(Funding funding) {
        if(funding != null && funding.getName().equals(NEW_FUNDING_NAME)) {
            return fundingZone.getBody();
        }
        return null;
    }

    @CommitAfter
    void onSuccessFromPR() {
            session.saveOrUpdate(purchaseRequest);
    }

//Select Menu OnChange
    public Object onValueChanged(Funding funding) {
        if(funding != null && funding.getName().equals(NEW_FUNDING_NAME)) {
            return fundingZone.getBody();
        }
        return null;
    }

//Encoders

    @SuppressWarnings("unchecked")
    public ValueEncoder getEncoderLineItem() {
        return new ValueEncoder<LineItem>() {
            public String toClient(LineItem value) {
                Long key = value.getTempId();
                return key.toString();
            }

            public LineItem toValue(String keyAsString) {
                Long key = new Long(keyAsString);
                for (LineItem holder : purchaseRequest.getLineItems()) {
                    if (holder.getTempId() == key) {
                        return holder;
                    }
                }
                return null;
            }
        };
    }

    @SuppressWarnings("unchecked")
    public ValueEncoder getEncoderLineItemFunding() {
        return new ValueEncoder<LineItemFunding>() {
            public String toClient(LineItemFunding value) {
                Long key = value.getTempId();
                return key.toString();
            }

            public LineItemFunding toValue(String keyAsString) {
                Long key = new Long(keyAsString);

                for (LineItemFunding holder : lineItem.getLineItemFundings()) {
                    if (holder.getTempId() == key) {
                        return holder;
                    }
                }
                return null;
            }
        };
    }

    public ValueEncoder<Funding> getSelectEncoder() {
        final ValueEncoder<Funding> encoder = valueEncoderSource.getValueEncoder(Funding.class);
        return new FundingValueEncoder(encoder);
    }

    final private static class FundingValueEncoder implements ValueEncoder<Funding> {
        final private ValueEncoder<Funding> delegate;

        public FundingValueEncoder(ValueEncoder<Funding> delegate) {
            this.delegate = delegate;
        }

        public String toClient(Funding value) {
            if (value == OTHER) {
                System.out.println(OTHER_ID);
                return OTHER_ID;
            } else {
                return delegate.toClient(value);
            }
        }

        public Funding toValue(String clientValue) {
            if (OTHER_ID.equals(clientValue))  {
                return OTHER;
            } else {
                return delegate.toValue(clientValue);
            }
        }
    }

//Add Row - TempID UUID

    LineItem onAddRowFromLineItem() {
        LineItem newLineItem = new LineItem();

        purchaseRequest.getLineItems().add(newLineItem);
        newLineItem.setPurchaseRequest(purchaseRequest);

        return newLineItem;
    }

    LineItemFunding onAddRowFromLineItemFunding(Long tempId) {
        LineItemFunding newLineItemFunding = new LineItemFunding();

        for (LineItem _lineItem : purchaseRequest.getLineItems()) {
            if (_lineItem.getTempId() == tempId) {
                 _lineItem.getLineItemFundings().add(newLineItemFunding);
                 newLineItemFunding.setLineItem(_lineItem);
                 break;
            }
        }
        return newLineItemFunding;
    }



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

Thiago H de Paula Figueiredo
On Fri, 24 Jun 2011 12:35:51 -0300, George Christman  
<[hidden email]> wrote:

>     void onPrepareFromPR() {
>
>         List<Funding> _fundings =
> session.createCriteria(Funding.class).add(Restrictions.eq("purchaseRequest.id",
> purchaseRequest.getId())).list();
>
>         funding = new Funding();
>         funding.setName(NEW_FUNDING_NAME);
>         funding.setId(OTHER_ID);
>         _fundings.add(funding);
>
>         fundingModel = selectModelFactory.create(_fundings, "label");
>
>     }

Here's the problem: you should use OTHER instead of instantiating Funding,  
as the encoder is doing a == check.

--
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, Ars Machina Tecnologia da Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

George Christman
Seems like we are super close now. Hopefully I'm doing this correctly

        List<Funding> _fundings = session.createCriteria(Funding.class).add(Restrictions.eq("purchaseRequest.id", purchaseRequest.getId())).list();

        _fundings.add(OTHER);

ValueEncoder is returning -1 as expected and the onValueChanged(Funding funding) seems to be returning an object. Only two issues left to resolve is a null funding name / id  within onValueChanged and no funding label exist within the select menu. If you could point me in the direction to resolving those two bugs, this issue should be completed. Once again, thanks so much!
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

Thiago H de Paula Figueiredo
On Fri, 24 Jun 2011 13:34:59 -0300, George Christman  
<[hidden email]> wrote:

> Seems like we are super close now. Hopefully I'm doing this correctly
>
>         List<Funding> _fundings =
> session.createCriteria(Funding.class).add(Restrictions.eq("purchaseRequest.id",
> purchaseRequest.getId())).list();
>
>         _fundings.add(OTHER);

I guess so. :)

> ValueEncoder is returning -1 as expected and the onValueChanged(Funding
> funding) seems to be returning an object. Only two issues left to  
> resolve is a null funding name / id  within onValueChanged and no  
> funding label exist within the select menu. If you could point me in the  
> direction to resolving those two bugs, this issue should be completed.  
> Once again, thanks so much!

I guess both can be solved by setting the id and the property used as  
label in the OTHER object.

--
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, Ars Machina Tecnologia da Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

George Christman
In reply to this post by Thiago H de Paula Figueiredo
Thiago, it looks like that did the trick.

I'm running into a couple issues, sorry to keep bothering you :-/

I'm setting the funding id / name

        List<Funding> _fundings = session.createCriteria(Funding.class).add(Restrictions.eq("purchaseRequest.id", purchaseRequest.getId())).list();
        NEW_FUNDING.setName(NEW_FUNDING_NAME);
        NEW_FUNDING.setId(OTHER_ID);
        _fundings.add(OTHER);

value encoder works perfectly, and the onChanged method works perfectly for a short period before funding id / name goes null. The funding object still exist though. Any Ideas?

    public Object onValueChanged(Funding funding) {
        System.out.println("Change " + funding.getId());
       
        if(funding != null && funding.getName().equals(NEW_FUNDING_NAME)) {
           return fundingZone.getBody();
        }
        return null;
    }

Also, I need to validate that the other object isn't being selected and committed to the db. I wrote this code within the onValidate method

        for (LineItem _lineItem : purchaseRequest.getLineItems()) {
            for(LineItemFunding _lineItemFunding : _lineItem.getLineItemFundings()) {
                if(lineItemFunding.getFunding().getId() == -1) {
                    _lineItem.getLineItemFundings().remove(_lineItemFunding);
                }
            }
        }

and I get the following error

java.util.ConcurrentModificationException

Hide uninteresting stack frames Stack trace

        * java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
        * java.util.AbstractList$Itr.next(AbstractList.java:343)
        * org.hibernate.collection.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:580)
        * com.mycompany.rolemanager.pages.Purchase_Request.onValidateFromPR(Purchase_Request.java:137)
        * com.mycompany.rolemanager.pages.Purchase_Request$MethodAccess_onValidateFromPR_130c294c1c0.invoke(Purchase_Request$MethodAccess_onValidateFromPR_130c294c1c0.java)
        * org.apache.tapestry5.internal.transform.BaseEventHandlerMethodInvoker.invokeEventHandlerMethod(BaseEventHandlerMethodInvoker.java:52)
        * org.apache.tapestry5.internal.transform.OnEventWorker$4.invokeEventHandlers(OnEventWorker.java:157)
        * org.apache.tapestry5.internal.transform.OnEventWorker$4.advise(OnEventWorker.java:136)
        * org.apache.tapestry5.internal.services.AbstractComponentMethodInvocation.proceed(AbstractComponentMethodInvocation.java:86)
        * com.mycompany.rolemanager.pages.Purchase_Request.dispatchComponentEvent(Purchase_Request.java)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl.dispatchEvent(ComponentPageElementImpl.java:942)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl.processEventTriggering(ComponentPageElementImpl.java:1132)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl.access$3000(ComponentPageElementImpl.java:72)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl$7.invoke(ComponentPageElementImpl.java:1077)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl$7.invoke(ComponentPageElementImpl.java:1075)
        * org.apache.tapestry5.ioc.internal.OperationTrackerImpl.invoke(OperationTrackerImpl.java:65)
        * org.apache.tapestry5.ioc.internal.PerThreadOperationTracker.invoke(PerThreadOperationTracker.java:68)
        * org.apache.tapestry5.ioc.internal.RegistryImpl.invoke(RegistryImpl.java:1063)
        * org.apache.tapestry5.internal.structure.ComponentPageElementResourcesImpl.invoke(ComponentPageElementResourcesImpl.java:141)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl.triggerContextEvent(ComponentPageElementImpl.java:1073)
        * org.apache.tapestry5.internal.structure.InternalComponentResourcesImpl.triggerContextEvent(InternalComponentResourcesImpl.java:287)
        * org.apache.tapestry5.corelib.components.Form.fireValidateEvent(Form.java:606)
        * org.apache.tapestry5.corelib.components.Form.fireValidateFormEvent(Form.java:594)
        * org.apache.tapestry5.corelib.components.Form._$advised$onAction(Form.java:548)
        * org.apache.tapestry5.corelib.components.Form$onAction$invocation_130c294d0e0.invokeAdvisedMethod(Form$onAction$invocation_130c294d0e0.java)
        * org.apache.tapestry5.internal.services.AbstractComponentMethodInvocation.proceed(AbstractComponentMethodInvocation.java:77)
        * org.apache.tapestry5.ioc.internal.services.LoggingAdvice.advise(LoggingAdvice.java:37)
        * org.apache.tapestry5.internal.transform.LogWorker$1.advise(LogWorker.java:54)
        * org.apache.tapestry5.internal.services.AbstractComponentMethodInvocation.proceed(AbstractComponentMethodInvocation.java:86)
        * org.apache.tapestry5.corelib.components.Form.onAction(Form.java)
        * org.apache.tapestry5.corelib.components.Form$MethodAccess_onAction_130c294c1da.invoke(Form$MethodAccess_onAction_130c294c1da.java)
        * org.apache.tapestry5.internal.transform.BaseEventHandlerMethodInvoker.invokeEventHandlerMethod(BaseEventHandlerMethodInvoker.java:52)
        * org.apache.tapestry5.internal.transform.OnEventWorker$4.invokeEventHandlers(OnEventWorker.java:157)
        * org.apache.tapestry5.internal.transform.OnEventWorker$4.advise(OnEventWorker.java:136)
        * org.apache.tapestry5.internal.services.AbstractComponentMethodInvocation.proceed(AbstractComponentMethodInvocation.java:86)
        * org.apache.tapestry5.corelib.components.Form.dispatchComponentEvent(Form.java)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl.dispatchEvent(ComponentPageElementImpl.java:950)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl.processEventTriggering(ComponentPageElementImpl.java:1132)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl.access$3000(ComponentPageElementImpl.java:72)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl$7.invoke(ComponentPageElementImpl.java:1077)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl$7.invoke(ComponentPageElementImpl.java:1075)
        * org.apache.tapestry5.ioc.internal.OperationTrackerImpl.invoke(OperationTrackerImpl.java:65)
        * org.apache.tapestry5.ioc.internal.PerThreadOperationTracker.invoke(PerThreadOperationTracker.java:68)
        * org.apache.tapestry5.ioc.internal.RegistryImpl.invoke(RegistryImpl.java:1063)
        * org.apache.tapestry5.internal.structure.ComponentPageElementResourcesImpl.invoke(ComponentPageElementResourcesImpl.java:141)
        * org.apache.tapestry5.internal.structure.ComponentPageElementImpl.triggerContextEvent(ComponentPageElementImpl.java:1073)
        * org.apache.tapestry5.internal.services.ComponentEventRequestHandlerImpl.handle(ComponentEventRequestHandlerImpl.java:81)
        * org.apache.tapestry5.internal.services.ImmediateActionRenderResponseFilter.handle(ImmediateActionRenderResponseFilter.java:42)
        * $ComponentEventRequestHandler_130c294ac92.handle($ComponentEventRequestHandler_130c294ac92.java)
        * org.apache.tapestry5.internal.services.AjaxFilter.handle(AjaxFilter.java:42)
        * $ComponentEventRequestHandler_130c294ac92.handle($ComponentEventRequestHandler_130c294ac92.java)
        * org.apache.tapestry5.upload.internal.services.UploadExceptionFilter.handle(UploadExceptionFilter.java:75)
        * $ComponentEventRequestHandler_130c294ac92.handle($ComponentEventRequestHandler_130c294ac92.java)
        * org.apache.tapestry5.services.TapestryModule$39.handle(TapestryModule.java:2583)
        * $ComponentEventRequestHandler_130c294ac92.handle($ComponentEventRequestHandler_130c294ac92.java)
        * $ComponentEventRequestHandler_130c294ab4e.handle($ComponentEventRequestHandler_130c294ab4e.java)
        * org.apache.tapestry5.internal.services.ComponentRequestHandlerTerminator.handleComponentEvent(ComponentRequestHandlerTerminator.java:43)
        * org.apache.tapestry5.services.InitializeActivePageName.handleComponentEvent(InitializeActivePageName.java:39)
        * $ComponentRequestHandler_130c294ab50.handleComponentEvent($ComponentRequestHandler_130c294ab50.java)
        * $ComponentRequestHandler_130c294ab35.handleComponentEvent($ComponentRequestHandler_130c294ab35.java)
        * org.apache.tapestry5.internal.services.ComponentEventDispatcher.dispatch(ComponentEventDispatcher.java:46)
        * $Dispatcher_130c294ab37.dispatch($Dispatcher_130c294ab37.java)
        * $Dispatcher_130c294ab30.dispatch($Dispatcher_130c294ab30.java)
        * org.apache.tapestry5.services.TapestryModule$RequestHandlerTerminator.service(TapestryModule.java:321)
        * org.apache.tapestry5.internal.services.RequestErrorFilter.service(RequestErrorFilter.java:26)
        * $RequestHandler_130c294ab31.service($RequestHandler_130c294ab31.java)
        * org.apache.tapestry5.services.TapestryModule$4.service(TapestryModule.java:984)
        * $RequestHandler_130c294ab31.service($RequestHandler_130c294ab31.java)
        * org.apache.tapestry5.services.TapestryModule$3.service(TapestryModule.java:974)
        * $RequestHandler_130c294ab31.service($RequestHandler_130c294ab31.java)
        * org.apache.tapestry5.internal.services.StaticFilesFilter.service(StaticFilesFilter.java:90)
        * $RequestHandler_130c294ab31.service($RequestHandler_130c294ab31.java)
        * org.apache.tapestry5.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:90)
        * org.apache.tapestry5.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:81)
        * org.apache.tapestry5.ioc.internal.util.ConcurrentBarrier.withRead(ConcurrentBarrier.java:85)
        * org.apache.tapestry5.internal.services.CheckForUpdatesFilter.service(CheckForUpdatesFilter.java:103)
        * $RequestHandler_130c294ab31.service($RequestHandler_130c294ab31.java)
        * $RequestHandler_130c294ab27.service($RequestHandler_130c294ab27.java)
        * org.apache.tapestry5.services.TapestryModule$HttpServletRequestHandlerTerminator.service(TapestryModule.java:272)
        * org.apache.tapestry5.upload.internal.services.MultipartServletRequestFilter.service(MultipartServletRequestFilter.java:44)
        * $HttpServletRequestHandler_130c294ab29.service($HttpServletRequestHandler_130c294ab29.java)
        * org.apache.tapestry5.internal.gzip.GZipFilter.service(GZipFilter.java:53)
        * $HttpServletRequestHandler_130c294ab29.service($HttpServletRequestHandler_130c294ab29.java)
        * org.apache.tapestry5.internal.services.IgnoredPathsFilter.service(IgnoredPathsFilter.java:62)
        * $HttpServletRequestFilter_130c294ab25.service($HttpServletRequestFilter_130c294ab25.java)
        * $HttpServletRequestHandler_130c294ab29.service($HttpServletRequestHandler_130c294ab29.java)
        * org.apache.tapestry5.services.TapestryModule$2.service(TapestryModule.java:928)
        * $HttpServletRequestHandler_130c294ab29.service($HttpServletRequestHandler_130c294ab29.java)
        * $HttpServletRequestHandler_130c294ab23.service($HttpServletRequestHandler_130c294ab23.java)
        * org.apache.tapestry5.TapestryFilter.doFilter(TapestryFilter.java:147)

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

Thiago H de Paula Figueiredo
On Fri, 24 Jun 2011 15:48:08 -0300, George Christman  
<[hidden email]> wrote:

>         List<Funding> _fundings =
> session.createCriteria(Funding.class).add(Restrictions.eq("purchaseRequest.id",
> purchaseRequest.getId())).list();
>         NEW_FUNDING.setName(NEW_FUNDING_NAME);
>         NEW_FUNDING.setId(OTHER_ID);
>         _fundings.add(OTHER);

You're setting the fields of NEW_FUNDING and using OTHER. ;)

OTHER.setName(NEW_FUNDING_NAME);
OTHER.setId(OTHER_ID);
_fundings.add(OTHER);

> Also, I need to validate that the other object isn't being selected and
> committed to the db. I wrote this code within the onValidate method
>
>         for (LineItem _lineItem : purchaseRequest.getLineItems()) {
>             for(LineItemFunding _lineItemFunding :
> _lineItem.getLineItemFundings()) {
>                 if(lineItemFunding.getFunding().getId() == -1) {
> _lineItem.getLineItemFundings().remove(_lineItemFunding);
>                 }
>             }
>         }
>
> and I get the following error
> java.util.ConcurrentModificationException

Copy the list to another list instance and work on the copy.

--
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, Ars Machina Tecnologia da Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

George Christman
Thanks Thiago for your patience, That was just a typo in my last question when changing my variable back to OTHER from NEW_FUNDING for the question. The problem had to do with the value encoder creating a new object when converting the client ID back to an object. I changed the way I handled the onValueChanged to look for a new Object like we did in the encoder instead of the object label and it solved the issue. So anyhow, I successfully got this working. I do think it would be a nice addition to be able to input an other option directly as a component parameter similar to blankLabel rather than having to go through all the troubles of coding this up. With the use of ajax, this is a very handy feature and can be used in many areas such as payment, shipping addresses, etc.

Anyhow, I'd like to share the code to all who maybe struggling with this. (I simplified my code for easier understanding and has not been tested for compiling errors)


<t:Select t:id="funding" model="fundingModel" zone="fundingZone" encoder="encoder"/>

    @Property
    private Funding funding;

    @Property
    @Persist
    private SelectModel fundingModel;

    @InjectComponent
    private Zone fundingZone;

    final private static Funding NEW_FUNDING = new Funding();
    final private static String NEW_FUNDING_ID = "-1";

    void onPrepare() {
        fundings = session.createCriteria(Funding.class).list();
        NEW_FUNDING.setName("+ Other");
        fundings.add(NEW_FUNDING);

        fundingModel = selectModelFactory.create(fundings, "label");

    }

    @CommitAfter
    void onSuccess() {
        //you would want to add some sort of logic to prevent the "Other" object from being commited.
    }

    public ValueEncoder<Funding> getEncoder() {
        final ValueEncoder<Funding> encoder = valueEncoderSource.getValueEncoder(Funding.class);
        return new FundingValueEncoder(encoder);
    }

    final private static class FundingValueEncoder implements ValueEncoder<Funding> {
        final private ValueEncoder<Funding> delegate;

        public FundingValueEncoder(ValueEncoder<Funding> delegate) {
            this.delegate = delegate;
        }

        public String toClient(Funding value) {
            if (value == NEW_FUNDING) {
                return NEW_FUNDING_ID;
            } else {
                return delegate.toClient(value);
            }
        }

        public Funding toValue(String clientValue) {
            if (NEW_FUNDING_ID.equals(clientValue))  {
                return NEW_FUNDING;
            } else {
                return delegate.toValue(clientValue);
            }
        }
    }

    public Object onValueChanged(Funding funding) {
        if(funding == NEW_FUNDING) {
            return fundingZone.getBody();
        }
        return null;
    }


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: T5 Select Menu with Other Option

George Christman
In reply to this post by Thiago H de Paula Figueiredo
After playing with the value encoder, I found this method to be slightly better since it will handle newly created session objects / existing objects and other.

    @SuppressWarnings("unchecked")
    public ValueEncoder getSelectEncoder() {
        return new ValueEncoder<Funding>() {
            public String toClient(Funding value) {
                if (value == NEW_FUNDING) {
                    return NEW_FUNDING_ID;
                } else {
                    Long key = value.getTempId();
                    return key.toString();
                }
            }

            public Funding toValue(String clientValue) {
                if (NEW_FUNDING_ID.equals(clientValue))  {
                    return NEW_FUNDING;
                } else {
                    for (Funding _funding : getPurchaseRequest().getFundings()) {
                        if (_funding.getTempId() == Long.parseLong(clientValue)) {
                            return _funding;
                        }
                    }
                }
                return null;
            }
        };
    }
Loading...