Статьи

Пример списка JSF

Это пример списка приложений, созданных с использованием JSF 2.0 (JavaServer Faces). Приложение представляет собой список задач (todo). Это приложение имеет функции для добавления, редактирования или удаления элементов в списке. Элемент todo имеет свойства name и description.

Страница JSF завершенного приложения имеет:

  • Список h:selectOneListbox реализован с использованием html-тега h:selectOneListbox .
  • Данные для списка заполняются с помощью основного тега f:selectItems .
  • Поля имени и описания h:inputText реализованы с использованием h:inputText и h:inputTextarea соответственно.
  • Функции new, edit, save, delete и cancel реализованы с h:commandButton тегов h:commandButton .
  • Сообщение о состоянии реализовано с использованием тега h:outputText .

Классы, используемые в приложении:

  • Todo: это представляет задачу, и имеет свойства name и description.
  • TodosBean: это управляемый боб; здесь есть код для запуска приложения, включая слушатели и методы доступа для компонентов.
  • TodoConverter: это пользовательский конвертер, преобразующий строковое имя todo в объект Todo и наоборот.

На следующем рисунке показан пользовательский интерфейс завершенного приложения:

todolist3

Этот пример приложения объясняется в три этапа. Первый шаг объясняет базовую реализацию списка. Функция приложения улучшена на следующих шагах. Шаги:

  • Шаг 1. В списке задач отображаются элементы, а при выборе отображаются свойства выбранного элемента.
  • Шаг 2: Список с задачами и функцией для добавления элементов в список.
  • Шаг 3: Список с задачами и функциями для добавления, редактирования и удаления элементов списка.

Шаг 1. В списке задач отображаются элементы, а при выборе отображаются свойства выбранного элемента.

todolist1

Ниже приведены компоненты кода для этого приложения:

  • Класс Todo.java представляет Todo.java .
  • index.xhtml — это страница JSF со списком и сообщением о состоянии, которое отображает выбранный элемент в списке.
  • Управляемый компонент TodosBean.java имеет функции для получения данных списка, запуска прослушивателя изменения значения списка и отображения сообщения о состоянии.

Todo.java:

Этот класс представляет элемент todo. Это имеет два атрибута — имя и описание. Обратите внимание на переопределенный метод toString() класса Object .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Package com.javaquizplayer.example;
public class Todo {
    private String name;
    private String desc;
    public Todo() {
    }
    public Todo(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    @Override
    public String toString() {
        return this.name;
    }
}

index.xhtml:

На этой странице JSF отображается список задач. Список можно прокрутить и выбрать элемент. Имя выбранного элемента отображается в сообщении о состоянии.

Список реализован с h:selectOneListbox html-тега h:selectOneListbox . Текущее значение выбранного элемента списка указывается с помощью атрибута: value="#{bean.todo}" . Элементы выбора указываются с f:selectItems основного тега f:selectItems :

1
<f:selectItems value="#{bean.data}"/>

Этот тег находится внутри h:selectOneListbox tag . Элементы списка заполняются из TodosBean getData() TodosBean который возвращает коллекцию List . В списке отображаются метки — значения имени todo, т. Е. Значение String объекта Todo из метода toString() .

Слушатель изменения значения списка указывается с помощью атрибута:

1
valueChangeListener=""#{bean.valueChanged}"

Когда элемент списка выбран, форма отправляется, и этот код слушателя выполняется. В этом примере, когда выбран элемент списка, имя todo отображается в сообщении о состоянии как «todo_item_name selected».

Форма отправляется каждый раз, когда элемент выбирается в списке. Это указывается с помощью атрибута списка: onchange="submit()" .

Сообщение о состоянии отображается вместе с компонентом вывода:

1
<h:outputText id="msg" value="#{bean.message}" />

,

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    xmlns:h="http://java.sun.com/jsf/html">
<h:head>
    <title>A JSF List Example</title>
</h:head>
<h:body>
    <h:form>
        <h3>TODOs List</h3>
        <h:selectOneListbox id="list" size="10"
                value="#{bean.todo}"
                valueChangeListener="#{bean.valueChanged}"
                onchange="submit()">
            <f:selectItems value="#{bean.data}"/>
        </h:selectOneListbox>
        <h:outputText id="msg" value="#{bean.message}" />
    </h:form>
</h:body>
</html>

TodosBean:

Этот класс управляемых бинов имеет функции:

