Есть несколько способов выполнить требование.
Используйте взамен <f:param>
. Добавляет параметр запроса.
<h:commandLink action="#{bean.insert}" value="insert">
<f:param name="id" value="#{item.id}" />
</h:commandLink>
Если ваш бин находится в области запроса, пусть JSF установит его на @ManagedProperty
@ManagedProperty(value="#{param.id}")
private Long id; // +setter
Или, если ваш компонент имеет более широкую область действия или если вы хотите более детализированную проверку / преобразование, используйте <f:viewParam>
в целевом представлении, см. Также f: viewParam vs @ ManagedProperty :
<f:viewParam name="id" value="#{bean.id}" required="true" />
В любом случае, это имеет преимущество в том, что модель данных не обязательно должна быть сохранена для отправки формы (для случая, когда ваш компонент является областью запроса).
Используйте взамен <f:setPropertyActionListener>
. Преимущество состоит в том, что это устраняет необходимость доступа к карте параметров запроса, когда боб имеет более широкую область действия, чем область запроса.
<h:commandLink action="#{bean.insert}" value="insert">
<f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
</h:commandLink>
В сочетании с
private Long id; // +setter
Это будет просто доступно по свойству id
в методе действия. Это только требует, чтобы модель данных была сохранена для запроса отправки формы. Лучше всего поместить боб в область видимости на @ViewScoped
.
Если ваш сервлет-контейнер поддерживает Servlet 3.0 / EL 2.2, просто передайте его в качестве аргумента метода. Это также требует, чтобы модель данных была сохранена для запроса отправки формы. Лучше всего поместить боб в область видимости на @ViewScoped
.
<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
В сочетании с:
public void insert(Long id) {
// ...
}
Вы можете даже передать весь объект предмета:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
с:
public void insert(Item item) {
// ...
}
В контейнерах Servlet 2.5 это также возможно, если вы предоставите реализацию EL, которая поддерживает это, например, JBoss EL. Подробнее о конфигурации см. этот ответ .
Привязать значение данных к DataModel<E>
, что, в свою очередь, оборачивает элементы.
<h:dataTable value="#{bean.model}" var="item">
с
private transient DataModel<Item> model;
public DataModel<Item> getModel() {
if (model == null) {
model = new ListDataModel<Item>(items);
}
return model;
}
(делая его transient
и лениво создавая его экземпляр в геттере, обязательно, если вы используете его в bean-объекте представления или сеанса, поскольку DataModel
не реализует Serializable
)
Тогда вы сможете получить доступ к текущей строке с помощью DataModel#getRowData()
, ничего не передавая (JSF определяет строку на основе имени параметра запроса по нажатой ссылке / кнопке команды).
public void insert() {
Item item = model.getRowData();
Long id = item.getId();
// ...
}
Для этого также необходимо, чтобы модель данных была сохранена для запроса отправки формы. Лучше всего поместить боб в область видимости на @ViewScoped
.
Вы можете использовать Application#evaluateExpressionGet()
для программной оценки текущего #{item}
.
public void insert() {
FacesContext context = FacesContext.getCurrentInstance();
Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
Long id = item.getId();
// ...
}
Какой путь выбрать, зависит от функциональных требований и от того, предлагает ли тот или другой больше преимуществ для других целей. Лично я хотел бы продолжить с № 3 или, если вы хотите также поддерживать контейнеры с сервлетом 2.5, с № 2.