2013-08-07 45 views
1

我想在掛毯做以下工作。掛毯更新從AJAX編輯網格的DAO

我有一個Dictionary<String, Dictionary<String, Object>>其中包含我的數據。

我想完成,我有1個下拉菜單(選擇組件),其中包含外鍵字典的鍵。

當選擇發生變化時,應該使用所選子字典中的鍵和值更新網格。

例如:

Dictionary<String, Dictionary<String, Object>> dictionaries = new Hashtable<String, Dictionary<String, Object>>(); 

Dictionary<String, Object> dict1 = new Hashtable<String, Object>(); 
Dictionary<String, Object> dict2 = new Hashtable<String, Object>(); 

dict1.put("k1", "d1v1"); 
dict1.put("k2", "d1v2"); 

dict2.put("k1", "d2v1"); 
dict2.put("k2", "d2v2"); 

dictionaries.put("d1", dict1); 
dictionaries.put("d2", dict2); 

會有人會這麼好心給我一個例子或推我朝着正確的方向嗎?

編輯:

我設法拿到了第一部分工作,與網格內容進行改變,這取決於從外部字典的鍵選擇。

不過,我我在與更新網格和保存更改問題:

我用我自己的GridDataSource:

public class EntityDataSource<T> implements GridDataSource { 

    private Class<T> persistentClass; 

    protected List<T> data; 
    protected int count = -1; 
    protected int startIndex = 0; 


    public EntityDataSource(Class<T> persistentClass, List<T> data) { 
     this.persistentClass = persistentClass; 
     this.data = data; 
    } 

    public static final <T> EntityDataSource<T> create(
      Class<T> persistentClass, List<T> data) { 
     return new EntityDataSource<T>(persistentClass, data); 
    } 

    public int getAvailableRows() { 
     return this.data.size(); 
    } 

    public void prepare(int startIndex, int endIndex, 
      List<SortConstraint> sortConstraints) { 
     this.startIndex = startIndex; 
     this.data = this.data.subList(startIndex, endIndex + 1); 
    } 

    public Object getRowValue(int index) { 
     return this.data.get(index - this.startIndex); 
    } 

    @SuppressWarnings("rawtypes") 
    public Class getRowType() { 
     return this.persistentClass; 
    } 

} 

我的網格看起來是這樣的:

<t:form t:id="configSelectForm"> 
    <t:select t:id="storageKeySelecter" 
      t:model="storageKeyModel" 
      t:value="storageKey" 
      zone="configZone" /> 
</t:form> 

<t:zone t:id="configZone" id="configZone"> 
    <t:form t:id="configReviewForm"> 
     <table width="100%"> 
      <t:grid t:source="configurationEntrySource" 
        t:add="update, delete" 
        t:row="configurationEntry" 
        t:mixins="DisableGridSorting" 
        t:include="configKey, configValue" 
        t:encoder="configurationEntryEncoder"> 
       <p:configValueCell> 
        <input t:id="value" t:type="TextField" t:value="configurationEntry.configValue" 
          t:validate="required" t:context="configurationEntry.configValue" /> 
       </p:configValueCell> 

       <p:updateCell> 
        <t:actionlink t:id="update" zone="configZone" context="[configurationEntry.configKey, configurationEntry.configValue]">Update</t:actionlink> 
       </p:updateCell> 

       <p:deleteCell> 
        <t:actionlink t:id="delete" zone="configZone" context="configurationEntry.configKey">Delete</t:actionlink> 
       </p:deleteCell> 

      </t:grid> 
     </table> 
     <br></br> 
     <!-- <input type="submit" value="Update" class="button" /> --> 
    </t:form> 
</t:zone> 

我設法做出了一個刪除鏈接的工作,但是,我似乎無法更新任意鍵的值。

當我點擊更新的鏈接,從文本字段的值不是正在傳遞的一個:

public Object onActionFromUpdate(String configKey, String configValue) { 

    // my stuff here 

    return request.isXHR() ? configZone.getBody() : null; 
} 

的configValue是入門當前存在和價值不是我試圖改變它。

有沒有辦法獲得該值?我的網格有一個任意數量的行。

EDIT2:即使更多信息提供

