Existem várias maneiras de atingir o requisito.
Se o seu servletcontainer suporta um mínimo de Servlet 3.0 / EL 2.2, apenas passe-o como um argumento do método de ação / ouvinte do UICommand
componente ou AjaxBehavior
tag. Por exemplo
<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
Em combinação com:
public void insert(Long id) {
// ...
}
Isso requer apenas que o modelo de dados seja preservado para a solicitação de envio do formulário. O melhor é colocar o bean no escopo de visualização@ViewScoped
.
Você pode até mesmo passar todo o objeto do item:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
com:
public void insert(Item item) {
// ...
}
Em contêineres Servlet 2.5, isso também é possível se você fornecer uma implementação EL que suporte isso, como JBoss EL. Para detalhes de configuração, veja esta resposta .
Use <f:param>
no UICommand
componente. Ele adiciona um parâmetro de solicitação.
<h:commandLink action="#{bean.insert}" value="insert">
<f:param name="id" value="#{item.id}" />
</h:commandLink>
Se o seu bean tiver escopo de solicitação, deixe o JSF configurá-lo por @ManagedProperty
@ManagedProperty(value="#{param.id}")
private Long id; // +setter
Ou se o seu bean tem um escopo mais amplo ou se você deseja uma validação / conversão mais refinada, use <f:viewParam>
na visualização de destino, consulte também f: viewParam vs @ManagedProperty :
<f:viewParam name="id" value="#{bean.id}" required="true" />
De qualquer forma, isso tem a vantagem de que o modelo de dados não precisa necessariamente ser preservado para o envio do formulário (para o caso de seu bean ter escopo de solicitação).
Use <f:setPropertyActionListener>
no UICommand
componente. A vantagem é que isso elimina a necessidade de acessar o mapa de parâmetros da solicitação quando o bean tem um escopo mais amplo do que o escopo da solicitação.
<h:commandLink action="#{bean.insert}" value="insert">
<f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
</h:commandLink>
Em combinação com
private Long id; // +setter
Estará disponível apenas por propriedade id
no método de ação. Isso requer apenas que o modelo de dados seja preservado para a solicitação de envio do formulário. O melhor é colocar o bean no escopo de visualização por @ViewScoped
.
Vincule o valor da tabela de dados a, DataModel<E>
que por sua vez envolve os itens.
<h:dataTable value="#{bean.model}" var="item">
com
private transient DataModel<Item> model;
public DataModel<Item> getModel() {
if (model == null) {
model = new ListDataModel<Item>(items);
}
return model;
}
(torná-lo transient
e instanciá-lo preguiçosamente no getter é obrigatório quando você está usando isso em uma visão ou bean com escopo de sessão, uma vez DataModel
que não implementaSerializable
)
Em seguida, você poderá acessar a linha atual DataModel#getRowData()
sem passar nada (o JSF determina a linha com base no nome do parâmetro de solicitação do link / botão de comando clicado).
public void insert() {
Item item = model.getRowData();
Long id = item.getId();
// ...
}
Isso também requer que o modelo de dados seja preservado para a solicitação de envio do formulário. O melhor é colocar o bean no escopo de visualização por @ViewScoped
.
Use Application#evaluateExpressionGet()
para avaliar programaticamente o atual #{item}
.
public void insert() {
FacesContext context = FacesContext.getCurrentInstance();
Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
Long id = item.getId();
// ...
}
O caminho a ser escolhido depende dos requisitos funcionais e se um ou outro oferece mais vantagens para outros fins. Eu pessoalmente iria em frente com o # 1 ou, quando você gostaria de oferecer suporte a containers servlet 2.5 também, com o # 2.