删除由角度组件创建的主机HTML元素选择器

时间:2015-12-15 03:07:35

标签: svg angular

在角度2中, svg-rect 是一个创建 rect 的组件,如下所示,

<svg height="550" width="450" x="0" y="0">
    <g id="svgGroup">
        <svg-rect>
        <!--template bindings={}-->
            <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
        <!--template bindings={}-->
        </svg-rect>
        <svg-rect>
        <!--template bindings={}-->
            <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
        <!--template bindings={}-->
        </svg-rect>
    </g>
</svg>

但由于创建了特殊元素标记,因此无法呈现 rect 。如果删除 svg-rect 标记,则会呈现 rect

<svg height="550" width="450" x="0" y="0">
    <g id="svgGroup">
        <!--template bindings={}-->
        <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
        <!--template bindings={}-->
        <!--template bindings={}-->
        <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
        <!--template bindings={}-->
    </g>
</svg>

在Angular 1.x中,有 替换:&#39; true&#39; ,它会删除带有编译输出的指令标记。我们可以在angular2中实现相同的功能吗?

5 个答案:

答案 0 :(得分:29)

另一种删除我使用的组件主机的方法。

指令remove-host

//remove the host of avatar to be rendered as svg
@Directive({
    selector: '[remove-host]'
})
class RemoveHost {
    constructor(private el: ElementRef) {
    }

    //wait for the component to render completely
    ngOnInit() {
        var nativeElement: HTMLElement = this.el.nativeElement,
            parentElement: HTMLElement = nativeElement.parentElement;
        // move all children out of the element
        while (nativeElement.firstChild) {
            parentElement.insertBefore(nativeElement.firstChild, nativeElement);
        }
        // remove the empty element(the host)
        parentElement.removeChild(nativeElement);
    }
}

使用此指令;
<avatar [name]="hero.name" remove-host></avatar>

remove-host指令中,nativeElement的所有子节点都插入主机之前,然后删除主机元素。

Sample Example Gist
根据用例,可能会出现一些性能问题。

答案 1 :(得分:28)

不是试图摆脱主机元素,而是将其转换为有效的SVG,但其他明智的不受影响:而不是元素选择器

selector: "svg-rect"

及其在模板中的相应元素:

template: `...<svg-rect>...</svg-rect>...`

切换到属性选择器

selector: "[svg-rect]"

并将该属性添加到组元素标记:

template: `...<g svg-rect>...</g>...`

这将扩展为:

<svg height="550" width="450" x="0" y="0">
    <g id="svgGroup">
        <g svg-rect>
        <!--template bindings={}-->
            <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
        <!--template bindings={}-->
        </g>
        <g svg-rect>
        <!--template bindings={}-->
            <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
        <!--template bindings={}-->
        </g>
    </g>
</svg>

这是有效的SVG,它将呈现。 Plnkr

答案 2 :(得分:7)

还有另一种方法,我们可以从组件中获取组件的模板 首先,我们创建组件,我们希望从浏览器渲染中删除其标记(我们不会尝试在此处删除标记。)

@Component({
  selector: 'tl-no-tag',
  template: `
    <template #tmp>
      <p>{{value}}</p>
    </template>`,
  styleUrls: []
})
export class TlNoTagComponent {
  @ViewChild('tmp') tmp: any;
  value = 5;
}

然后,在另一个组件的模板中,我们写道:

<tl-no-tag #source></tl-no-tag> <!-- This line can be placed anywhere -->
<template [ngTemplateOutlet]="source.tmp"></template> <!-- This line will be placed where needed -->

然后,我们在浏览器中有这样的东西:

<tl-no-tag></tl-no-tag>
<p>5</p>

因此,我们将<p>{{value}}</p>从TlNoTagComponent中删除。 <{1}}将继续存在,但不会阻止任何css或svg-thing。

答案 3 :(得分:4)

引用Angular 1 to Angular 2 Upgrade Strategy doc

  

Angular 2中不支持替换其主机元素的指令(替换:Angular 1中的true指令)。在许多情况下,这些指令可以升级到常规组件指令。

     

有些情况下,常规组件指令不起作用,在这些情况下,可以使用替代方法。例如,对于svg,请参阅:https://github.com/mhevery/ng2-svg

答案 4 :(得分:3)

那又怎么样呢?

:host { display: contents; }

将其放在主机组件的css(或scss)文件中将导致该组件的框无法呈现。

N.B:以前它对我有用-但是显然我担心浏览器的兼容性,特别是如果您正在开发以支持较旧的浏览器。我也很确定这并不完全超出“实验”阶段。文档还指出,这可能会导致可访问性问题。