programing tip

선택한 행을 dataTable 또는 ui : repeat 내의 commandLink에 어떻게 전달할 수 있습니까?

itbloger 2020. 8. 23. 08:37
반응형

선택한 행을 dataTable 또는 ui : repeat 내의 commandLink에 어떻게 전달할 수 있습니까?


JSF 2 응용 프로그램에서 Primefaces를 사용하고 있습니다. 나는을 가지고 있으며 <p:dataTable>행을 선택하는 대신 사용자가 개별 행에서 다양한 작업을 직접 실행할 수 있기를 원합니다. 이를 위해 <p:commandLink>마지막 열에 여러 개의 s가 있습니다.

내 문제 : 명령 링크로 시작된 작업에 행 ID를 전달하여 작업 할 행을 어떻게 알 수 있습니까? 나는 사용을 시도했다 <f:attribute>:

<p:dataTable value="#{bean.items}" var="item">
    ...
    <p:column>
        <p:commandLink actionListener="#{bean.insert}" value="insert">
            <f:attribute name="id" value="#{item.id}" />
        </p:commandLink>
    </p:column>
</p:dataTable>

그러나 그것은 항상 0을 산출합니다-분명히 f속성이 렌더링 될 때 행 변수 를 사용할 수 없습니다 (고정 값을 사용할 때 작동합니다).

누구든지 대체 솔루션이 있습니까?


원인 <f:attribute>에 관해서는는 반복 된 행 (보기 렌더링 시간 동안 채워짐)이 아니라 구성 요소 자체 (보기 빌드 시간 동안 채워짐)에 고유합니다.

요구 사항을 달성하는 방법에는 여러 가지가 있습니다.

  1. <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 대 @ManagedProperty 도 참조하십시오 .

    <f:viewParam name="id" value="#{bean.id}" required="true" />
    

    어느 쪽이든, 이것은 양식 제출을 위해 데이터 모델을 반드시 보존 할 필요가 없다는 장점이 있습니다 (빈이 요청 범위 인 경우).


  2. <f:setPropertyActionListener>대신 사용하십시오 . 장점은 Bean이 요청 범위보다 더 넓은 범위를 가질 때 요청 매개 변수 맵에 액세스 할 필요가 없다는 것입니다.

    <h:commandLink action="#{bean.insert}" value="insert">
        <f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
    </h:commandLink>
    

    와 함께

    private Long id; // +setter
    

    속성 id에서 행동 방식 으로 만 사용할 수 있습니다 . 이는 양식 제출 요청에 대해 데이터 모델을 보존하기 만하면됩니다. 가장 좋은 방법은 뷰 범위에 빈을 넣는 것 @ViewScoped입니다.


  3. servletcontainer가 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 컨테이너에서는 JBoss EL과 같이이를 지원하는 EL 구현을 제공하는 경우에도 가능합니다. 구성 세부 정보는 이 답변을 참조하십시오 .


  4. 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;
    }
    

    (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. You can 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 #3 or, when you'd like to support servlet 2.5 containers as well, with #2.


In JSF 1.2 this was done by <f:setPropertyActionListener> (within the command component). In JSF 2.0 (EL 2.2 to be precise, thanks to BalusC) it's possible to do it like this: action="${filterList.insert(f.id)}


In my view page:

<p:dataTable  ...>
<p:column>
<p:commandLink actionListener="#{inquirySOController.viewDetail}" 
               process="@this" update=":mainform:dialog_content"
           oncomplete="dlg2.show()">
    <h:graphicImage library="images" name="view.png"/>
    <f:param name="trxNo" value="#{item.map['trxNo']}"/>
</p:commandLink>
</p:column>
</p:dataTable>

backing bean

 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;
        }
    }
}

Thanks to this site by Mkyong, the only solution that actually worked for us to pass a parameter was this

<h:commandLink action="#{user.editAction}">
    <f:param name="myId" value="#{param.id}" />
</h:commandLink>

with

public String editAction() {

  Map<String,String> params = 
            FacesContext.getExternalContext().getRequestParameterMap();
  String idString = params.get("myId");
  long id = Long.parseLong(idString);
  ...
}

Technically, that you cannot pass to the method itself directly, but to the JSF request parameter map.

참고URL : https://stackoverflow.com/questions/4994458/how-can-i-pass-selected-row-to-commandlink-inside-datatable-or-uirepeat

반응형