Калитка — порядок добавления компонентов в Java имеет значение?

#java #wicket

#java #калитка

Вопрос:

Я создал простую форму калитки с выпадающим списком, кнопкой отправки и двумя текстовыми полями, чтобы попробовать некоторую цепочку моделей. HTML:

     <!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
    <head>
        <meta charset="utf-8" />
        <title>DropDownTest</title>
    </head>
    <body>      
        <form wicket:id="selectForm">   
            <select wicket:id="dropDown"></select>              
            <input type="submit" wicket:id="bt"/>           
            <input type="text" wicket:id="age"/>
            <input type="text" wicket:id="name"/>           
        </form>             
    </body>
</html>
  

и код Java:

 public class HomePage extends WebPage {
    private static final long serialVersionUID = 1L;    

private class Person implements Serializable {
    private int age;
    private String name;

    public Person(){};

    public Person(int pAge, String pName) {     
        age = pAge;
        name = pName;           
    }

    public int getAge() {return age;}

    public void setAge(int age) {this.age = age;}

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

}   

public List<Person> getPersons() {

    List<Person> persons = new ArrayList<Person>();
    persons.add(new Person(34, "Hanna"));
    persons.add(new Person(17, "Ivan"));
    persons.add(new Person(64, "Carol"));   
    return persons;
}

private Form form;
private DropDownChoice<Person> dropDown;

public HomePage(final PageParameters parameters) {
    super(parameters);      

    Model<Person> personModel = new Model<Person>();

    dropDown = new DropDownChoice<Person>("dropDown", personModel, getPersons(), 
            new ChoiceRenderer<Person>("name"));

    form = new Form("selectForm");

    form.add(new TextField("name", new PropertyModel(personModel, "name")));
    form.add(new TextField("age", new PropertyModel(personModel, "age")));      
    form.add(dropDown);

    form.add(new Button("bt"));     

    add(form);
}   
}
  

Выпадающий список и два текстовых поля используют одну и ту же модель (PersonModel), поэтому, когда пользователь выбирает пользователя из выпадающего списка и отправляет форму, нажимая кнопку, и страница перезагружается, два поля получают свои значения от пользователя, выбранного с помощью модели. Это работает так, как ожидалось, и я не получаю ошибок. Теперь, если я изменю порядок, в котором я добавляю компоненты в форму из этого (рабочего):

 form.add(new TextField("name", new PropertyModel(personModel, "name")));
form.add(new TextField("age", new PropertyModel(personModel, "age")));      
form.add(dropDown);
  

к этому (не работает)

 form.add(dropDown);
form.add(new TextField("name", new PropertyModel(personModel, "name")));
form.add(new TextField("age", new PropertyModel(personModel, "age")));
  

Я получаю сообщение об ошибке при отправке формы:

Метод [public int com.asbjorntest.Домашняя страница $Person.getAge()]. Не удается преобразовать нулевое значение в примитивный класс: int для его установки в com.asbjorntest.Домашняя страница $Person @71460b93

Я понимаю, что ошибка возникает из-за того, что я отправляю текстовое поле «возраст» без какого-либо значения, и оно не может быть преобразовано в int в моем классе Person. Но почему эта ошибка возникает только в том случае, если я добавляю выпадающий список перед добавлением текстовых полей в код Java? Или, может быть, я должен спросить: почему этого НЕ происходит, когда я добавляю его после? Имеет ли значение порядок, в котором я добавляю компоненты в форму или на страницу в коде Java, или я здесь что-то полностью упускаю?

Заранее спасибо за любые ответы или подсказки!

Ответ №1:

Я думаю, что порядок в HTML не имеет значения. Порядок в Java может иметь значение, поскольку порядок компонентов определяет, как они проверяются.

Когда вы добавляете DropDownChoice последнюю версию, значение null age from the TextField будет переопределено значением, которое вы выбрали в раскрывающемся списке, и все работает нормально.

Если вы разместите свои компоненты наоборот, у age вас будет null (значение из TextField , и вы получите свою ошибку.

Короче говоря: будьте осторожны, когда несколько компонентов редактируют одно и то же значение модели.

Ответ №2:

Насколько я помню, не рекомендуется делиться моделями между компонентами, и поэтому рекомендуется создавать новую для каждого компонента. Обратите внимание, что при создании personModel изначально не привязан конкретный человек, я подозреваю, что он создается при добавлении на страницу. Таким образом, лицо модели равно нулю, когда текстовые поля создаются и добавляются в форму.

В общем, я бы порекомендовал вам что-то подобное:

 public HomePage(final PageParameters parameters) {
    super(parameters);      

    Person person = new Person();
    form = new Form("selectForm");

    dropDown = new DropDownChoice<Person>("dropDown", new Model<Person>(person), getPersons(), new ChoiceRenderer<Person>("name"));
        form.add(dropDown);

    // I think you can use person as first parameter, else use new Model<Person(person),
    form.add(new TextField("name", new PropertyModel(person, "name")));
    form.add(new TextField("age", new PropertyModel(person, "age")));      

    form.add(new Button("bt"));     

    add(form);
} 
  

В любом случае, прошло довольно много времени с тех пор, как я использовал Wicket, поэтому я могу быть совершенно неправ: P

Комментарии:

1. Хорошо, спасибо за ответ! Я новичок в Wicket, и я следовал руководству / руководству от apache, где описано, что модели совместного использования могут использоваться для создания цепочки моделей, где модель-результат одного компонента (в моем случае выпадающего списка) может быть источником модели для другого компонента. Но я полагаю, что, как комментирует @RobAu, я должен быть осторожен с порядком из-за проблем с проверкой. С уважением!