Esistono diversi modi per soddisfare il requisito.
Se il tuo servletcontainer supporta un minimo di Servlet 3.0 / EL 2.2, passalo come argomento del metodo action / listener del UICommand
componente o del AjaxBehavior
tag. Per esempio
<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
In combinazione con:
public void insert(Long id) {
// ...
}
Ciò richiede solo che il modello di dati venga conservato per la richiesta di invio del modulo. La cosa migliore è mettere il bean nell'area di visualizzazione di @ViewScoped
.
Puoi anche passare l'intero oggetto oggetto:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
con:
public void insert(Item item) {
// ...
}
Sui contenitori Servlet 2.5, questo è possibile anche se fornisci un'implementazione EL che lo supporta, come JBoss EL. Per i dettagli sulla configurazione, vedere questa risposta .
Utilizzare <f:param>
nel UICommand
componente. Aggiunge un parametro di richiesta.
<h:commandLink action="#{bean.insert}" value="insert">
<f:param name="id" value="#{item.id}" />
</h:commandLink>
Se il tuo bean ha l'ambito della richiesta, lascia che JSF lo imposti da @ManagedProperty
@ManagedProperty(value="#{param.id}")
private Long id; // +setter
Oppure, se il tuo bean ha un ambito più ampio o se desideri una convalida / conversione più dettagliata, usalo<f:viewParam>
nella vista di destinazione, vedi anche f: viewParam vs @ManagedProperty :
<f:viewParam name="id" value="#{bean.id}" required="true" />
In ogni caso, questo ha il vantaggio che il datamodel non deve necessariamente essere conservato per l'invio del modulo (nel caso in cui il tuo bean abbia lo scope della richiesta).
Utilizzare <f:setPropertyActionListener>
nel UICommand
componente. Il vantaggio è che ciò elimina la necessità di accedere alla mappa dei parametri della richiesta quando il bean ha un ambito più ampio rispetto all'ambito della richiesta.
<h:commandLink action="#{bean.insert}" value="insert">
<f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
</h:commandLink>
In combinazione con
private Long id; // +setter
Sarà disponibile solo per proprietà id
nel metodo di azione. Ciò richiede solo che il modello di dati venga conservato per la richiesta di invio del modulo. La cosa migliore è mettere il bean nell'area di visualizzazione di @ViewScoped
.
Associa invece il valore datatable DataModel<E>
che a sua volta avvolge gli elementi.
<h:dataTable value="#{bean.model}" var="item">
con
private transient DataModel<Item> model;
public DataModel<Item> getModel() {
if (model == null) {
model = new ListDataModel<Item>(items);
}
return model;
}
( transient
crearlo e istanziarlo pigramente nel getter è obbligatorio quando lo si utilizza su una vista o un bean con ambito di sessione poiché DataModel
non implementa Serializable
)
Quindi sarai in grado di accedere alla riga corrente DataModel#getRowData()
senza passare nulla (JSF determina la riga in base al nome del parametro di richiesta del link / pulsante di comando cliccato).
public void insert() {
Item item = model.getRowData();
Long id = item.getId();
// ...
}
Ciò richiede anche che il modello di dati venga conservato per la richiesta di invio del modulo. La cosa migliore è mettere il bean nell'area di visualizzazione di @ViewScoped
.
Utilizzare Application#evaluateExpressionGet()
per valutare a livello di codice la corrente #{item}
.
public void insert() {
FacesContext context = FacesContext.getCurrentInstance();
Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
Long id = item.getId();
// ...
}
Quale modo scegliere dipende dai requisiti funzionali e se l'uno o l'altro offre più vantaggi per altri scopi. Personalmente andrei avanti con il numero 1 o, quando desideri supportare anche i contenitori servlet 2.5, con il numero 2.