0

私は<p:dataTable>セル内編集を使用しています。それぞれに 2 つの列があり、<h:selectOneMenu>さらに 3 番目の編集列があります。2 番目<h:selectOneMenu>は、最初の での選択に依存し<h:selectOneMenu>ます。行が入力/編集モードの場合、最初の値を変更する<h:selectOneMenu>と2番目のリストが更新され、2番目<h:selectoneMenu>の値を引き続き変更して行の変更を保存できるはずです。

私の問題は、最初の値<h:selectOneMenu>が変更された場合、2 番目のリストは正しく更新されますが、列<p:selectOneMenu>のチェック アイコン (変更を保存) をクリックしても何も起こらず、行は編集モードのままです。<p:rowEditor>バッキング Bean の RowEditEvent リスナーも (明らかに) 呼び出されません。ただし、閉じるアイコンをクリックして行を出力モードに戻すことはできますが、何も保存されません。

<h:selectOneMenu>最初の の値を変更せずに 2 番目の値のみを変更すると、<h:selectOneMenu>変更の保存に問題はありません。

以下はコード スニペットであり、簡略化されており、何日にもわたってコードをテストしているため、まだ「ダーティ」です。

xhtml:

<h:form id="dataListForm">
<p:dataTable id="dataTable" value="#{bean.rdcList}" var="rdc" >
    <p:ajax event="rowEdit" listener="#{bean.onRowEdit}" />
    <f:facet name="header">
        Data List
    </f:facet>
    <p:column headerText="Agency">
        <p:cellEditor>
            <f:facet name="output">
                <h:outputText value="#{rdc.agency.descr}" />
            </f:facet>
            <f:facet name="input">
                <h:selectOneMenu value="#{rdc.agency.id}" valueChangeListener="#{bean.agChanged}">
                    <f:selectItems value="#{bean.agenciestab}" var="ag" itemValue="#{ag.id}" itemLabel="#{ag}" />
                    <p:ajax event="change" update="zoneSelect" />
                </h:selectOneMenu>
            </f:facet>
        </p:cellEditor>
    </p:column>
    <p:column headerText="Zone">
        <p:cellEditor>
            <f:facet name="output">
                <h:outputText value="#{rdc.zone.id} - #{rdc.zone.name}" />
            </f:facet>
            <f:facet name="input">
                <h:selectOneMenu id="zoneSelect" value="#{rdc.zone.id}" valueChangeListener="#{bean.zChanged}">
                    <f:selectItems value="#{bean.zonestab}" var="z" itemValue="#{z.id}" itemLabel="#{z}" />
                </h:selectOneMenu>
            </f:facet>
        </p:cellEditor>
    </p:column>
    <p:column headerText="Edit">
        <p:rowEditor />
    </p:column>
</p:dataTable>

bean:

@ManagedBean(name = "bean")
@SessionScoped