  • Для создания исходных данных задач и заполнения списка задач.
  • Слушатель изменения значения, чтобы получить текущий выбранный элемент списка.
  • Для захвата текущего выбранного значения элемента в списке.
  • Установите статус сообщения.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.javaquizplayer.example;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.event.ValueChangeEvent;
import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;
@ManagedBean(name="bean")
@SessionScoped
public class TodosBean implements Serializable {
    private List<Todo> data; // todo list data
    private String todo; // the currently selected item value
    private String msg; // status message
    public TodosBean() {
        loadData();
        // select the first item in the list
        Todo t = data.get(0);
        setTodo(t.getName());
        setMessage(t.getName() + " selected.");
    }
    private void loadData() {
        data = new ArrayList<>();
        Todo t = new Todo("item 1", "item 1 description");
        data.add(t);
        t = new Todo("item 2", "item 2 description");
        data.add(t);
        t = new Todo("item 3", "item 3 description");
        data.add(t);
        t = new Todo("item 4", "item 4 description");
        data.add(t);
    }
    public List<Todo> getData() {
        return data;
    }
    public String getTodo() {
        return todo;
    }
    public void setTodo(String t) {
        todo = t;
    }
    // value change listener for list item selection
    public void valueChanged(ValueChangeEvent e) {
        String t = (String) e.getNewValue();
        setMessage(t + " selected.");
    }
    public void setMessage(String s) {
        msg = s;
    }
    public String getMessage() {
        return msg;
    }
}

Шаг 2: Список с элементами todo и функцией для добавления элементов в список.

todolist2

На этом этапе в приложении есть функция добавления нового элемента todo. Нажмите кнопку «Создать», введите данные задачи в текстовые поля имени и описания и сохраните. Отмените новый ввод данных todo, нажав кнопку отмены или выбрав другой элемент в списке.

Компоненты кода те же, что и на предыдущем шаге, но дополнены новыми функциями. В приложение добавлен новый пользовательский класс конвертера.

  • Класс Todo.java представляет Todo.java , не изменяется.
  • index.xhtml — это страница JSF со списком и сообщением о состоянии, которое отображает выбранный элемент в списке. Кроме того, есть виджеты для ввода новых задач и сохранения.
  • Управляемый компонент TodosBean.java содержит код для получения данных списка, запуска прослушивателя изменения значения списков и отображения сообщения. Кроме того, есть слушатели действий для новых, сохранения и отмены действий.
  • Преобразователь TodoConverter.java преобразует данные из значения строки todo в объект Todo и наоборот.

Todo.java:

Этот класс остается неизменным.

index.xhtml:

Ниже приведены изменения:

Текущее значение элемента списка в списке указывается как: value="#{bean.todo}" . На предыдущем шаге 1 значение элемента было преобразовано в строку имени todo. Теперь значение разрешается в экземпляре Todo.

Следующее недавно добавлено:

Поля имени и описания h:inputText реализованы с h:inputTextarea тегов h:inputText и h:inputTextarea соответственно. Обратите внимание, что эти поля доступны для редактирования, только когда редактируются данные readonly="#{not bean.editable}" (т. Е. Функция New todo): readonly="#{not bean.editable}" . Когда список находится в режиме выбора, эти поля доступны только для чтения.

К списку прикреплен конвертер для преобразования имени выбранного элемента в объект Todo, и наоборот, с помощью основного тега f:converter :

1
<f:converter converterId="todoConvertor"/>

Обратите внимание, что для конвертера установлен атрибут:

1
<f:attribute name="beanattr" value="#{bean}"/>

; это используется для доступа к данным Todo в классе конвертера.

Добавлены три кнопки для новых, сохранения и отмены действий с помощью тега h:commandButton . У каждой кнопки есть соответствующий слушатель действий. Например:

1
<h:commandButton value="New" actionListener="#{bean.newListener}"/>

,

Наконец, отправка списка изменяется на вызов Ajax с использованием основного тега f:ajax : onchange="submit()" заменяется на

1
<f:ajax execute="@this" render="msg name desc" />

Почему это изменение?

При использовании опции отправки, когда действие «Новый» отменяется путем выбора другого элемента списка, поля «Текст» и «Текстовая область» не будут заполняться выбранным элементом; значения останутся отредактированными. Это потому, что отредактированные текстовые значения также отправляются вместе с формой; эти значения не изменятся на выбранные значения элемента. Но в Ajax форма не отправляется, обновляются только текстовые значения (атрибут render тега f:ajax указывает обновляемые поля: сообщение о состоянии, имя и описание задачи).

ПРИМЕЧАНИЕ. В следующем коде вновь добавленные и удаленные строки кода из предыдущего шага 1 выделены цветом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    xmlns:h="http://java.sun.com/jsf/html">
<h:head>
    <title>A JSF List Example</title>
</h:head>
<h:body>
    <h:form>
        <h3>TODOs List</h3>
            <h:panelGrid>
            <h:inputText id="name" value="#{bean.todoName}" size="30"
                    readonly="#{not bean.editable}"/>
            <h:inputTextarea id="desc" value="#{bean.todoDesc}"
                    rows="2" cols="40"
                    readonly="#{not bean.editable}"/>
            <h:selectOneListbox id="list" size="10" value="#{bean.todo}"
                    valueChangeListener="#{bean.valueChanged}"
                    onchange="submit()">
                <f:ajax execute="@this" render="msg name desc"/>
                <f:selectItems value="#{bean.data}"/>
                <f:attribute name="beanattr" value="#{bean}"/>
                <f:converter converterId="todoConvertor"/>
            </h:selectOneListbox>
                </h:panelGrid>
        <h:commandButton value="New" actionListener="#{bean.newListener}"/>
        <h:commandButton value="Save" actionListener="#{bean.saveListener}"/>
        <h:commandButton value="Cancel" actionListener="#{bean.cancelListener}"/>
        <h:outputText id="msg" value="#{bean.message}" />
    </h:form>
</h:body>
</html>

TodoConverter.java:

Это пользовательский класс-преобразователь, преобразующий объекты Todo в строку (имя todo) и наоборот.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.javaquizplayer.example;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;
import java.util.Map;
@FacesConverter(value="todoConvertor")
public class TodoConverter implements Converter {
    private static final long serialVersionUID = 1L;
    @Override
    public Object getAsObject(FacesContext context, UIComponent component,String value)
            throws ConverterException {
        if (value == null) {
            return null;
        }
        Map<String, Object> attrs = component.getAttributes();       
        TodosBean bean = (TodosBean) attrs.get("beanattr");
        Todo todo = bean.getTodoForName(value);
        return todo;
    }
    @Override
    public String getAsString(FacesContext context, UIComponent component,Object value)
            throws ConverterException {
        if (value == null) {
            return null;
        }
        Todo todo = (Todo) value;
        return todo.getName();
    }
}

TodosBean.java:

Этот класс управляемых бинов имеет функции:

