2014-02-12 62 views
5

我已經閱讀了大量關於在自定義控件中動態綁定字段的優秀帖子和文章,但他們都假設了文檔數據源。將自定義控件中的編輯框動態綁定到託管bean

我想允許管理bean數據源的可能性。我試過屬性類型設置爲com.ibm.xsp.model.DataSourcecom.ibm.xsp.extlib.model.ObjectDataSource既不具有以下XML的工作:

<xp:inputText 
    id="input" 
    value="${compositeData.dsn[compositeData.fieldName]}" 
> 
</xp:inputText> 

在使用控制我已經通過了在自定義的數據,像這樣:

<xc:input 
    dsn="#{issue}" 
    fieldName="Database" 
> 
</xc:input> 

對於我測試目的,我有一個名爲issue的託管bean,我打電話給我的字段Database。我通常會綁定到#{issue.Database},但我無法弄清楚如何動態地做到這一點。理想情況下,我也想支持文檔數據源,但是如果我不能這樣做,那麼我需要綁定到託管bean。

編輯:問題似乎是數組符號。如果我硬編碼我的價值#{issue.Database}它的作品,但如果我硬編碼到它失敗。所以問題是如果有一個替代表示符號。我今天沒有時間,但是我想知道是不是將dsn和fieldName分開,如果我只是將#{issue}傳入dsn並使用它作爲我的數據綁定可以工作?當我有機會時,我會嘗試。

Edit2:因爲它看起來問題可能與我正在使用的bean有關,所以我會在這裏發佈代碼。

AbstractMapModel

public abstract class AbstractMapModel implements Serializable, DataObject { 
    private static final long serialVersionUID = 1L; 
    private Map<Object, Object> values; 

    public Class<?> getType(final Object key) { 
     Class<?> result = null; 
     if (getValues().containsKey(key)) { 
      Object value = getValues().get(key); 
      if (value != null) { 
       result = value.getClass(); 
      } 
     } 
     return result; 
    } 

    protected Map<Object, Object> getValues() { 
     if (values == null) { 
      values = new HashMap<Object, Object>(); 
     } 
     return values; 
    } 

    public Object getValue(final Object key) { 
     return getValues().get(key); 
    } 

    public boolean isReadOnly(final Object key) { 
     return false; 
    } 

    public void setValue(final Object key, final Object value) { 
     getValues().put(key, value); 
    } 
} 

AbstractDocumentMapModel

public abstract class AbstractDocumentMapModel extends AbstractMapModel { 
private static final long serialVersionUID = 1L; 
private String unid; 

public AbstractDocumentMapModel() { 
    String documentId = ExtLibUtil.readParameter(FacesContext 
      .getCurrentInstance(), "id"); 
    if (StringUtil.isNotEmpty(documentId)) { 
     load(documentId); 
    } 
} 

protected abstract String getFormName(); 

public String getUnid() { 
    return unid; 
} 

public void setUnid(String unid) { 
    this.unid = unid; 
} 

public void load(final String unid) { 
    setUnid(unid); 
    Document doc = null; 
    try { 
     if (StringUtil.isNotEmpty(getUnid())) { 
      doc = ExtLibUtil.getCurrentDatabase().getDocumentByUNID(
        getUnid()); 
      DominoDocument wrappedDoc = DominoDocument.wrap(doc 
        .getParentDatabase().getFilePath(), // databaseName 
        doc, // Document 
        null, // computeWithForm 
        null, // concurrencyMode 
        false, // allowDeleteDocs 
        null, // saveLinksAs 
        null // webQuerySaveAgent 
        ); 
      for (Object eachItem : doc.getItems()) { 
       if (eachItem instanceof Item) { 
        Item item = (Item) eachItem; 
        String itemName = item.getName(); 
        if (!("$UpdatedBy".equalsIgnoreCase(itemName) || "$Revisions" 
          .equalsIgnoreCase(itemName))) { 
         setValue(item.getName(), wrappedDoc.getValue(item 
           .getName())); 
        } 
        DominoUtil.incinerate(eachItem); 
       } 
      } 
     } 
    } catch (Throwable t) { 
     t.printStackTrace(); 
    } finally { 
     DominoUtil.incinerate(doc); 
    } 
} 

protected boolean postSave() { 
    return true; 
} 

protected boolean querySave() { 
    return true; 
} 

public boolean save() { 
    boolean result = false; 
    if (querySave()) { 
     Document doc = null; 
     try { 
      if (StringUtil.isEmpty(getUnid())) { 
       doc = ExtLibUtil.getCurrentDatabase().createDocument(); 
       setUnid(doc.getUniversalID()); 
       doc.replaceItemValue("Form", getFormName()); 
      } else { 
       doc = ExtLibUtil.getCurrentDatabase().getDocumentByUNID(
         getUnid()); 
      } 
      for (Entry<Object, Object> entry : getValues().entrySet()) { 
       String itemName = entry.getKey().toString(); 
       doc.replaceItemValue(itemName, DominoUtil 
         .toDominoFriendly(entry.getValue())); 
      } 
      if (doc.save()) { 
       result = postSave(); 
      } 
     } catch (Throwable t) { 
      t.printStackTrace(); 
     } finally { 
      DominoUtil.incinerate(doc); 
     } 
    } 
    return result; 
} 

}

