1
votes

I'm developing a web application using Angular 5 with Ngx-Bootstrap and I'm having a trouble in the template inside a SVG tag.

I'm doing a loop in a svg group (g tag). Inside G I have some foreignObjects and I want to use bootstrap popover for each foreignObject when mouse is on it, but I need make binding inside the popovers, and template needs data from loop.

<g *ngFor='let textBox of textBoxes'>
    <foreignObject [id]='textBox.name' [attr.x]='textBox.topLeftNode.x' [attr.y]='textBox.topLeftNode.y'
        [attr.width]='getWidth(textBox)' [attr.height]='getHeight(textBox)' [popover]='commentsTemplate' 
        popoverTitle='Comments' triggers='mouseenter' [outsideClick]='true' container='body' placement='right'>
    </foreignObject>

    <ng-template #commentsTemplate>
        <span class='comment' *ngFor='let comment of getComments(textBox.id)'>
          {{comment}}
        </span>

        <input type='text' class='form-control comment-input' placeholder='Add comment...'>
        <button class='btn btn-secondary comment-submit'>Comment</button>
    </ng-template>
</g>

When angular-cli builds the application (don't show errors), browser shows only a blank page and the console shows the following error:

Error: Template parse errors: Unexpected closing tag ":svg:ng-template". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags ("dd comment...'> Comment [ERROR ->] "): ng:///AppModule/ReadComponent.html@78:10

But I has set popover container the "body".

I've already tried use ng-container and put the ng-template tag inside another foreignObject, but console says that :svg:ng-template not exists...

I can't put ng-template inside the main foreignObject because I'm binding the content of it (I didn't show that bind to avoid misunderstanding).

Sorry for the confusing english.

Can someone help me?

2

2 Answers

1
votes

Solved. I did put a ng-container inside ng-template of the loop. So my ng-container calls a external ng-template, passing context.

<svg>
    <g *ngFor='let textBox of textBoxes'>
        <foreignObject [id]='textBox.name' [attr.x]='textBox.topLeftNode.x' [attr.y]='textBox.topLeftNode.y'
            [attr.width]='getWidth(textBox)' [attr.height]='getHeight(textBox)' [popover]='preCommentsTemplate' 
            popoverTitle='Comments' triggers='mouseenter' [outsideClick]='true' container='body' placement='right'>
        </foreignObject>

        <ng-template #preCommentsTemplate>
            <ng-container *ngTemplateOutlet='commentsTemplate; context: textRectangle'></ng-container>
        </ng-template>
    </g>
</svg>

<ng-template #commentsTemplate let-id='id'>
    <span class='comment' *ngFor='let comment of getComments(id)'>
      {{comment}}
    </span>

    <input type='text' class='form-control comment-input' placeholder='Add comment...'>
    <button class='btn btn-secondary comment-submit'>Comment</button>
</ng-template>
1
votes

I just wanted to warn you that since angular 9 <ng-template> often gives issues when used inside an <svg> element. See also.

I ended up replacing all of <ng-template> with <g> elements, which can also contain structural directives like *ngIf and *ngFor.