這是我的TML:

<t:form t:id="configSelectForm"> 
    <t:select t:id="storageKeySelecter" 
      t:model="storageKeyModel" 
      t:value="storageKey" 
      zone="configZone" /> 
</t:form> 

<br/> 

<t:zone t:id="configZone" id="configZone" elementName="div"> 
    <form t:type="form" t:id="configReviewForm" id="configReviewForm" t:zone="configZone" zone="configZone"> 
     <table width="100%"> 
      <t:grid t:source="configurationEntries" 
        t:add="update, delete" 
        t:row="configurationEntry" 
        t:mixins="DisableGridSorting" 
        t:include="configKey, configValue" 
        t:encoder="configurationEntryEncoder" > 

       <p:configValueCell> 
        <input t:id="configValueTextField" t:type="TextField" t:value="configurationEntry.configValue" 
          t:validate="required" /> 
       </p:configValueCell> 

       <p:updateCell> 
        <t:actionlink id="update" t:id="update" zone="configZone" t:context="[configurationEntry.configKey, configurationEntry.configValue]">Update</t:actionlink> 
       </p:updateCell> 

       <p:deleteCell> 
        <t:actionlink id="delete" t:id="delete" zone="configZone" t:context="configurationEntry.configKey">Delete</t:actionlink> 
       </p:deleteCell> 

      </t:grid> 
     </table> 
     <br/> 
     <input type="submit" value="Update" class="button" zone="configZone"/> 
    </form> 
</t:zone> 

<br/> 
<br/> 

<t:form t:id="addNewEntryForm"> 
    <table width="100%"> 
     <tr> 
      <td> 
       <input t:id="newEntryKey" t:type="textfield" t:value="newEntry.configKey" 
         t:validate="required" t:context="newEntry.configKey" /> 
      </td> 

      <td> 
       <input t:id="newEntryValue" t:type="textfield" t:value="newEntry.configValue" 
         t:validate="required" t:context="newEntry.configValue" /> 
      </td> 

      <td> 
       <input type="submit" value="Add New Entry" zone="configZone"/> 
      </td> 
     </tr> 
    </table> 
</t:form> 

這是我的JAVA:

public class PropertyConfiguration { 

    @Inject 
    private BeanModelSource beanModelSource; 

    @Component 
    private Form configReviewForm; 

    @Property 
    private List<ConfigurationEntry> configurationEntries; 

    private List<ConfigurationEntry> persistentEntries; 

    @Property 
    private ConfigurationEntry configurationEntry = new ConfigurationEntry("", ""); 

    @Property 
    private ConfigurationEntryEncoder configurationEntryEncoder; 

    @InjectComponent 
    private Zone configZone; 

    @InjectComponent 
    private TextField configValueTextField; 

    @Inject 
    private ConfigurationPersitanceDAO dao; 

    private GridDataSource dataSource; 

    @Inject 
    private Messages messages; 

    @Property 
    private ConfigurationEntry newEntry; 

    @Inject 
    private Request request; 

    @Property 
    @Validate("required") 
    @Persist(PersistenceConstants.SESSION) 
    private String storageKey; 

    private StringSelectModel storageKeysSelectModel; 

    public ValueEncoder<ConfigurationEntry> getConfigurationEntryEncoder() { 
     initConfigurationEntityEncoder(); 

     return this.configurationEntryEncoder; 
    } 

    public BeanModel<ConfigurationEntry> getModel() { 
     return beanModelSource.createDisplayModel(ConfigurationEntry.class, messages); 
    } 

    public SelectModel getStorageKeyModel() { 
     if (storageKeysSelectModel == null) { 
      storageKeysSelectModel = new StringSelectModel(this.dao.getStorageKeys()); 
     } 

     return storageKeysSelectModel; 
    } 

    private void initConfigurationEntityEncoder() { 
     if (this.configurationEntryEncoder == null) { 
      this.configurationEntryEncoder = new ConfigurationEntryEncoder(dao, storageKey); 
     } 
    } 

    private void initZoneData() { 
     if (this.storageKey == null) { 
      this.storageKey = this.dao.getStorageKeys().get(0); 
     } 
     initConfigurationEntityEncoder(); 
    } 

