3
votes

I have a problem using Ember/Handlebars with SVG elements:

Controller:

display: function() {
  this.set('isDisplayed', true);
}

Template:

<button {{action display}}>Display</button>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  {{#if isDisplayed}}
    <text>Foo</text>
  {{/if}}
</svg>

When I click on the button, I get this error: Uncaught Error: NotSupportedError: DOM Exception 9 (ember.js:18709: Metamorph#htmlFunc on the createContextualFragment line)

Is Ember/Handlebars correctly handling SVG ? What should I do to make this work ?

[EDIT] A little JSBin to see this in action: http://jsbin.com/onejec/2/edit

1
I've edited my answer, have a look. Hope this helps.intuitivepixel

1 Answers

2
votes

Handling SVG is somewhat tricky if you want to rely on ember to render DOM elements for you. But as a starting point you could consider creating a svg wrapper like this:

App.SVGView = Ember.View.extend({
  tagName: 'svg',
  attributeBindings: ['height', 'width', 'xmlns', 'version'],
  height: 100,
  width: 100,
  xmlns: 'http://www.w3.org/2000/svg',
  version: '1.1',
  render: function(buffer) {
    return buffer.push('<text x="20" y="20" font-family="sans-serif" font-size="20px">Foo!</text>');
  }
});

And then hook into the render method to inject your text tag.

This results in the following HTML markup:

<svg id="svg_view" class="ember-view" height="100" width="100" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <text x="20" y="20" font-family="sans-serif" font-size="20px">Foo!</text>
</svg>

Here also your working modified jsbin.

Edit If you need to re-render the view based on some properties that might change you could add an observer to the correspondent property and call this.rerender() inside that method, something like this:

App.SVGView = Ember.View.extend({
  tagName: 'svg',
  attributeBindings: ['height', 'width', 'xmlns', 'version'],
  height: 100,
  width: 100,
  xmlns: 'http://www.w3.org/2000/svg',
  version: '1.1',
  render: function(buffer) {
    return buffer.push('<text x="20" y="20" font-family="sans-serif" font-size="20px">Foo!</text>');
  },
  myProperty: 'This value might change',
  myPropertyChanged: function() {
    this.rerender();
  }.observes('myProperty')
});

Hope it helps.