IssueModel

public class IssueModel extends AbstractDocumentMapModel implements 
    Serializable { 
private static final long serialVersionUID = 1L; 

@Override 
protected String getFormName() { 
    return "frmIssue"; 
} 

@Override 
protected boolean querySave() { 
    return super.querySave(); 
} 

@Override 
public boolean isReadOnly(final Object key) { 
    boolean result = super.isReadOnly(key); 
    /** 
    * Implement read only logic here as follows 
    * 
    * if ("jobTitle".equalsIgnoreCase((String) key)) { if 
    * (!ExtLibUtil.getXspContext().getUser().getRoles().contains("[HR]")) { 
    * result = true; } } 
    */ 
    return result; 
} 

}

ccFieldset

<?xml version="1.0" encoding="UTF-8"?> 
<xp:view 
    xmlns:xp="http://www.ibm.com/xsp/core" 
> 
    <div 
     class="form-group" 
    > 
     <xp:label 
      id="label" 
      for="input" 
      value="${compositeData.label.text}" 
     > 
      <xp:this.styleClass><![CDATA[${javascript:styleClass = "control-label col-" + compositeData.sz + "-" + compositeData.label.columns; 
return styleClass;}]]></xp:this.styleClass> 
     </xp:label> 
     <xp:div> 
      <xp:this.styleClass><![CDATA[${javascript:styleClass = "col-" + compositeData.sz + "-" + compositeData.input.columns; 
return styleClass;}]]></xp:this.styleClass> 
      <xp:inputText 
       id="input" 
      > 
       <xp:this.value><![CDATA[${javascript:"#{"+compositeData.BindTo+"}"}]]></xp:this.value> 
       <xp:this.styleClass><![CDATA[${javascript:styleClass = "input-" + compositeData.sz; 
return styleClass;}]]></xp:this.styleClass> 
      </xp:inputText> 
     </xp:div> 
    </div> 
</xp:view> 

中的XPage工作領域中的XPage

  <div 
      class="form-group" 
     > 
      <xp:label 
       value="Database" 
       id="database_Label1" 
       for="database1" 
       styleClass="col-sm-2 control-label" 
      > 
      </xp:label> 
      <div 
       class="col-sm-6" 
      > 
       <xp:inputText 
        value="#{issue.Database}" 
        id="database1" 
        styleClass="input-sm" 
       > 
       </xp:inputText> 
      </div> 
     </div> 

不工作ccFieldset

  <xc:fieldset sz="md"> 
       <xc:this.input> 
        <xc:input 
         columns="10" 
         bindTo="issue.Database" 
        > 
        </xc:input> 
       </xc:this.input> 
       <xc:this.label> 
        <xc:label 
         columns="2" 
         text="test" 
        > 
        </xc:label> 
       </xc:this.label> 
      </xc:fieldset> 
+0

我從來沒有嘗試過你正在嘗試的,但我建議你嘗試使用「高級」下的自定義綁定。您也可以先嚐試將compositeDate設置爲作用域變量,然後嘗試動態綁定該元素。 –

