Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using jade to create an unordered list tree

I have an object called boundedArea which contains an array of boundedArea objects in a field children and I would like to create a tree of unordered lists.

I have the following code:

- for (var index = 0; index < rootAreas.length; index++) {
  - var boundedArea = rootAreas[index];
  div(class='panel panel-default')
    div.panel-heading
      | #{boundedArea.NAME}
    div.panel-body
      - printChildren(boundedArea, 0); 
- }
- 
- function printChildren(boundedArea, depth) {
  - var children = boundedArea.children;
  - if (children == null || children.length == 0) {
    - return;
  - } 
  ul  
  - for (var index = 0; index < children.length; index++) {
    - var child = children[index];
    li #{child.NAME}
    - console.log("Printing %s child of %s", child.NAME, boundedArea.NAME);
    - printChildren(child, depth + 1); 
  - } 
- }

Now obviously this sort of works in that it prints out all the values. However because the ul and li tags are a fixed indentation in they do not nest and just ended up printing sequentially.

Is there any way to dynamically set the level of indent or to force these to nest. Or should I be using a completely different model of nesting altogether.

I tried cretaing a javascript variable indent filled with two spaces for each depth level and then tried to use #{indent} but that just ended up creating tags with spaces in which was not what I wanted. Though that implies that something around this idea could work as it must be resolved at some level before but the it is picked up as a token of some kind.

like image 740
James Robinson Avatar asked Feb 25 '26 22:02

James Robinson


1 Answers

Try using a mixin instead of a function. Mixins respect/remember the level of indentation (not really sure why functions don't).

mixin printChildren(boundedArea, depth)
  - var children = boundedArea.children;
  - if (children == null || children.length == 0)
    - return;
  ul  
    - for (var index = 0; index < children.length; index++)
      - var child = children[index];
      li #{child.NAME}
        +printChildren(child, depth + 1)

- for (var index = 0; index < rootAreas.length; index++)
  - var boundedArea = rootAreas[index];
  div(class='panel panel-default')
    div.panel-heading
      | #{boundedArea.NAME}
    div.panel-body
      +printChildren(boundedArea, 0)

I tweaked your code a bit. Mixins are invoked using a + instead of a - and they need to be defined before they are used.

I tested it with this sample data:

{
  rootAreas: [
    {
      NAME: 'area1',
      children: [
        { NAME: 'child1' },
        { NAME: 'child2' },
        { 
          children: [
            { NAME: 'child3' },
            { NAME: 'child4' },
          ]
        },
      ]
    },
    {
      NAME: 'area2',
      children: [
        { NAME: 'child5' },
        { NAME: 'child6' },
        { NAME: 'child7' },
      ]
    }
  ]
}

And the template yielded this HTML code:

<div class="panel panel-default">
  <div class="panel-heading">area1</div>
  <div class="panel-body">
    <ul> 
      <li>child1</li>
      <li>child2</li>
      <li>
        <ul> 
          <li>child3</li>
          <li>child4</li>
        </ul>
      </li>
    </ul>
  </div>
</div>
<div class="panel panel-default">
  <div class="panel-heading">area2</div>
  <div class="panel-body">
    <ul> 
      <li>child5</li>
      <li>child6</li>
      <li>child7</li>
    </ul>
  </div>
</div>

If I understood you correctly, this is what you're looking for.

like image 100
JME Avatar answered Feb 28 '26 11:02

JME



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!