web-dev-qa-db-fra.com

AngularJS ng-href et svg xlink

J'aimerais avoir des informations sur l'utilisation des attributs d'espaces de noms xml avec angular.

Le problème est angular est livré avec quelques directives pour gérer l'écriture d'attributs tels que href et src lorsque angular a analysé les expressions (sinon le navigateur essaiera de charge {{mymodel.myimage}} comme une URL)

https://github.com/angular/angular.js/blob/master/src/ng/directive/booleanAttrs.js#L329

Le problème auquel je suis confronté est que j'utilise angular pour sortir svg avec D3 et depuis angular n'a pas de moyen de sortir xlink:href J'étais coincé.

J'ai créé une directive personnalisée qui génère xlink: href

app.directive('ngXlinkHref', function () {
  return {
    priority: 99,
    restrict: 'A',
    link: function (scope, element, attr) {
      var attrName = 'xlink:href';
      attr.$observe('ngXlinkHref', function (value) {
        if (!value)
          return;

        attr.$set(attrName, value);
      });
    }
  };
});

Démo complète: http://plnkr.co/edit/cMhGRh

Mais il semble que si je n'ajoute pas manuellement xlink: href à l'élément, l'image svg ne sera pas rendue.

Toute suggestion sur la meilleure façon de gérer les espaces de noms xml/svg avec angular serait grandement appréciée.

39
Leon Radley

Vous pouvez utiliser ng-attr-<some attribute>

ng-attr-xlink:href="{{xxx}}" travaille pour moi.


Notez que vous avez également besoin d'un xlink:href="" comme valeur initiale. - Derek Hsu

59
Derek Hsu

Si, comme moi, vous cherchez un moyen d'ajouter des images au svg, vous pouvez le faire en ajoutant:

xlink:href="" ng-href="{{ foo }}"

Exemple:

http://jsbin.com/sigoleya/1/edit?html,js,output

Où j'ai trouvé la solution:

https://github.com/angular/angular.js/issues/7697

19
Tiagojdferreira

J'ai rencontré un problème similaire lors de la tentative de sortie d'une valeur pour xlink:href qui est lié au modèle. Basé sur le choix de l'utilisateur <option> dans un <select> control, j'essayais d'afficher une icône SVG dynamique via le xlink:href attribut de <use> élément.

J'ai trouvé n fil à ce sujet dans les problèmes GitHub pour AngularJS. Sur la base de la discussion, il semble que parce qu'une solution de contournement viable existe, ils ont effectivement déposé un correctif en le déplaçant vers le jalon Backlog.

Ce qui a finalement fonctionné pour moi a été inspiré par ce JSBin:

http://jsbin.com/sigoleya/1/edit?html,js,output

Voici le code que j'ai utilisé dans mon modèle:

<svg class="icon" data-ng-class="category.iconName">
  <use xlink:href="" data-ng-href="{{'#' + category.iconName}}">
</svg>

Donné un category.iconName de icon-music, par exemple, Angular définit le xlink:href dynamiquement à #icon-music, qui fait référence au <svg id="icon-music"> élément plus haut sur la même page.

Comme d'autres l'ont noté, ce qui est essentiel, c'est de mettre un _ xlink:href="" attribut sur l'élément où vous appelez la directive ngHref. L'ordre des attributs ne semble pas avoir d'importance. En utilisant ng-attr-xlink:href="{{xxx}}" (comme mentionné dans la réponse de Derek Hsu) n'a pas fonctionné pour moi.

Tout cela suppose Angular 1.3.36.

10
Bungle

J'ai résolu le même problème avec les modules suivants:

Module pour SVG:

var app = angular.module('Svgs', []);

