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


99

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속성이 렌더링 될 때 행 변수 를 사용할 수 없습니다 (고정 값을 사용할 때 작동합니다).

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

답변:


215

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

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

  1. servletcontainer가 최소 Servlet 3.0 / EL 2.2를 지원하는 경우 UICommand 컴포넌트 또는 AjaxBehavior태그 의 action / listener 메소드의 인수로 전달하십시오 . 예

     <h:commandLink action="#{bean.insert(item.id)}" value="insert" />

    다음과 함께 사용 :

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

    이는 양식 제출 요청에 대해 데이터 모델을 보존하기 만하면됩니다. 가장 좋은 방법은 뷰 범위에 빈을 넣는 것 @ViewScoped입니다.

    전체 항목 개체를 전달할 수도 있습니다.

     <h:commandLink action="#{bean.insert(item)}" value="insert" />

    와:

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

    Servlet 2.5 컨테이너에서는 JBoss EL과 같이이를 지원하는 EL 구현을 제공하는 경우에도 가능합니다. 구성 세부 정보는 이 답변을 참조하십시오 .


  2. 사용 <f:param>UICommand구성 요소입니다. 요청 매개 변수를 추가합니다.

     <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" />

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


  3. 사용 <f:setPropertyActionListener>UICommand구성 요소입니다. 장점은 Bean이 요청 범위보다 더 넓은 범위를 가질 때 요청 매개 변수 맵에 액세스 할 필요가 없다는 것입니다.

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

    와 함께

     private Long id; // +setter

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


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

    (이를 구현하지 않기 transient때문에 뷰 또는 세션 범위 빈에서 이것을 사용할 때 getter에서 그것을 만들고 느리게 인스턴스화하는 것은 필수입니다 )DataModelSerializable

    그런 다음 DataModel#getRowData()아무 것도 전달하지 않고 현재 행에 액세스 할 수 있습니다 (JSF는 클릭 한 명령 링크 / 버튼의 요청 매개 변수 이름에 따라 행을 결정합니다).

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

    또한 양식 제출 요청을 위해 데이터 모델이 보존되어야합니다. 가장 좋은 방법은 뷰 범위에 빈을 넣는 것 @ViewScoped입니다.


  5. 사용 Application#evaluateExpressionGet()하는 프로그래밍 전류를 평가 #{item}.

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

선택하는 방법은 기능 요구 사항과 둘 중 하나가 다른 목적을 위해 더 많은 이점을 제공하는지 여부에 따라 다릅니다. 개인적으로 # 1 또는 서블릿 2.5 컨테이너도 지원하려면 # 2로 진행하겠습니다.


1
+1, 내 선호도는 # 2 (2.5를 지원해야하는 경우)로 이동합니다.
Bozho

철저한 답변 주셔서 감사합니다. 불행히도 나는 # 1이 필터링 된 프라임 페이스 데이터 테이블에서 작동했던 유일한 것이라고보고해야합니다 (정확히 필요한 시나리오입니다). 나머지는 모두 필터링되지 않은 테이블에서만 작업했습니다. 나는 이것이 당신의 대답보다 프라임 페이스의 버그로 더 많이 봅니다.
Michael Borgwardt

Bean 요청 또는보기 범위가 있습니까?
BalusC

2
"필터링 됨"이란 이 쇼케이스 예제 에서와 같이 의미 합니까? 증상은 필터 동작이 클라이언트 측에서만 발생하고 서버 측의 모델이 유지되지 않음을 나타냅니다. 이것이 의도적 인 것인지 확실하지 않습니다. 언제든지 문제 보고서를 남길 수 있습니다.
BalusC

귀하의 게시물은 내가 읽은 가장 유용한 게시물 사이에 있습니다. 서블릿 2.5를 사용해야했기 때문에 방법 5를 사용했습니다. 내 질문은 이제 commandLink (예제와 같이)를 사용하여 매개 변수를 보낼 수 있지만 ajax를 사용하는 것입니까?
Aditzu

11

JSF 1.2에서 이것은 <f:setPropertyActionListener>(명령 구성 요소 내에서)에 의해 수행되었습니다 . JSF 2.0 (BalusC 덕분에 정확히 EL 2.2)에서는 다음과 같이 할 수 있습니다.action="${filterList.insert(f.id)}


6
이 기능은 JSF 2.0 (서블릿 2.5 컨테이너에서 자체적으로 실행될 수 있음)이 아니라 EL 2.2 (서블릿 3.0의 일부)에만 해당됩니다.
BalusC

11

내보기 페이지에서 :

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

백킹 콩

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

-1

Mkyong의이 사이트 덕분에 실제로 우리가 매개 변수를 전달하는 데 도움 이 된 유일한 솔루션 은 다음과 같습니다.

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

public String editAction() {

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

기술적으로는 메서드 자체에 직접 전달할 수 없지만 JSF request parameter map.


1
여기에서 묻는 것과 다른 문제가 있습니다. #{param}임의의 매개 변수를 전달하지 않고 후속 요청을 위해 맵의 요청 매개 변수를 유지하려고합니다 . 귀하의 Q & A에 의해 덮여있다 stackoverflow.com/questions/17734230
BalusC
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.