+1

如果你有一個具有getters和setter的普通Java bean,那麼fieldName必須是「數據庫」。它不適用於大寫字母作爲第一個字符。在我的測試中,我不得不在「value =」$ {compositeData.dsn [compositeData.fieldName]}「'行中使用」#「而不是」$「。但是,這兩個變化你的代碼爲我工作。 –

+1

我已經在自定義控件中使用動態綁定,沒有任何問題使用這種語法:'value =「#{compositeData.dataSource [compositeData.fieldName]}」'。有關示例,請參閱此處:http://bootstrap4xpages.com/bs4xp/demos.nsf/reusableFields.xsp。順便說一句:我永遠不會打電話給我的字段名稱「數據庫」,因爲還有一個叫做'database'的全局SSJS對象。理論上它可以工作,但我喜歡保持安全。 –

回答

8

訣竅是交出一個字符串作爲參數,這將是你想要使用的EL。比方說,你有一個參數bindTo爲字符串值myBean.Color

<xp:this.value><![CDATA[${javascript:"#{"+compositeData.BindTo+"}"}]]></xp:this.value> 

的$將評估第一和實際值替換的CompositeData。方法之美:適用於任何EL。文檔Bean等,所以你的自定義控件不需要對其容器做任何假設。

所以,你可以打電話給你的組件與各種綁定:

<xc:myComponent BindTo="document1.subject"></xc:myComponent> 
<xc:myComponent BindTo="viewScope.someVariable"></xc:myComponent> 
<xc:myComponent BindTo="myBean.Color"></xc:myComponent> 

讓我們知道如何爲你工作!

+0

謝謝你的回覆。必須有一些中間步驟我做錯了。它似乎計算爲空 - 該字段是不可編輯的並且未填充。 –

+0

添加顯示您參數的計算字段,以便您瞭解是否有效。並更新問題以添加您當前的代碼嘗試。 – stwissel

+0

你的參數值是多少? – stwissel

3

確保下列之一是關於你傳遞到自定義控制對象真:

  1. 這真的是一個bean(具體如下bean conventions)。例如,如果您將綁定到database屬性,則該對象應具有(至少)getDatabase方法,該方法返回database屬性的當前值;如果該屬性不是隻讀的,則該類還應該有一個接受新值的方法setDatabase
  2. 這是一個DataObject:你的對象實現了com.ibm.xsp.model.DataObject接口。通用getValuesetValue方法此接口需要您執行的方法將分別用於檢索和更新任何屬性的值,包括database
  3. 這是一個Map。您綁定的任何屬性名稱將被視爲地圖的關鍵字。
  4. 這是com.ibm.jscript.types.FBSObject的一個實例。這是所有SSJS對象文字({ })在運行時解析SSJS字符串時變成的基礎Java類。小心在託管的bean中使用此類型,因爲這些對象不是serializable

只要傳入的對象是這四個中的一個,問題中列出的EL語法就會有效。將屬性類型設置爲要傳遞的對象的實際類名稱或其擴展的基類(或實現的接口)。或者,爲確保它可以接受任何內容,只需將屬性類型設置爲object即可。

但是請記住,在faces-config.xml中聲明一個類作爲託管bean只能「管理」一個變量名和範圍......此聲明實際上並不會使您的Java類成爲一個bean。除非它符合bean conventions,否則它不是一個bean。如果確實符合bean約定,那麼它就是一個bean,不管你是否聲明它是一個被管理的 bean。這種區別是XPages社區中混淆不清的一個原因,所以我只是想在這個背景下重新評論一下。

+1

我的bean基本上是NotesIn9演示文稿中的一條直線,所以它符合1,2和3.您將認識到'AbstractDocumentMapModel'。所以我已經將我的類型設置爲' .AbstractDocumentMapModel',並且由於在編譯時我這樣做了錯誤_Unknown屬性dsn。它沒有在標籤xc上定義:input_ –

+0

按照您的建議將類型更改爲'object'修復了錯誤,但實際上並沒有將編輯框綁定到我的bean。 –

相關問題