angular.forEach([
    { ngAttrName: 'ngXlinkHref', attrName: 'xlink:href' },
    { ngAttrName: 'ngWidth', attrName: 'width' },
    { ngAttrName: 'ngHeight', attrName: 'height' }
], function (pair) {

    var ngAttrName = pair.ngAttrName;
    var attrName = pair.attrName;

    app.directive(ngAttrName, function (IeHelperSrv) {

        return {

            priority: 99,

            link: function (scope, element, attrs) {

                attrs.$observe(ngAttrName, function (value) {

                    if (!value) return;

                    attrs.$set(attrName, value);
                    if (IeHelperSrv.isIE) element.prop(attrName, value);
                });
            }
        };
    });
});

Module pour IE détection:

angular.module('IeHelper', []).factory('IeHelperSrv', function () {

    return {
        isIE: checkForIE.isIE,
    }
});

var checkForIE = {
    init: function () {
        this.isIE = (navigator.userAgent.indexOf('MSIE') != -1);
    }
};

checkForIE.init();

HTML:

<!-- image has initial fake source, width and height to force it to render -->
<image xlink:href="~/Content/Empty.png" width="1" height="1"
    ng-xlink-href="{{item.imageSrc}}"
    ng-width="{{item.width}}" ng-height="{{item.height}}"
    ng-cloak
    />
6
Danny Varod

Pour toute autre personne ayant ce problème en raison du routeur d'interface utilisateur angulaire/angulaire en mode HTML5, j'ai trouvé une solution simple pour permettre aux icônes svg Sprite de fonctionner avec leur attribut xlink: href et la balise.

Gist est ici: https://Gist.github.com/planetflash/4d9d66e924aae95f7618c03f2aabd4a

app.run(['$rootScope', '$window', function($rootScope, $window){
 $rootScope.$on('$locationChangeSuccess', function(event){
    $rootScope.absurl = $window.location.href;
});

<svg><use xlink:href="{{absurl+'#svgvID'}}"></use></svg>
2
Paul Thomas

Cela m'a pris plus de temps que je l'aurais souhaité. Environ 20-30 minutes.

Si je comprends bien, tout échec de chargement sur l'élément image rendra cet élément inutile à l'avenir. Je pense que c'est quelque chose de similaire que dit @GeekyMonkey. Si angular a initialement défini xlink: href sur null, l'élément Image ne fonctionnera plus, même si nous avons une valeur valide à l'avenir.

Voici la solution, remarquez comment j'ai encapsulé l'élément image à l'intérieur de l'élément g, en utilisant la directive ng-if. Cela garantit que nous ne nous lierons à l'image que lorsqu'une valeur correcte est disponible.

<g ng-if="vm.svgMap.background != null">
    <image
        ng-attr-xlink:href="{{vm.svgMap.background.image | trusted}}"
        ng-attr-width="{{vm.svgMap.background.width}}"
        ng-attr-height="{{vm.svgMap.background.width}}"

        xlink:href=""

        width="1"
        height="1"
        x="0"
        y="0"></image>
</g>

Comme d'autres l'ont dit, l'ordre des attributs est également important. Pour nous assurer que angularJS nous permet de lier l'élément image, nous devons également faire confiance à cette ressource, je l'ai fait via le filtre (c'est celui de l'attribut xlink: href):

(function() {
    'use strict';

    angular.module('myTool').filter('trusted', TrustedFilter);

    function TrustedFilter($sce) {
        return function(url) {
            return $sce.trustAsResourceUrl(url);
        };
    };
}());
0
Erti-Chris Eelmaa

J'ai rencontré ce problème où j'utilisais Ajax pour charger la feuille de calcul svg sur la page. Si j'avais un sur la page avant le chargement de la feuille de sprites, il échouerait et ne se résoudrait pas une fois la feuille de sprites disponible. Tout ajout au dom après le chargement de la feuille de sprites était correct. J'ai dû retarder la mise en place des éléments dans le dom jusqu'à ce que la feuille de sprites ait fini de charger.

Cela n'a affecté que l'IOS. Tous les autres navigateurs se moquaient de la commande.

0
GeekyMonkey