How can I pass selected row to commandLink inside dataTable or ui:repeat?

前端 未结 4 1810
情话喂你
情话喂你 2020-11-21 06:29

I\'m using Primefaces in a JSF 2 application. I have a , and instead of selecting rows, I want the user to be able to directly execute variou

4条回答
  •  情歌与酒
    2020-11-21 07:03

    As to the cause, the is specific to the component itself (populated during view build time), not to the iterated row (populated during view render time).

    There are several ways to achieve the requirement.

    1. If your servletcontainer supports a minimum of Servlet 3.0 / EL 2.2, then just pass it as an argument of action/listener method of UICommand component or AjaxBehavior tag. E.g.

       
      

      In combination with:

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

      This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by @ViewScoped.

      You can even pass the entire item object:

       
      

      with:

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

      On Servlet 2.5 containers, this is also possible if you supply an EL implementation which supports this, like as JBoss EL. For configuration detail, see this answer.


    2. Use in UICommand component. It adds a request parameter.

       
           
       
      

      If your bean is request scoped, let JSF set it by @ManagedProperty

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

      Or if your bean has a broader scope or if you want more fine grained validation/conversion, use on the target view, see also f:viewParam vs @ManagedProperty:

       
      

      Either way, this has the advantage that the datamodel doesn't necessarily need to be preserved for the form submit (for the case that your bean is request scoped).


    3. Use in UICommand component. The advantage is that this removes the need for accessing the request parameter map when the bean has a broader scope than the request scope.

       
           
       
      

      In combination with

       private Long id; // +setter
      

      It'll be just available by property id in action method. This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by @ViewScoped.


    4. Bind the datatable value to DataModel instead which in turn wraps the items.

       
      

      with

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

      (making it transient and lazily instantiating it in the getter is mandatory when you're using this on a view or session scoped bean since DataModel doesn't implement Serializable)

      Then you'll be able to access the current row by DataModel#getRowData() without passing anything around (JSF determines the row based on the request parameter name of the clicked command link/button).

       public void insert() {
           Item item = model.getRowData();
           Long id = item.getId();
           // ...
       }
      

      This also requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by @ViewScoped.


    5. Use Application#evaluateExpressionGet() to programmatically evaluate the current #{item}.

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

    Which way to choose depends on the functional requirements and whether the one or the other offers more advantages for other purposes. I personally would go ahead with #1 or, when you'd like to support servlet 2.5 containers as well, with #2.

提交回复
热议问题