我如何有条件地重复渲染多个项目

问题描述 投票:0回答:2

我想为一个节点使用条件showIf产生一组重复的节点,如下所示:

div<id = "parent">
  div<id = "child1">Child 1</div>
  div<id = "child2">Child 2</div>
  div<>Optional text for child 2</div>
</div>

为了产生这个,我可能会使用重复函数,如下所示:

div(id := "parent",
  repeat(seqProp)(child =>
   div(id := child.get.id),
   showIf(child.transform(_.otionalText.nonEmpty))(div(child.optionalText.get))
  )
)

但是无论我用什么方式尝试编写此代码,都无法编译以上代码。有人可以推荐我一个好方法吗?

注意。如果我有Seq [Frag],则可以按该序列调用render。但是showIf会生成一个Binding,它似乎隐式转换为Modifier,但没有转换为Frag

scala scala.js udash
2个回答
0
投票
这是一个棘手的任务,因为需要绑定以呈​​现DOM节点,而不是Modifier(因此可以在进行任何更改时相应地替换它们)。

首先,repeat仅跟踪结构更改,因此您需要组合2个绑定。为避免泄漏,在这种情况下,可以使用repeatWithNested

第二,scalatags.generic.LowPriUtil#OptionFrag允许您渲染Option节点,因此您无需担心showIf

考虑到这一点,假设您具有一些模型类和序列:

case class C(id: String, optionalText: Option[String]) val seqProp = SeqProperty(C("a", Some("")))

您可以写:

div( id := "parent", repeatWithNested(seqProp)((childProp, nested) => div( nested(produce(childProp)(child => Seq( div(id := child.id)(child.id).render, child.optionalText.render, ))) ).render) )

不幸的是,这会产生一个额外的嵌套div,但是会正确地对结构和值补丁做出反应。

您可以在此处查看此代码的运行情况:https://scalafiddle.io/sf/BHG388f/0

[如果您确实想避免这种情况,则必须牺牲其中的一些属性,例如通过在produce上使用seqProp并将parent创建为其在构建器内部的根节点。


0
投票
我不得不使用您在上文最后提到的生产选项,因为我想避免第一个解决方案附带额外的div。

我将详细说明我的情况,以更好地解释上下文。我有以下课程:

case class MenuNode(item: MenuItem, subNodes: Seq[MenuNode])

并且我需要一个递归函数,该函数迭代所有将它们转换为DOM结构的节点。除此之外,我需要处理这些节点的单击事件,并根据它们是否已展开来展开/折叠菜单。此函数将需要访问属性,因为它将修改实际节点。因此,为此,我添加了一个额外的转换,以从我的SeqProperty移到普通属性。

所以我想出的解决方案类似于以下递归函数:

def renderItems(property: Property[MenuNode]): Modifier = { val seqProp = property.transformToSeq(_.subNodes, (sns: Seq[MenuNode]) => property.get.copy(subNodes = sns)) produce(seqProp) { nodes => div(nodes.zipWithIndex.flatMap { case (node, i) => val nodeProp = property.transform(_.subNodes(i), (node: MenuNode) => property.get.copy(subNodes = property.get.subNodes.replace(i, node))) Seq( button(cls := "menu-button", onclick := { () => handleClick(nodeProp) }, node.item.label ) ) ++ node.subNodes.nonEmpty.option { div(cls := "sub-menu", renderItems(nodeProp)) } }).render } }

注意。 

option {...}是我添加的一项增强功能,用于将布尔值转换为Option。

© www.soinside.com 2019 - 2024. All rights reserved.