7

I am trying to render some SVG with AngularJS but I can't dynamically change the viewbox of the svg element.

Angular renders a 'viewbox' attribute, but browsers expect a 'viewBox' attribute. So the result is:

<svg height="151px" width="1366px" viewBox="{{ mapViewbox }}" viewbox="-183 425 1366 151">

How can I get the result I expect:

<svg height="151px" width="1366px" viewBox="-183 425 1366 151">

Thanks.

GKFX
  • 1,338
  • 1
  • 11
  • 27
lud
  • 1,673
  • 14
  • 30

4 Answers4

16

See if this directive works:

app.directive('vbox', function() {
  return {
    link: function(scope, element, attrs) {
      attrs.$observe('vbox', function(value) {
        element.attr('viewBox', value);
      })
    }
  };
});

HTML:

<svg height="151px" width="1366px" vbox="{{ mapViewbox }}">

Plnkr. You'll need to "Inspect element" or "View source" to see the svg tag.

Update: If your app includes jQuery, see Does the attr() in jQuery force lowercase?

@Niahoo found that this worked if jQuery is included (he made an edit to this post, but for some reason, other SO moderators rejected it... I liked it though, so here it is):

 element.get(0).setAttribute("viewBox", value);
Community
  • 1
  • 1
Mark Rajcok
  • 348,511
  • 112
  • 482
  • 482
  • Hi, thank you but it doesn't work. I've tried with different names to be sure. element.attr sets lowercase attributes names everytime. – lud Jan 30 '13 at 12:38
  • 1
    You made me find that jQuery was the reason, and thanks for pointing out directives. It seems very powerful. – lud Jan 30 '13 at 12:56
  • Very annoying! element.get(0).setAttribute("viewBox", value); instead of element.attr('viewBox', value) works with angular 1.4.7 – TroodoN-Mike Nov 22 '15 at 12:38
12

Looking for a solution myself I came upon this answer the correct way to achieve this is by using pattern transform ng-attr-view_box

probinson
  • 371
  • 2
  • 8
1

The proposed solution didn't work. I'm no javascript pro but this did.

app.directive('vbox', function () {
    return {
        link: function (scope, element, attrs) {
            attrs.$observe('vbox', function (value) {
                element.context.setAttribute('viewBox', value);
            })
        }
    };
});
  • Hi, you got to read the full answer. It works, used the same solution as you give ( but with ̉element.get(0) ) – lud Mar 01 '14 at 18:52
0

Something like this in a directive linking function (imagine a scope with the variables used):

        var svg = $compile(
            $interpolate('<svg width="{{w}}" height="{{h}}" class="vis-sample" id="vis-sample-{{$id}}" viewBox="0 0 {{w}} {{h}}" preserveAspectRatio="xMidYMid meet"></svg>')( scope )
        )( scope );

The key is using $interpolate before $compile. There has to be a better solution but this is the most direct option I know of for single-pass templates where the variables are all available initially.

jimmont
  • 1,699
  • 21
  • 24