Does anybody else use the AjaxFormLoop? Either I am using it incorrectly, or it is very buggy. I'd like to point out I'm using Tap 5.4-beta-2.
Another interesting bug seems to happen when you add a new row and provide a null toValue from the encoder. The row adds without issue, but if you attempt to remove the row before saving, you get an exception. This behavior worked without issue in 5.3.7. I can provide a temp id if that's whats required to make it work properly. Issue 2, when I have textfield number validate="min-length=10,required" and I submit the form on a new row with a validation error, the page reloads with a serverside error without highlighting the field, "clienside validation on", the url ends in form rather than the original person id. Now when I fixed the validation error and resubmit it, that's when I discover the phone has somehow been persisted with a pk despite hibernate save never being called. I am not sure how it's getting it's ID. When I remove the cascade all, it does no persist the phone record. I discovered this issue when I noticed my toValue was failing do to the fact it was trying to do a query against the database for a record that does not yet exist. If the data is correct on a save, the save works perfectly and as long as the data has a pk, the remove works perfectly. On Wed, Jan 22, 2014 at 11:23 PM, George Christman <gchrist...@cardaddy.com>wrote: > Hello, I'm having some difficulties with the AjaxFormLoop component and > I'm hoping one of you guys could help me out. > > > For the most part, I've followed the following example > http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/AjaxFormLoop.htmlhowever, > my implementation needs to be slightly different from the > example. > > I need to be able to instantiate a new Person() object and before ever > persisting the object be able to add new Phone objects to the arraylist > with the ajaxformloop. Once the user finishes inputting the data, then save > the changes by submitting the form and commit them all to the database. > > Now I'm aware you need to use a value encoder to do this, but I'm running > into an issue where hibernate is trying to save the phone object before I > ever call session.save() which is resulting exceptions. > > I'm hoping someone can provide me with a little help or an example of how > to accomplish this task. > > Example code > > <div t:type="ajaxformloop" t:id="phones" source="person.phones" value="phone" > encoder="encoder"> > <t:textfield t:id="number" value="phone.number"/> > <t:removerowlink>remove</t:removerowlink> > </div> > > public class Edit { > > @PageActivationContext > @Property > private Person person; > > @Property > private Phone phone; > > @Inject > private Session session; > > public void onPrepare() { > if(person == null) { > person = new Person(); > } > } > > @CommitAfter > public Object onSuccess() { > session.saveOrUpdate(person); > return Index.class; > } > > Object onAddRowFromPhones() { > return new Phone(); > } > > @CommitAfter > void onRemoveRowFromPhones(Phone phone) { > if(phone.getId() != null) { > session.delete(phone); > } > } > > @SuppressWarnings("unchecked") > public ValueEncoder getEncoder() { > > return new ValueEncoder<AccessPoint>() { > > @Override > public String toClient(Phone value) { > Long id = value.getId(); > return id != null ? id.toString() : null; > > } > > @Override > public Phone toValue(String toValue) { > if(toValue != null) { > System.out.println(toValue); > Long id = Long.parseLong(toValue); > > phone = session.createCritera(Phone.class, id); > } else { > person.getPhones().add(phone); > phone = new Phone(person); > > } > return phone; > } > }; > } > } > > @Entity > public class Person { > > @Id > @GeneratedValue(strategy = GenerationType.auto) > @NonVisual > private long id; > > @OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval > = true) > private List<Phone> phones; > > public List<Phone> getPhones() { > if(phones == null) { > phones = new ArrayList<>(); > } > return phones; > } > > public void setPhones(List<Phone> phones) { > this.phones = phones; > } > > } > > @Entity > public class Phone { > > @Id > @GeneratedValue(strategy = GenerationType.auto) > @NonVisual > private long id; > > @ManyToOne(optional = false) > private Person person; > > @Column(nullable = true, length = 20) > @Width(20) > @Validate("required,maxlength=20") > private String number; > > public Phone(Person person) { > this.person = person; > } > > //getters and setters > > } > > Thanks in advance. > > -- George Christman www.CarDaddy.com P.O. Box 735 Johnstown, New York