public class Bean implements Serializable {
.
.
/* Init */
@PostConstruct
public void init() {
    aChanged = false;
    zChanged = false;
    edited = false;
    agenciestab = new ArrayList<SelectItem>();
    for (Agency agency : agencyDao.all()) {
        agenciestab.add(new SelectItem(agency.getId(), agency.getDescr()));
    }
}

/* Listeners */
public void agChanged(ValueChangeEvent event) {
    aChanged = true;
    selectedAgency = agencyDao.get(Integer.valueOf(event.getNewValue()
            .toString()));
    zonestab = new ArrayList<SelectItem>();
    if (selectedAgency != null) {
        for (Zone zone : zoneDao.getByDistrict(selectedAgency.getDistrict())) {
            zonestab.add(new SelectItem(zone.getId(), zone.getZone()+ " - " + zone.getName()));
        }
    } else {
        for (Zone zone : zoneDao.getByDistrict(rdcList.getRowData().getAgency().getDistrict())) {
            zonestab.add(new SelectItem(zone.getId(), zone.getZone()+ " - " + zone.getName()));
        }
    }
}

public void zChanged(ValueChangeEvent event) {
    zChanged = true;
    selectedZone = zoneDao.get(Integer.valueOf(event.getNewValue().toString()));
}

public void onRowEdit(RowEditEvent event) {
    edited = true;
    Rdc rdc = (Rdc) event.getObject();
    if (aChanged) {
        rdc.setAgency(selectedAgency);
        aChanged = false;
    }
    if (zChanged) {
        rdc.setZone(selectedZone);
        zChanged = false;
    }
    try {
        rdcDao.saveOrUpdate(rdc);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/* Getters & Setters */
public DataModel<Rdc> getRdcList() {
    if (rdcList == null) {
        rdcList = new ListDataModel<Rdc>(rdcDao.getBatchRdc(batchBean.getCurBatch().getId()));
    } else {
        rdcList.setRowIndex(0);
        if (rdcList.isRowAvailable() && rdcList.getRowData().getBatch().getId().equals(batchBean.getCurBatch().getId())) {
            if (edited) {
                edited = false;
                rdcList = new ListDataModel<Rdc>(
                        rdcDao.getBatchRdc(batchBean.getCurBatch().getId()));
            }
        } else {
            rdcList = new ListDataModel<Rdc>(rdcDao.getBatchRdc(batchBean.getCurBatch().getId()));
        }
    }
    return rdcList;
}

public void setRdcList(DataModel<Rdc> rdcList) {
    this.rdcList = rdcList;
}

public ArrayList<SelectItem> getAgenciestab() {
    return agenciestab;
}

public void setAgenciestab(ArrayList<SelectItem> agenciestab) {
    this.agenciestab = agenciestab;
}

public ArrayList<SelectItem> getZonestab() {
    zonestab = new ArrayList<SelectItem>();
    if (aChanged && selectedAgency != null) {
        for (Zone zone : zoneDao.getByDistrict(selectedAgency.getDistrict())) {
            zonestab.add(new SelectItem(zone.getId(), zone.getZone()+ " - " + zone.getName()));
        }
    } else if (!aChanged) {
        for (Zone zone : zoneDao.getByDistrict(rdcList.getRowData().getAgency().getDistrict())) {
            zonestab.add(new SelectItem(zone.getId(), zone.getZone()+ " - " + zone.getName()));
        }
    }

    return zonestab;
}

public void setZonestab(ArrayList<SelectItem> zonestab) {
    this.zonestab = zonestab;
}
/* other getters & setters */
}

私はprimefaces-3.1.1、mojarra-2.1.3-FCS、およびTomcat 7.0.26を使用しています

私はどこで間違ったのですか?そして、私が達成しようとしていることを達成するためのよりクリーンでより良い方法はありますか?

4

1 に答える 1

2

ゲッター メソッドでビジネス ロジックを実行しています。特定のケースでは、データテーブルのゲッターが呼び出されるたびに、データテーブルの行インデックスを 0 に設定しています。これが、具体的な問題の根本的な原因である可能性が最も高いです。このようにして、JSF は最初の行以外の行で実行されたアクションを見つけることができなくなります。ゲッター メソッドでビジネス ロジックを実行することは絶対に避けてください。ゲッター メソッドは、EL が式を評価する必要があるたびに呼び出されます。これは、適度なサイズのデータ​​ テーブルで数百回に及ぶ可能性があります。

ゲッター メソッドは、データのみを返すように設計する必要があります。

public List<Rdc> getRdcList() {
    return rdcList;
}

ビジネス ロジックは、代わりに (アクション) リスナー メソッドの (ポスト) コンストラクターで実行する必要があります。初回の初期化は (ポスト) コンストラクターで行い、エンドユーザー (ajax) アクションに基づく 1 回限りの変更は (アクション) リスナー メソッドで行う必要があります。極端なケースでは、最大の遅延読み込みを使用する必要があります。

以下も参照してください。


具体的な問題とは関係valueChangeListenerありませんが、目的に適したツールではありません。むしろ使用して<p:ajax listener="#{bean.changed}">ください。モデルは、その時点で送信された値ですでに更新されています。

于 2012-06-19T13:49:25.440 に答える