2013-04-09 15 views
30

Ich möchte einige Eingabe auf die Verwendung von XML Namespaced Attribute mit eckigen.angular ng-href und svg xlink

Das Problem Winkel ist mit ein paar Richtlinien kommt Attribute wie href und src zu handhaben zu schreiben, als Winkel die Expresssions analysiert hat (sonst wird der Browser versuchen {{mymodel.myimage}} als URL zu laden)

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

Das Problem, mit dem ich konfrontiert bin, ist, dass ich eckig verwende, um Svg zusammen mit D3 auszugeben, und weil Winkel keine Möglichkeit zur Ausgabe hat xlink:href Ich steckte fest.

Ich habe eine benutzerdefinierte Richtlinie, die die x-Verbindung gibt: 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); 
     }); 
    } 
    }; 
}); 

Full-Demo: http://plnkr.co/edit/cMhGRh

Aber es scheint, dass, wenn ich xlink nicht manuell hinzufügen: href auf das Element, das SVG-Bild wird nicht gerendert.

Alle Vorschläge, wie man XML-Namespaces/svg zusammen mit angular am besten behandelt, würden sehr geschätzt werden.

+0

ich, keine Antwort auf Ihre Frage finden, aber danke für die Plunker veröffentlichen. Ich habe es für meine eigene eckige SVG-Bindung verwendet. –

Antwort

49

Sie können 01 verwenden

ng-attr-xlink:href="{{xxx}}" funktioniert für mich.


Beachten Sie, dass Sie auch einen leeren xlink:href="" als Anfangswert benötigen. - Derek Hsu

+2

Dies liefert keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlasse einen Kommentar unter seinem Beitrag - du kannst deine eigenen Beiträge jederzeit kommentieren, und sobald du genügend [Reputation] (http://stackoverflow.com/help/whats-reputation) hast, wirst du das tun in der Lage sein [jeden Beitrag kommentieren] (http://stackoverflow.com/help/privileges/comment). – Siddharth

+4

@Siddharth, Eigentlich tut es das. Die Frage betrifft nicht nur benutzerdefinierte Anweisungen. In der Tat wollte @Leon einige Eingaben für die Verwendung von XML-Namespaced-Attributen mit eckigen und Vorschlägen, wie XML-Namespaces/svg zusammen mit angular am besten gehandhabt werden. Um sein Problem zu lösen, schrieb er sogar benutzerdefinierte Anweisungen. Ich betone, dass benutzerdefinierte Anweisungen nicht notwendig sind. Angularjs hat bereits "ng-attr", was die Aufgabe für ihn erledigt. –

+0

Ein upvote von @Leon wird helfen, meine Entscheidung umzukehren. – Siddharth

6

löste ich das gleiche Problem mit den folgenden Modulen:

Modul für SVGs:

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); 
       }); 
      } 
     }; 
    }); 
}); 

Modul für IE-Erkennung:

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 
    /> 
+2

Wenn der xlink: href für mich nicht funktionierte, musste ich diesen Beitrag erneut lesen. Der Schlüssel hier ist, dass Sie einen gefälschten Wert benötigen, um mit zu beginnen. Ohne es wird das Bild nicht mit dem richtigen Attribut wiedergegeben. Lassen Sie diesen Kommentar, um anderen TL, DR Dummies wie mir zu helfen. Danke Danny! – coblr

+0

@fractalspawn Gern geschehen. Ich wollte diesen Kommentar zu der Antwort hinzufügen, dann sah ich, dass ich dies bereits in einen Kommentar über dem HTML geschrieben hatte :-) –

7

Ich stieß auf ein ähnliches Problem beim Versuch, einen Wert für xlink:href auszugeben, der an das Modell gebunden ist. Basierend auf dem vom Benutzer gewählten <option> in einem <select> Steuerelement, versuchte ich, ein dynamisches SVG-Symbol über das xlink:href Attribut des Elements <use> anzuzeigen.

Ich habe in den GitHub-Ausgaben für AngularJS gefunden. Basierend auf der Diskussion dort, scheint es, dass, weil ein praktikabler Workaround existiert, sie effektiv einen Fix eingereicht haben, indem sie es zum Backlog Meilenstein verschoben haben.

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

Hier ist der Code, den ich in meiner Vorlage verwendet:

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

ein category.iconName von icon-music, zum Beispiel gegebenen Winkel

Was schließlich für mich gearbeitet wurde dieses JSBin inspiriert setzt die xlink:href dynamisch auf #icon-music, die das Element <svg id="icon-music"> weiter oben auf der gleichen Seite verweist.

Wie andere bemerkt haben, ist der Schlüssel zum Setzen eines leeren xlink:href="" Attributs auf das Element, wo Sie die ngHref Anweisung aufrufen. Die Reihenfolge der Attribute scheint nicht wichtig zu sein. Die Verwendung von ng-attr-xlink:href="{{xxx}}" (wie in Derek Hsus Antwort erwähnt) funktionierte nicht für mich.

All dies vorausgesetzt Angular 1.3.36.

+2

Vielen Dank. –

0

I lief auf dieses Problem, wo ich Ajax verwendet, um das Svg-Spritesheet auf die Seite zu laden. Wenn ich ein auf der Seite hatte, bevor das Spritesheet geladen wurde, würde es fehlschlagen und würde nicht aufgelöst werden, sobald das Spritesheet verfügbar war. Alle, die nach dem Laden des Spritesheets zum Dom hinzugefügt wurden, waren in Ordnung. Ich musste die Gegenstände in den Dom verschieben, bis das Spritesheet fertig geladen war.

Dies betrifft nur IOS. Alle anderen Browser kümmerten sich nicht um die Bestellung.

0

Das nahm mir mehr Zeit, als ich mir gewünscht hätte. Ungefähr 20-30 Minuten.

Wenn ich richtig verstehe, wird jedes fehlerhafte Laden auf Bildelement dieses Element in Zukunft nutzlos machen. Ich glaube, es ist etwas ähnliches @ GeekyMonkey sagt. Wenn das eckige Bindungssystem xlink: href anfänglich auf null gesetzt hat, funktioniert das Bildelement nicht mehr, selbst wenn wir in Zukunft einen gültigen Wert haben.

Hier ist die Lösung, beachten Sie, wie ich Bildelement in g Element eingepackt habe, mit ng-if-Anweisung. Das stellt sicher, dass wir nur dann ein Bild binden, wenn ein korrekter Wert verfügbar ist.

<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> 

Wie andere gesagt haben, ist auch die Reihenfolge der Attribute wichtig. Um sicherzustellen, dass AngularJS uns Bildelement zu binden, erlaubt, werden wir auch diese Ressource vertrauen müssen, habe ich es durch den Filter durchgeführt (es ist das einzige, in xlink: href-Attribut):

2

Für alle anderen mit Dieses Problem aufgrund des Angular/Angular UI Routers im HTML5-Modus brachte mir eine einfache Lösung, mit der Svg-Sprite-Icons mit ihrem xlink: href-Attribut und dem Tag arbeiten können.

Gist ist hier: https://gist.github.com/planetflash/4d9d66e924aae95f7618c03f2aabd4a3

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>