    public Object onActionFromDelete(String configKey) { 
     System.out.println("Deleting from: " + storageKey + " entry: " + configKey); 
     this.dao.deleteConfigurationEntry(storageKey, configKey); 

     return request.isXHR() ? configZone.getBody() : null; 
    } 

    public Object onActionFromUpdate(String configKey, String configValue) { 
     this.dao.updateConfigurationEntry(storageKey, configKey, configValue); 

     return request.isXHR() ? configZone.getBody() : null; 
    } 

    void onActivate(String storageKey) { 
     initZoneData(); 
     this.newEntry = new ConfigurationEntry("", ""); 
    } 

    String onPassivate() { 
     this.newEntry = new ConfigurationEntry("", ""); 
     return this.storageKey; 
    } 

    Object onRefresh() { 
     return request.isXHR() ? configZone.getBody() : null; 
    } 

    Object onSuccessFromAddNewEntryForm() { 
     String configKey = this.newEntry.getConfigKey(); 
     String configValue = this.newEntry.getConfigValue(); 

     this.dao.addConfigurationEntry(storageKey, configKey, configValue); 

     return request.isXHR() ? configZone.getBody() : null; 
    } 

    void onValidateFromAddNewEntryForm() { 
     return; 
    } 

    Object onValueChangedFromStorageKeySelecter(String storageKey) { 
     this.storageKey = storageKey; 
     initConfigurationEntityEncoder(); 
     this.configurationEntries = wrap(this.dao.getConfiguration(storageKey)); 
     return configZone.getBody(); 
    } 

    private void updateChangedConfigurations(List<ConfigurationEntry> changedEntries) { 
     for (ConfigurationEntry changedEntry : changedEntries) { 
      String configKey = changedEntry.getConfigKey(); 
      String configValue = changedEntry.getConfigValue(); 

      System.out.println("Updated: [" + storageKey + ":" + configKey + ":" + configValue + "]"); 

      this.dao.updateConfigurationEntry(storageKey, configKey, configValue); 
     } 
    } 

    void onValidateFromConfigReviewForm() { 
     this.persistentEntries = wrap(this.dao.getConfiguration(storageKey)); 
     List<ConfigurationEntry> tmpList = new ArrayList<ConfigurationEntry>(); 

     for (ConfigurationEntry newEntry : this.configurationEntries) { 
      for (ConfigurationEntry oldEntry : this.persistentEntries) { 
       System.out.println("NewEntry: " + newEntry.toString() + " vs. OldEntry: " + oldEntry.toString()); 
       if (oldEntry.getConfigKey().equals(newEntry.getConfigKey())) { 
        if (!oldEntry.getConfigValue().equals(newEntry.getConfigValue())) { 
         newEntry.setConfigValue(newEntry.getConfigValue().trim()); 
         tmpList.add(newEntry); 
        } 
       } 
      } 
     } 

     this.persistentEntries = tmpList; 
    } 

    Object onSuccessFromConfigReviewForm() { 
     updateChangedConfigurations(this.persistentEntries); 

     return request.isXHR() ? configZone.getBody() : null; 
    } 

    /** 
    * Wraps dictionary entries in instances of ConfigurationEntry 
    */ 
    private List<ConfigurationEntry> wrap(
     Dictionary<String, Object> rawConfiguration) { 
     Set<String> keySet = new TreeSet<String>(); 
     List<ConfigurationEntry> wrappedEntries = new ArrayList<ConfigurationEntry>(); 

     Enumeration<String> keys = rawConfiguration.keys(); 

     while (keys.hasMoreElements()) { 
      String key = keys.nextElement(); 
      keySet.add(key); 
     } 

     for (String key : keySet) { 
      String value = (String) rawConfiguration.get(key); 

      ConfigurationEntry entry = new ConfigurationEntry(key, value); 

      wrappedEntries.add(entry); 
     } 

     return wrappedEntries; 
    } 
} 

出於某種原因, WH單擊「更新」操作鏈接時,傳遞給public Object onActionFromUpdate(String configKey, String configValue)的值不是我剛剛寫入指定文本字段的值,而是頁面呈現時從我的數據庫中提取的值。