  • Заполнить список задач.
  • Слушатель изменения значения, чтобы получить текущий выбранный элемент списка.
  • Для захвата текущего выбранного значения элемента в списке.
  • Установите статус сообщения.

Это изменения:

  • Сохраните текущее выбранное значение элемента в списке как объект Todo (вместо ранее использованной строки имени todo).
  • Слушатель изменения значения изменяется, чтобы получить объект Todo, а не строковое значение todo name.

Это недавно добавленные:

  • Методы доступа для имени todo, описания и их редактируемости.
  • Слушатели действий для новых, сохранения и отмены действий.
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package com.javaquizplayer.example;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.ActionEvent;
import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;
@ManagedBean(name="bean")
@SessionScoped
public class TodosBean implements Serializable {
    private List<Todo> data;
    private Todo todo; // selected item value
    private String msg;
    private String name; // text field value
    private String desc;
    private String actionFlag = "NONE"; // specifies the current action (NEW, NONE)
    private boolean editable;
    public TodosBean() {
        loadData();
        if (data.size() == 0) {
            return;
        }
        Todo t = data.get(0);
        selectRow(t); // select the first item in the list
    }
    private void selectRow(Todo t) {
        setTodo(t);
        setTodoName(t.getName());
        setTodoDesc(t.getDesc());
        setMessage(t.getName() + " selected."););
    }
    private void loadData() {
        data = new ArrayList<>();
    }
    public List<Todo> getData() {
        return data;
    }
    public Todo getTodo() {
        return todo;
    }
    public void setTodo(Todo t) {
        todo = t;
    }
    public void valueChanged(ValueChangeEvent e) {
        if (! actionFlag.equals("NONE")) {
            setEditable(false);
            actionFlag = "NONE";
        }
        Todo t = (Todo) e.getNewValue();
        setMessage(t.getName() + " selected."););
        setTodoName(t.getName());
        setTodoDesc(t.getDesc());
    }
    public void setMessage(String msg) {
        this.msg = msg;
    }
    public String getMessage() {
        return msg;
    }
    public String getTodoName() {
        return name;
    }
    public void setTodoName(String n) {
        name = n;
    }
    public String getTodoDesc() {
        return desc;
    }
    public void setTodoDesc(String d) {
        desc = d;
    }
    // returns the Todo object for a given todo name
    // method used in converter
    public Todo getTodoForName(String name) {
        for (Todo t : data) {
            if (name.equals(t.getName())) {
                return t;
            }
        }
        return null;
    }
    public void setEditable(boolean b) {
        editable = b;
    }
    public boolean getEditable() {
        return editable;
    }
    public void newListener(ActionEvent e) {
        setEditable(true);
        setMessage("Enter new todo. Name must be uniquie and at least 5 chars.");
        setTodoName("NEW Todo");
        setTodoDesc("");
        actionFlag = "NEW";
    }
    public void saveListener(ActionEvent e) {
        if (! actionFlag.equals("NEW")) {
            return;
        }
        String name = getTodoName();
        String desc = getTodoDesc();
        if (name.length() < 5) {
            setMessage("Name must be at least 5 chars long.");
            return;
        }
        if (duplicateName(name)) {
            setMessage("Name must be unique.");
            return;
        }
        Todo t = new Todo(name, desc);
        data.add(t);
        setMessage(name + " saved.");
        setTodo(t); // select the saved item
        setEditable(false);
        actionFlag = "NONE";
    }
    private boolean duplicateName(String name) {
        for (Todo t : data) {
            if (t.getName().equals(name)) {
                return true;
            }
        }
        return false;
    }
    public void cancelListener(ActionEvent e) {
        if (actionFlag.equals("NONE")) {
            return;
        }
        actionFlag = "NONE";
        setMessage(actionFlag + " action cancelled");
        if (data.size() == 0) {
            setTodoName("");
            setTodoDesc("");
            setEditable(false);
            return;
        }
        // populate text fields with selected item
        setTodoName(todo.getName());
        setTodoDesc(todo.getDesc());
        setEditable(false);
    }
}

