Can't access passed object variable in re-used ng-template

时间:2018-12-03 13:11:01

标签: angular scope ng-template

Looping over a JSON object in order to render it as HTML in my Component Template. Re-using a inline ng-template for outputting the HTML.

From the first iteration I am not able to access the Ojbect properties on level since it is undefined, however, the output HTML-like tree structure is build up exactly as the JSON is. Seems like i'm not passing the oject variable in the correct order.

JSON

    { "content": [
            {
                "tag": "paragraph",
                "html": "\r\n",
                "children": [
                    {
                        "tag": "header",
                        "level": "1",
                        "html": "\r\n91\/439\/EC Driving Licences"
                    },
                    {
                        "tag": "header",
                        "level": "2",
                        "html": "\r\nANNEX II - chapter II"
                    }
                ]
            },
            {
                "tag": "br"
            },
            {
                "tag": "paragraph",
                "children": [
                    {
                        "tag": "table",
                        "html": "\r\n",
                        "children": [
                            {
                                "tag": "tr",
                                "children": [
                                    {
                                        "tag": "td",
                                        "html": "II    ."
                                    },
                                    {
                                        "tag": "td",
                                        "html": "\r\nMember States may implement the appropriate measures to ensure that drivers who have lost the knowledge, skills and behaviour as described under points 1 to 9 can recover this knowledge and these skills and will continue to exhibit such behaviour required for driving a motor vehicle.",
                                        "children": [
                                            {
                                                "tag": "br"
                                            },
                                            {
                                                "tag": "br"
                                            },
                                            {
                                                "tag": "list",
                                                "type": "disc",
                                                "html": "\r\n",
                                                "children": [
                                                    {
                                                        "tag": "li",
                                                        "html": "Recognise traffic dangers and assess their seriousness;"
                                                    },
                                                    {
                                                        "tag": "li",
                                                        "html": "Have sufficient command of their vehicle not to create dangerous situations and to react appropriately should such situations occur;"
                                                    },
                                                    {
                                                        "tag": "li",
                                                        "html": "Comply with road traffic regulations, and in particular those intended to prevent road accidents and to maintain the flow of traffic;"
                                                    },
                                                    {
                                                        "tag": "li",
                                                        "html": "Detect any major technical faults in their vehicles, in particular those posing a safety hazard, and have them remedied in an appropriate fashion;"
                                                    },
                                                    {
                                                        "tag": "li",
                                                        "html": "Take account of all the factors affecting driving behaviour (e.g. alcohol, fatigue, poor eyesight, etc.) so as to retain full use of the faculties needed to drive safely;"
                                                    },
                                                    {
                                                        "tag": "li",
                                                        "html": "Help ensure the safety of all road users, and in particular of the weakest and most exposed by showing due respect for others."
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }

Template

<div *ngFor="let rootLevel of jsonHTML; let i = index;">
  <span *ngIf="rootLevel.tag">{{i}} [{{rootLevel.tag}}]</span {{rootLevel.html}}

    <ng-container *ngTemplateOutlet="nextLevelTemplate; context: { level: rootLevel.children, index: i }">
    </ng-container>

</div>

<ng-template #nextLevelTemplate let-level="level" let-i="index">

  <span *ngIf="level && level.tag">[{{level.tag}}]</span><span *ngIf="level && level.html">[{{level.html}}]</span>

  [tag]{{level?.tag}}[/tag] 

  [html]{{level?.html}}[/html]

  -{{level | json}}-

  <div *ngFor="let nextLevel of level; let i = index;">
    <ng-container *ngTemplateOutlet="nextLevelTemplate; context: { level: nextLevel.children, index: i }">
    </ng-container>
  </div>

</ng-template>

Output

0 [paragraph] 
  0 -[object Object],[object Object]-
    0 [tag][/tag] [html][/html] --
    1 [tag][/tag] [html][/html] --

1 [br] 1 [tag][/tag] [html][/html] --

2 [paragraph] 2 [tag][/tag] [html][/html] -[object Object]-
  0 [tag][/tag] [html][/html] -[object Object]-
    0 [tag][/tag] [html][/html] -[object Object],[object Object]-
      0 [tag][/tag] [html][/html] --
      1 [tag][/tag] [html][/html] -[object Object],[object Object],[object Object]-

      0 [tag][/tag] [html][/html] --
      1 [tag][/tag] [html][/html] --
      2 [tag][/tag] [html][/html] -[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]-
        0 [tag][/tag] [html][/html] --
        1 [tag][/tag] [html][/html] --
        2 [tag][/tag] [html][/html] --
        3 [tag][/tag] [html][/html] --
        4 [tag][/tag] [html][/html] --
        5 [tag][/tag] [html][/html] --

Output and screenshot of the following JSON node

"children": [
  {
    "tag": "header",
    "level": "1",
    "html": "\r\n91\/439\/EC Driving Licences"
  },
  {
    "tag": "header",
    "level": "2",
    "html": "\r\nANNEX II - chapter II"
  }
]

enter image description here

As you can see there are 2 items in the Array, template loops over it twice, but tag and html properties cant be accessed.

Is this is scoping issue, that ng-template cant be re-used in this way?

1 个答案:

答案 0 :(得分:0)

我的问题的答案是:Recursive ng-template references

确实是一个范围问题。显然,这一切都是关于以正确的方式绕过范围。

<!-- Define the recursive template. -->
<ng-template #nodeTemplateRef let-node>

    <div class="node" [class.node--selected]="( node === selectedTreeNode )">

        <a (click)="selectNode( node )" class="node__label">
            {{ node.label }}
        </a>

        <div *ngIf="node.children.length" class="node__children">

            <!-- Invoke the recursive template. -->
            <ng-template
                ngFor
                [ngForOf]="node.children"
                [ngForTemplate]="nodeTemplateRef">
                <!--
                    NOTE: The "$implicit" property of the ngFor context is what will
                    be made available to the template ref's implicit let-node binding.
                -->
            </ng-template>

        </div>

    </div>

</ng-template>

<ng-template
    [ngTemplateOutlet]="nodeTemplateRef"
    [ngTemplateOutletContext]="{ $implicit: data.root }">
</ng-template>

<p class="note">
    <em>Ng-For Template Rendering</em>
</p>

... ngFor指令成功地以递归方式呈现了定义它的ngTemplate。

使用ngFor指令时,无法显式传入“上下文”对象-ngFor指令隐式传入ngForContext对象作为模板上下文。这意味着我的ng-template指令必须使用ngFor上下文的“隐式”导出作为“ let-node”模板绑定。

在这种情况下,这不是问题,因为我只想传递一个值。但是,为了获得更大的灵活性,我们可以放弃ngFor指令,而仅使用另一个ng-template递归呈现模板(与使用ng-template实例启动递归的方式几乎相同)...