2011-04-14 106 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