Шаг 3: Список с задачами и функциями для добавления, редактирования и удаления элементов списка.

todolist3

Это законченное приложение. В нем есть функции для выбора, добавления, редактирования и удаления элемента списка.

На этом этапе добавляются две новые функции — редактирование, удаление элемента списка. Для редактирования выберите элемент списка задач и нажмите кнопку «Изменить». Это позволяет изменить имя и описание значения, а также сохранить. Редактирование можно отменить, нажав кнопку отмены или выбрав другой элемент списка. Функции удаления позволяют удалить выбранный элемент списка задач.

Компоненты кода те же, что и на предыдущем шаге 2, но дополнены новыми функциями.

  • Класс Todo.java представляет Todo.java . Это не изменилось.
  • Преобразователь TodoConverter.java преобразует данные из значения строки todo в объект Todo и наоборот. Это не изменилось.
  • index.xhtml — это страница JSF со списком, свойствами todo и сообщением о состоянии, которое отображает выбранный элемент в списке. Кроме того, есть виджеты для добавления, редактирования выбранного элемента или его удаления.
  • Управляемый компонент TodosBean.java содержит код для получения данных списка, запуска прослушивателя изменения значения списка и отображения сообщения. Кроме того, есть слушатели действий для новых, редактирования, удаления, сохранения и отмены действий.

Todo.java:

Этот класс остается неизменным.

TodoConverter.java:

Этот класс остается неизменным.

index.xhtml:

Следующее недавно добавлено:

Добавлены две командные кнопки для редактирования и удаления действий. У каждой кнопки есть соответствующий слушатель действий.

TodoBean.java:

Этот класс управляемых бинов имеет функции:

  • Заполнить список задач.
  • Слушатель изменения значения, чтобы получить текущий выбранный элемент списка.
  • Для захвата текущего выбранного значения элемента в списке.
  • Установите статус сообщения.
  • Методы доступа для имени todo, описания и их редактируемости.
  • Слушатели действий для новых, сохранения и отмены действий. Они расширены, чтобы приспособить функции редактирования и удаления.

Это недавно добавленные:

  • Слушатели действий для редактирования и удаления действий.

Скачать код:

Это ссылки для загрузки готового файла WAR приложения и исходного кода.

Примечания и ссылки:

Это приложение разработано с использованием Apache MyFaces 2.0 (MyFaces 2.0 реализует JavaServer Faces 2.0). Приложение протестировано на веб-сервере Tomcat 6 и сервере приложений GlassFish 3 (GlassFish 3 реализует Java EE 6).

Полезные ссылки: