【问题标题】:Angular2 SVG xlink:hrefAngular2 SVG xlink:href
【发布时间】:2016-05-07 01:52:39
【问题描述】:

我有渲染 SVG 图标的组件:

import {Component, Directive} from 'angular2/core';
import {COMMON_DIRECTIVES} from 'angular2/common';

@Component({
  selector: '[icon]',
  directives: [COMMON_DIRECTIVES],
  template: `<svg role="img" class="o-icon o-icon--large">
                <use [xlink:href]="iconHref"></use>
              </svg>{{ innerText }}`
})
export class Icon {
  iconHref: string = 'icons/icons.svg#menu-dashboard';
  innerText: string = 'Dashboard';
}

这会触发错误:

EXCEPTION: Template parse errors:
  Can't bind to 'xlink:href' since it isn't a known native property ("<svg role="img" class="o-icon o-icon--large">
<use [ERROR ->][xlink:href]=iconHref></use>
  </svg>{{ innerText }}"): SvgIcon@1:21

如何设置动态xlink:href?

【问题讨论】:

    标签: angular angular2-template


    【解决方案1】:

    SVG 元素没有属性,因此大多数时候都需要属性绑定(另请参阅Properties and Attributes in HTML)。

    你需要的属性绑定

    <use [attr.xlink:href]="iconHref">
    

    或

    <use attr.xlink:href="{{iconHref}}">
    

    更新

    消毒可能会导致问题。

    另见

    更新 DomSanitizationService 将在 RC.6 中重命名为 DomSanitizer

    更新这应该修复

    但是对于命名空间属性https://github.com/angular/angular/pull/6363/files 支持此功能存在一个未解决的问题

    作为解决方法添加一个额外的

    xlink:href=""
    

    Angular 可以更新属性,但添加时有问题。

    如果 xlink:href 实际上是一个属性,那么在添加 PR 之后,您的语法也应该可以工作。

    【讨论】:

    • 谢谢!现在 iconHref 在 DOM 中呈现。仍然没有显示图标,就像我 SVG 没有选择更改一样。似乎需要 PR 才能正常工作。
    • 请注意,这也适用于图像标签。 &lt;image attr.xlink:href="http://somewhere.com/{{restOfUrl}}" /&gt;
    【解决方案2】:

    Gunter 描述的 attr.xlink:href 仍然存在问题,因此我创建了一个类似于 SVG 4 Everybody 但特定于 angular2 的指令。

    用法

    &lt;div [useLoader]="'icons/icons.svg#menu-dashboard'"&gt;&lt;/div&gt;

    说明

    该指令将

    1. 通过 http 加载图标/icons.svg
    2. 解析响应并提取#menu-dashboard 的路径信息
    3. 将解析后的 svg 图标添加到 html 中

    代码

    import { Directive, Input, ElementRef, OnChanges } from '@angular/core';
    import { Http } from '@angular/http';
    
    // Extract necessary symbol information
    // Return text of specified svg
    const extractSymbol = (svg, name) => {
        return svg.split('<symbol')
        .filter((def: string) => def.includes(name))
        .map((def) => def.split('</symbol>')[0])
        .map((def) => '<svg ' + def + '</svg>')
    }
    
    @Directive({
        selector: '[useLoader]'
    })
    export class UseLoaderDirective implements OnChanges {
    
        @Input() useLoader: string;
    
        constructor (
            private element: ElementRef,
            private http: Http
        ) {}
    
        ngOnChanges (values) {
            if (
                values.useLoader.currentValue &&
                values.useLoader.currentValue.includes('#')
            ) {
                // The resource url of the svg
                const src  = values.useLoader.currentValue.split('#')[0];
                // The id of the symbol definition
                const name = values.useLoader.currentValue.split('#')[1];
    
                // Load the src
                // Extract interested svg
                // Add svg to the element
                this.http.get(src)
                .map(res => res.text())
                .map(svg => extractSymbol(svg, name))
                .toPromise()
                .then(svg => this.element.nativeElement.innerHTML = svg)
                .catch(err => console.log(err))
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      我认为可以使用角管功能解决。

      <use attr.xlink:href={{weatherData.currently.icon|iconpipe}}></use>
      

      说明 该管道将​​

      1. 将解析后的响应值传递给管道
      2. 返回完整的 svg 路径
      3. attr.xlink:href= 将获得预期的路径和 svg 将呈现在 html页面

      这里是管道打字稿代码

      import { PipeTransform, Pipe } from '@angular/core';
      
      @Pipe({
          name: 'iconpipe'
      })
      export class IconPipe implements PipeTransform {
          constructor() { }
      
          transform(value: any) {
              let properIconName = undefined;
      
              switch (value) {
                  case 'clear-day':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#sun';
                      break;
                  case 'clear-night':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#night-1';
                      break;
                  case 'partly-cloudy-day':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#cloudy';
                      break;
      
                  case 'partly-cloudy-night':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#night';
                      break;
      
                  case 'cloudy':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#cloud';
                      break;
      
                  case 'rain':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#rain';
                      break;
      
                  case 'sleet':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#snowflake';
                      break;
                  case 'snow':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#snowing';
                      break;
      
                  case 'wind':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#storm';
                      break;
                  case 'fog':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#sun';
                      break;
                  case 'humid':
                      properIconName = '/assets/images/weather-SVG-sprite.svg#sun';
                      break;
                  default:
                      properIconName = '/assets/images/weather-SVG-sprite.svg#summer';
              }
              return properIconName;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-01-29
        • 1970-01-01
        • 2013-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-07
        相关资源
        最近更新 更多