2011-04-14 88 views
4

我正在處理我的第一個Lift項目,並且需要生成表單。更確切地說,我有一些操作,這些操作由具有附加參數列表的對象表示 - 其中一些是字符串,一些數字,一些布爾值和一些文件。我需要通過表單爲其參數提供操作對象的具體值。目前我只是遍歷參數列表並直接生成XML形式,但我知道這是非常糟糕的風格 - 我無法綁定輸入值,我無法綁定提交的操作,我無法應用驗證。我堅持傳遞請求參數,但我想解決這個問題。不幸的是,我不得不知道如何做到這一點,所以任何幫助將不勝感激。 我始終發現的所有示例始終具有固定數量的輸入參數。如何在Lift中動態生成輸入表單

這裏有一些相關的代碼。我希望這是足夠的理解(我真的羞於公開表明它:-))

def operationForm(): NodeSeq = { 
    val operationCode = S.param("operation").openOr("") 
    val operationVariant = S.param("operationVariant").openOr("") 

    if (operationCode != "" && !operationVariant.isEmpty) { 
     val operation = LighthouseDAOs.operationsRegistry.findByCode(operationCode) 
     val params: List[Parameter] = if (operationVariant == "default") { 
     operation.getParameters.toList 
     } else { 
     operation.getParameters.filter(p => p.getVariant == operationVariant).toList 
     } 

     <lift:surround with="closableBox" at="content"> 
     <form id="viewOperation" post={"/Deployment/" + S.param("location") + "/" + S.param("deployment")} method="post"> 
      {params.map(p => getInputElem(p))} 
      <input type="submit" style="width: 150px;" value="Execute operation"/> 
      <input type="hidden" name="executeOperation" value="true"/> 
     </form> 
     </lift:surround> 
    } else { 
     <span></span> 
    } 
    } 

    private def getOperationVariants(operation: Operation): Set[String] = { 
    operation.getParameters.map(_.getVariant).toSet 
    } 

    def operationVariants(deployment: Deployment): NodeSeq = { 
    val operationCode = S.param("operation").openOr("") 

    if (operationCode != "") { 
     val operation = LighthouseDAOs.operationsRegistry.findByCode(operationCode) 

     val variants = getOperationVariants(operation) 

     if (variants.size > 1) { 
     <lift:surround with="closableBox" at="content"> 
      <table cellspacing="0" cellpadding="0" border="0"> 
      <tr> 
       <th style="width: 160px;">Operation 
       {operation.getLongName} 
       variants</th> 
      </tr>{variants.map(v => { 
      <tr> 
       <td> 
       <a href={Path.path + "Deployment/" + encode(deployment.getLocation) + "/" + encode(deployment.getDeployedComponent.getCode) + "?operation=" + encode(operation.getCode) + "&operationVariant=" + encode(v)}> 
        {v} 
       </a> 
       </td> 
      </tr> 
      })} 
      </table> 
     </lift:surround> 
     } else { 
     <span></span> 
     } 
    } else { 
     <span></span> 
    } 
    } 

    def getInputElem(param: Parameter): Node = { 
    if (param.getChoice != null) { 
     <div> 
     <label for={param.getName}> 
      {param.getName} 
     </label> 
     <select id={param.getName} name={param.getName}> 
      {param.getChoice.flatMap(c => <option value={c}> 
      {c} 
     </option>)} 
     </select> 
     </div> 
    } else { 

     val paramType = param.getType match { 
     case Parameter.PASSWORD => "password" 
     case Parameter.BOOLEAN => "checkbox" 
     case Parameter.CLOB => "file" 
     case _ => "text" 
     } 

     <div> 
     <label for={param.getName}> 
      {param.getName} 
      :</label> <input type={paramType} id={param.getName} name={param.getName} stype="width: 300px;"> 
     {param.getDefaultValue} 
     </input> 
     </div> 
    } 
    } 

    def executeOperation(deployment: Deployment): Elem = { 
    val operationCode = S.param("operation").openOr("") 
    val operationVariant = S.param("operationVariant").openOr("") 

    if (S.param("executeOperation").openOr("false") == "true") { 
     val op = LighthouseDAOs.operationsRegistry.findByCode(operationCode) 
     val params = op.getParameters 

     LogLH3.info("Executing operation: " + op.getLongName) 

     val operationInstallation = new OperationInstallation(); 
     operationInstallation.setInstallationLocation(deployment); 
     operationInstallation.setInstalledOperation(op); 

     val operationCall = new OperationCall(operationInstallation); 
     if (operationVariant != "" && operationVariant != "default") 
     operationCall.setVariant(operationVariant) 

     params.filter(p => p.getVariant == operationVariant).foreach(p => operationCall.addParameterValue(op.createParameterValue(p.getName, S.param(p.getName).openOr("")))) 

     try { 
     LighthouseDAOs.operationInstallationRegistry.execute(operationCall) 
     S.notice("Operation " + op.getLongName + " was executed successfully.") 
     } catch { 
     case e: Exception => S.error(e.getMessage) 
     } 
    } 

    <span></span> 
    } 

只爲我用電梯2.2 &斯卡拉2.8.1

+0

你應該是一個更具體一點,你是如何在此刻做的事情。也許向我們展示一個簡化的代碼片段,以便我們改進它。 – 2011-04-14 13:03:43

+0

完成。我認爲我的解釋足夠通用,但代碼示例永遠不會受到傷害(即使像這個一樣醜陋)。基本上,operationForm()通過元素生成表單元素,executeOperation()處理提交的參數。問題很明顯 - 我無法驗證表單輸入,也無法檢索作爲多部分請求一部分發布的文件。但是,我只是不知道更好。 Lift似乎是一個很好的框架,但它真的需要更多的文檔,我認爲。 – 2011-04-14 13:18:20

回答

3

您可以改善這個紀錄例如,使它更友好一些,但這裏是基本的想法。你需要以某種形式包裝這個過程。

基本上你有一個模板,並用CSS選擇器綁定動態生成的內容替換它的內容。

在模板:

<div class="lift:MyForm.render"> 
    Form will go here 
</div> 

的片段:

class MyForm extends Snippet { 
    def render = { 
    val fields = List("a", "b", "c") 
    var params: Map[String, String] = ... //or whatever 

    def setf(key: String)(value: String) = params = params.updated(key, value) 
    def getf(key: String)() = params.get(key) 

    "*" #> fields map { 
     field => 
     <p> 
      <label>{field}</label>{SHtml.text(getf(field) _, setf(field) _)} 
     </p> 
    } 
    } 
} 
+0

感謝您的回答。我馬上就來。 – 2011-04-18 09:07:16