3

I'm attempting to bind SVG attributes using AngularJS. I have the following code for a resize handle of a shape:

// S handle.
var s_handle = d3.select(document.createElementNS("http://www.w3.org/2000/svg", "rect"))
    .attr("id", "s-resize")
    .attr("x", "{{(objects['" + id + "'].w - (scope.dragHandle.width / 2))}}")
    .attr("y", "{{(objects['" + id + "'].h - (scope.dragHandle.width / 2))}}")
    .attr(scope.dragHandle)
    .attr("cursor", "s-resize")
    .call(sresize);              

$compile(s_handle.node())(scope);
element.append(s_handle);

When I run this code, I get the following error:

Error: Invalid value for <rect> attribute x="{{(objects['9b320170-6365-4f40-801d-a7a5c6b936f9'].w - (scope.dragHandle.width / 2))}}" d3.min.js:1
Error: Invalid value for <rect> attribute y="{{(objects['9b320170-6365-4f40-801d-a7a5c6b936f9'].h - (scope.dragHandle.width / 2))}}" d3.min.js:1

I tried removing the append step to isolate the issue - and it looks like the issue actually happens when I set the x and y attributes, even before the Angular compile stage.

Note that I have this method working with another SVG object using the transform attribute, which natively accepts a string.

Has anyone run into this problem before? Are there any solutions? Thank you.

Edit: Been stepping through and it looks like $compile` isn't actually changing the element at all. Could this be because the element is invalid?

1 Answer 1

8

Looks like this was related to this issue: https://github.com/angular/angular.js/pull/2061

It was solved in that issue as well.

SVG elements use an XML-based schema, and are namespaced, and as such have validation rules. Certain attributes can't take an Angular interpolated directive because they expect a numeric value, and the browser validates this before Angular ever has a chance to catch it (even if the element is created and not appended to the DOM yet).

If anyone runs into this issue, hopefully this answer will help.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that was really helpful! Just to add a simplified version of the pull request discussion: when you want to do Angular interpolation on attributes of SVG elements, prepend the attribute name with ng-attr-
Beautiful, thanks! And thanks @ChrisLoer for summarizing. I've been banging my head on this for a few hours until I finally sorted that it was something in this domain. (No pun intended).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.