GSP页面中的递归

3
我有一个域名。
class Node {   

    String nodeId
    String label

    Node parent    
}

在GSP页面中,我希望从根开始打印所有子节点(请注意,我已经有父节点的引用而不是子节点)。您有什么好的建议吗?对于这个问题我很抱歉,因为我还是新手,真的很困惑。我想要打印从根节点向下的所有内容(不包括根节点)且根节点没有父节点(即为null)。所以我写了:

<g:each in="${nodes}" var="node">
<g:if test="${node.parent!=null}">

  ${node.label}
  <g:render template="node" model="[nodes:Node.findAllByParent(node)]" />
</g:if>
</g:each>

在以上代码中,不确定parent_node_intance应该是什么。节点列表从根节点开始。我不想打印它,而是从所有以根节点为父节点的其他节点开始。 node.gsp
<g:if test="${nodes}">
<ul>
  <g:each in="${nodes}" var="node">
    <li>
      ${node.label}
      <g:render template="node" model="[nodes:Node.findAllByParent(node)]" />
    </li>
  </g:each>
</ul>
</g:if>

我得到了以下的错误信息,我确信是由根目录引起的。
2014-10-02 12:28:21,693 [http-bio-8080-exec-1] ERROR errors.GrailsExceptionResolver  - NullPointerException occurred when processing request: [GET] /taxonomy - parameters:
outputFormat: concept
hierarchyId: lp
Cannot invoke method findAllByParent() on null object. Stacktrace follows:
Message: Error evaluating expression [[nodes:Node.findAllByParent(node)]] on line [11]: Cannot invoke method findAllByParent() on null object
    Line | Method
->>   11 | run       in C:/Users/U6021072/Documents/workspace-ggts-3.6.0.RELEASE/ae-and-sdx-analysis-ui/target/work/plugins/taxonomy-toolkit-for-grails-0.02-SNAPSHOT/grails-app/views/taxonomy/concept.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Caused by NullPointerException: Cannot invoke method findAllByParent() on null object
->>   11 | doCall    in C__Users_U6021072_Documents_workspace_ggts_3_6_0_RELEASE_ae_and_sdx_analysis_ui_target_work_plugins_taxonomy_toolkit_for_grails_0_02_SNAPSHOT_grails_app_views_taxonomy_concept_gsp$_run_closure4
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    198 | doFilter  in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter  in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run       in java.lang.Thread
2个回答

4

那么,您想打印所有具有已知父节点的节点吗?

像这样怎么样:

<g:each in="${Node.findAllByParent(parent_node_instance)}" var="node">
  ${node}<br>
</g:each>

既然您谈到了递归,我想您也希望打印所有的后代。

创建一个 _node.gsp 模板:

<g:each in="${nodes}" var="node">
  ${node}<br>
  <g:render template="node" model="[nodes:Node.findAllByParent(node)]" />
</g:each>

并且使用以下方式调用:

<g:render template="node" model="[nodes:Node.findAllByParent(parent_node_instance)]" />

你可以轻松地向模型添加一个深度变量,以便正确缩进每个子代,或在模板中使用 <ul><li> 元素。 parent_node_instance 是你希望从其开始打印树的根节点,它可以是绝对根节点或树中的任何节点。 findAllByParent() 是一个动态查找函数。详见http://grails.org/doc/latest/guide/GORM.html#finders

不错的想法,递归调用模板。我认为我会在Node中添加一个getChildren()方法,并将查找逻辑放在其中,而不是分散到各处。 - Steinar
@Steinar 小心!Node.getChildren() 方法不会包含 TX 上下文,所以如果你不小心的话,可能会得到一个错误的结果。 - injecteer

2
你也可以使用@collection/@bean

_node.gsp

<div class="fancy nested">
  id:${it.nodeId} - label:${it.label}
  <g:render template="node" collection="${Node.findAllByParent(it.node)}" />
</div>

main.gsp

<g:render template="node" bean="${rootNode}" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接