Como posso passar a linha selecionada para commandLink dentro de dataTable ou ui: repeat?

Estou usando o Primefaces em um aplicativo JSF 2. Eu tenho um

e, em vez de selecionar linhas, quero que o usuário possa executar diretamente várias ações em linhas individuais. Para isso, tenho vários

s na última coluna.

Meu problema: como posso passar um ID de linha para a ação iniciada pelo link de comando para que eu saiba em qual linha atuar? Eu tentei usar um :

 

...

Mas sempre produz 0 – aparentemente, a variável de linha f não está disponível quando o atributo é renderizado (funciona quando eu uso um valor fixo).

Alguém tem uma solução alternativa?

Quanto à causa, o é específico para o próprio componente (preenchido durante o tempo de criação da visualização), não para a linha iterada (preenchida durante o tempo de renderização da visualização).

Existem várias maneiras de atingir o requisito.

  1. Use lugar. Adiciona um parâmetro de solicitação.

        

    Se o seu bean tiver o escopo da solicitação, deixe o JSF configurá-lo por @ManagedProperty

     @ManagedProperty(value="#{param.id}") private Long id; // +setter 

    Ou se o seu bean tiver um escopo mais amplo ou se você quiser uma validação / conversão mais refinada, use na visualização de destino, veja também f: viewParam vs @ManagedProperty :

      

    De qualquer forma, isso tem a vantagem de que o modelo de dados não precisa necessariamente ser preservado para o formulário de envio (para o caso em que seu bean está com escopo de pedido).


  2. Use lugar. A vantagem é que isso elimina a necessidade de acessar o mapa do parâmetro de solicitação quando o bean possui um escopo mais amplo que o escopo da solicitação.

        

    Em combinação com

     private Long id; // +setter 

    Ele estará disponível apenas pelo id propriedade 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 da visão por @ViewScoped .


  3. Se o seu servletcontainer suporta Servlet 3.0 / EL 2.2, então apenas passe como argumento de método. 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 da visão por @ViewScoped .

      

    Em combinação com:

     public void insert(Long id) { // ... } 

    Você pode até passar todo o object do item:

      

    com:

     public void insert(Item item) { // ... } 

    Nos contêineres Servlet 2.5, isso também é possível se você fornecer uma implementação EL que suporte isso, como o JBoss EL. Para detalhes de configuração, veja esta resposta .


  4. Vincule o valor da tabela de dados a DataModel que, por sua vez, DataModel os itens.

      

    com

     private transient DataModel model; public DataModel getModel() { if (model == null) { model = new ListDataModel(items); } return model; } 

    (torná-lo transient e preguiçoso instanciando-o no getter é obrigatório quando você estiver usando isso em uma visão ou um bean com escopo de session, pois o DataModel não implementa Serializable )

    Em seguida, você poderá acessar a linha atual pelo DataModel#getRowData() sem passar nada ao redor (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 da visão por @ViewScoped .


  5. Você pode usar o Application#evaluateExpressionGet() para avaliar programaticamente o #{item} atual.

     public void insert() { FacesContext context = FacesContext.getCurrentInstance(); Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class); Long id = item.getId(); // ... } 

Qual a maneira de escolher depende dos requisitos funcionais e se um ou outro oferece mais vantagens para outros fins. Eu pessoalmente iria em frente com # 3 ou, quando você gostaria de apoiar os contêineres servlet 2.5 também, com # 2.

No JSF 1.2 isso foi feito por (dentro do componente de comando). No JSF 2.0 (EL 2.2 para ser preciso, graças ao BalusC) é possível fazer assim: action="${filterList.insert(f.id)}

Na minha página de visualização:

         

feijão de apoio

  public void viewDetail(ActionEvent e) { String trxNo = getFacesContext().getRequestParameterMap().get("trxNo"); for (DTO item : list) { if (item.get("trxNo").toString().equals(trxNo)) { System.out.println(trxNo); setSelectedItem(item); break; } } } 

Graças a este site por Mkyong , a única solução que realmente funcionou para nós para passar um parâmetro foi este

    

com

 public String editAction() { Map params = FacesContext.getExternalContext().getRequestParameterMap(); String idString = params.get("myId"); long id = Long.parseLong(idString); ... } 

Tecnicamente, você não pode passar diretamente para o método em si, mas para o JSF request parameter map do JSF request parameter map .