例如,如果我有這些對最初:

key1 => value1 
key2 => value2 
key3 => value3 

,我想爲key2爲「newValue2」的傳遞給該方法參數變化值分別是「KEY2」和「值2」,而不是「 key2「和」newValue2「。

同樣的問題是大規模更新不起作用的原因。 configurationEntries中的所有值都是來自數據庫的shapshot值,而不是當前寫入網格中的值。

所以,我的問題是我如何使用AJAX更新我的可編輯網格中的數據庫作爲具體示例。我已經嘗試了很多東西和其他互聯網上的建議,但他們似乎沒有工作,我不知道爲什麼。

+1

不知道爲什麼你加入懸賞這個自@nathanq已經提供了一個鏈接到正在運行的演示用代碼完成jumpstart? –

回答

3

您需要使用zone參數。

查看select component's javadoc的SelectZoneDemo.tml和SelectZoneDemo.java。它提供了一個選擇更改時更新區域的示例。

對於更復雜的交互,你可能會感興趣的this

+0

我知道我需要使用'zone'參數。讓我困惑的是如何連接2個不同的組件,'Select'和'Grid',這樣當'Select'改變時,'Grid'也會改變。儘管如此,趕上第二環節。 :) – Lopina

+1

如果將網格放入區域中,則在區域刷新時網格會更新。網格的數據源可能會受到選擇值的影響。 –

+0

您是否有任何機會擁有代碼段或引用我可以搜索這樣的東西?一些可以幫助我找出問題的例子? – Lopina

2

從您需要提交表單輸入有實際值。在使用ActionLink時,將使用其上下文中的值(這些值在鏈接呈現期間保存在上下文中,不能在沒有黑客攻擊的情況下在客戶端進行更改)。

要讓您的示例正常工作,您可以爲每行使用單獨的表單。您還需要一些提交組件,可以形式以外的工作:

<t:zone t:id="configZone" id="configZone"> 
    <table width="100%"> 
    <t:grid t:source="configurationEntrySource" 
      t:add="update, delete" 
      t:row="configurationEntry" 
      t:mixins="DisableGridSorting" 
      t:include="configKey, configValue" 
      t:encoder="configurationEntryEncoder"> 
     <p:configValueCell> 
     <t:form t:id="configReviewForm" zone="configZone"> 
      <input t:id="value" t:type="TextField" t:value="configurationEntry.configValue" 
       t:validate="required" t:context="configurationEntry.configValue" /> 
     </t:form> 
     </p:configValueCell> 

     <p:updateCell> 
     <t:customlinksubmit form="configReviewForm">Update</t:customlinksubmit> 
     </p:updateCell> 

     <p:deleteCell> 
     <t:actionlink t:id="delete" zone="configZone" context="configurationEntry.configKey">Delete</t:actionlink> 
     </p:deleteCell> 

    </t:grid> 
    </table> 
    <br/> 
</t:zone> 

CustomLinkSubmit:

@SupportsInformalParameters 
public class CustomLinkSubmit implements ClientElement { 

    @Parameter(required = true, allowNull = false, defaultPrefix = BindingConstants.COMPONENT) 
    private Form form; 

    @Parameter(allowNull = false, defaultPrefix = BindingConstants.LITERAL) 
    private SubmitMode mode = SubmitMode.NORMAL; 

    @Inject 
    private ComponentResources resources; 

    @Inject 
    private JavaScriptSupport javascriptSupport; 

    private String clientId; 

    @BeginRender 
    void beginRender(MarkupWriter writer) { 
     clientId = javascriptSupport.allocateClientId(resources); 
     writer.element("span", "id", clientId); 
     resources.renderInformalParameters(writer); 
    } 

    @AfterRender 
    void afterRender(MarkupWriter writer) { 
     writer.end(); 

     JSONObject spec = new JSONObject() 
       .put("form", form.getClientId()) 
       .put("clientId", clientId) 
       .put("validate", mode == SubmitMode.NORMAL); 

     javascriptSupport.addInitializerCall(InitializationPriority.EARLY, "linkSubmit", spec); 
    } 

    public String getClientId() { 
     return clientId; 
    } 
}