I would like to share some additional details related to this issue. I'm
finding after removing a row and refreshing the page the selected option is
marked selected in the html correctly, however the option displayed in the
select menu is the former select option from the previously deleted row.
I'm not sure why the selected option is being ignored. If I change the
ajaxformloop to a loop and refresh the page, all my select options the
appear to be correct. Below is the code used to reproduce the bug.

How I to reproduce it.

Add 3 rows.

Row 1. Select Mobile - Type "test1"
Row 2. Select Home - Type "test2"
Row 3 Select Fax - Type "test3"

Save results

Remove Row 1

Refresh page.

Notice how the results change to the following.

Row 1. Select Mobile - Type "test2"
Row 2. Select Home - Type "test3"

Code used to reproduce bug.

tml

<html t:type="layout" title="AjaxFormLoopDemo" xmlns:t="
http://tapestry.apache.org/schema/tapestry_5_1_0.xsd";
xmlns:p="tapestry:parameter">
    <t:form t:id="form">
        <div t:type="ajaxformloop" t:id="phones" source="person.phones"
value="phone" encoder="encoder">
            <t:select t:id="type" model="selectModel"
value="phone.phoneType"/>
            <t:textfield t:id="number" value="phone.number"/>
            <t:removerowlink>remove</t:removerowlink>
        </div>
        <input type="submit" value="Update"/>
    </t:form>
</html>

java

public class AjaxFormLoopDemo {

    @Property
    private Phone phone;
    @PageActivationContext
    @Property
    private Person person;
    @Inject
    private SelectModelFactory selectModelFactory;
    @Inject
    private Session session;

    void onPrepare() {
        if (person == null) {
            person = new Person();
        }

        List<PhoneType> phoneTypes =
session.createCriteria(PhoneType.class).addOrder(Order.desc("id")).list();

        if (phoneTypes.isEmpty()) {
            setupPhoneTypes();
        }
    }

    @CommitAfter
    public void setupPhoneTypes() {
        PhoneType phoneType = new PhoneType("HOME");
        session.save(phoneType);

        phoneType = new PhoneType("MOBILE");
        session.save(phoneType);

        phoneType = new PhoneType("FAX");
        session.save(phoneType);
    }

    @CommitAfter
    public void onSuccess() {
        session.saveOrUpdate(person);
    }

    public SelectModel getSelectModel() {
        List<PhoneType> phoneTypes =
session.createCriteria(PhoneType.class).addOrder(Order.asc("type")).list();
        return selectModelFactory.create(phoneTypes, "type");
    }

    Object onAddRow() {
        return new Phone(person);
    }

    @CommitAfter
    void onRemoveRow(Phone phone) {
        person.getPhones().remove(phone);
        session.delete(phone);
    }

    public ValueEncoder<Phone> getEncoder() {
        return new ValueEncoder<Phone>() {
            @Override
            public String toClient(Phone v) {
                Long id = v.getId();
                return id != null ? id.toString() :
v.getTempId().toString();
            }

            @Override
            public Phone toValue(String toValue) {
                Long id = Long.parseLong(toValue);

                if (id > 0) {
                    Phone phone = (Phone) session.get(Phone.class, id);
                    return phone;
                }
                Phone phone = new Phone(person);
                person.getPhones().add(phone);
                return phone;
            }
        };
    }
}

Person entity

@Entity
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL,
orphanRemoval = true)
    @OrderBy("id")
    private List<Phone> phones;

    @Transient
    private Long tempId = -System.nanoTime();

    public Person() {
    }

    public Long getTempId() {
        return tempId;
    }

    public void setTempId(Long tempId) {
        this.tempId = tempId;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public List<Phone> getPhones() {
        if (phones == null) {
            phones = new ArrayList<>();
        }
        return phones;
    }

    public void setPhones(List<Phone> phones) {
        this.phones = phones;
    }

}

Phone Entity

@Entity
public class Phone implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @ManyToOne
    @JoinColumn(name = "phone_type_id")
    private PhoneType phoneType;
    @ManyToOne
    @JoinColumn(name = "person_id")
    private Person person;
    private String number;
    @Transient
    private Long tempId = -System.nanoTime();

    public Phone() {
    }

    public Phone(Person person) {
        this.person = person;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public Long getTempId() {
        return tempId;
    }

    public void setTempId(Long tempId) {
        this.tempId = tempId;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public PhoneType getPhoneType() {
        return phoneType;
    }

    public void setPhoneType(PhoneType phoneType) {
        this.phoneType = phoneType;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

}

PhoneType entity

@Entity
public class PhoneType implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String type;
    @Transient
    private Long tempId = -System.nanoTime();

    public PhoneType() {
    }

    public PhoneType(String type) {
        this.type = type;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Long getTempId() {
        return tempId;
    }

    public void setTempId(Long tempId) {
        this.tempId = tempId;
    }

}


On Fri, Nov 22, 2013 at 1:34 AM, George Christman
<gchrist...@cardaddy.com>wrote:

> Hello, I have an ajaxformloop with a nested select menu loaded from the
> database.
>
> Lets say we have two rows in the list and both select menus have selected
> values. When I remove the first row everything works as desired. If I
> refresh the page I'm finding my now single row ajaxformloop select menu
> sets the selected value to the now deleted rows selected value. Despite
> page refreshes, the value remained. Now I found if I altered the id in the
> select menu and then refreshed the page, the select menu now properly set
> the selected value.
>
> It seems as if the selected value is being cached, does anybody know what
> might be going on?
>
>


-- 
George Christman
www.CarDaddy.com
P.O. Box 735
Johnstown, New York

Reply via email to