Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better SVG Support for namespaced attributes #2250

Closed
ledbruno opened this issue Sep 26, 2014 · 33 comments
Closed

Better SVG Support for namespaced attributes #2250

ledbruno opened this issue Sep 26, 2014 · 33 comments

Comments

@ledbruno
Copy link

We are trying to use React for a SVG document. But we are facing problems for namespaced attributes.

For instance, this element cant be constructed with React:

<image xlink:href="firefox.jpg" x="0" y="0" height="50px" width="50px"/>

We cant build a JSX for a xmlns:xlink attribute. Is there any way to solve this?

@ledbruno
Copy link
Author

The exception that is raised, when we try to put some namespaced attributes:
"Error: Namespace attributes are not supported. ReactJSX is not XML."

@edmspjp
Copy link

edmspjp commented Sep 28, 2014

I already faced the same issue for image element. I opened an issue and
meanwhile I'm using the following:

<svg dangerouslySetInnerHTML={

{__html:

"<image id=" + this.props.id + " x=" + this.props.x + " y=" +
this.props.y +

" width='"+ (this.props.width-20) +"' height='"+
(this.props.height-(this.props.text!=='none'?40:20)) +

"' fill='#90' stroke='#000' style='cursor:pointer' xlink:href='" +
this.props.image +

"'/>"

}

}/>

2014-09-28 15:20 GMT+01:00 Bruno Ledesma notifications@github.com:

The exception that is raised, when we try to put some namespaced
attributes:
"Error: Namespace attributes are not supported. ReactJSX is not XML."


Reply to this email directly or view it on GitHub
#2250 (comment).

Paulo Jorge Dias
: à procura do erro certo
: looking for the right error

@bobby
Copy link

bobby commented Apr 10, 2015

+1 on this. React could be a really great platform for doing SVG, but it's hard to use SVG to full effect without xlink:href and friends.

@dujuanxian
Copy link

Hi @edmspjp I had the same issue, but it seems add dangerouslySetInnerHTML to tag still has the same problem. And take the whole svg tag as dangerouslySetInnerHTML attr to its parent tag works for me. I am not sure if you met the problem before.

var svgTag='<svg><image..></svg>';

<div dangerouslySetInnerHTML={__html: svgTag} />

@lennerd
Copy link

lennerd commented Jul 5, 2015

Any updates on or further plans for supporting SVG namespaced elements and attributes?

@willhackett
Copy link

Seems it's still necessary to implement SVGs using dangerouslySetInnerHTML.

@lennerd
Copy link

lennerd commented Jul 27, 2015

I can recommend to use a combination of d3 and react. When ever I need to use namespaced attributes I use d3 in the componentDidMount method.

@ghost
Copy link

ghost commented Jul 29, 2015

+1 for this request. I need React to render an inline SVG that has an image inside a clipping path, and it's getting hung on the xmlns:xlink="http://www.w3.org/1999/xlink" attr in the <svg> tag.

@ghost
Copy link

ghost commented Jul 29, 2015

@dujuanxian's workaround helped me get through this, provided double (not single) braces are used, of course:

var svgString = '<svg /* React-unfriendly code here... */ </svg>';
<div dangerouslySetInnerHTML={{ __html: svgString }} />

@lennerd
Copy link

lennerd commented Jul 29, 2015

Just to show an example using d3 for the non-react-svg-stuff:

https://github.com/FH-Potsdam/shifted-maps/blob/master/app/client/components/place-map.js#L21-L40

I used d3 here, because React is not able to set href attribute of image tags.

@Nukesor
Copy link

Nukesor commented Sep 1, 2015

+1 Any updates on this? Thx for the workaround. Hope it'll work until this is fixed.

@edmspjp
Copy link

edmspjp commented Sep 1, 2015

See in How SVG Fragment Identifiers Work
https://css-tricks.com/svg-fragment-identifiers-work/ a different technic.

2015-07-29 23:12 GMT+01:00 Lennart Hildebrandt notifications@github.com:

Just to show an example using d3 for the non-react-svg-stuff:

https://github.com/FH-Potsdam/shifted-maps/blob/master/app/client/components/place-map.js#L21-L40

I used d3 here, because React is not able to set href attribute of image
tags.


Reply to this email directly or view it on GitHub
#2250 (comment).

Paulo Jorge Dias
: à procura do erro certo
: looking for the right error

@edvinerikson
Copy link
Contributor

In the master branch I managed to get namespaced attributes to work by using camelCase.
<svg xlinkHref="http://i.imgur.com/w7GCRPb.png" /> renders to <svg xlink:href="http://i.imgur.com/w7GCRPb.png" />

@lennerd
Copy link

lennerd commented Sep 1, 2015

Do you also get the proper namespace attribute for the namespace itself?

@edvinerikson
Copy link
Contributor

Not quite sure I understand what you mean. Can you give me an explanation/example?

@lennerd
Copy link

lennerd commented Sep 1, 2015

To be able to get links working, you also need an attribute for the namespace itself.

<svg width="800" height="600">
  <a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.github.com/"><!-- ... --></a>
</svg>

Does React handle this in your example?

@edvinerikson
Copy link
Contributor

No, it does only pass xlink:href to the DOM node.

@sophiebits
Copy link
Collaborator

@lennerd My understanding is that the xmlns:xlink is not required in HTML.

@edvinerikson
Copy link
Contributor

After looking through the SVG config and some tests it seems like the namespace is passed to the DOM node through the setAttributeNS method.

SVGDOMPropertyConfig.js
DOMPropertyOperations-test.js

@lennerd
Copy link

lennerd commented Sep 1, 2015

Sounds promising. Would be great to remove the d3 dependency.

@sophiebits
Copy link
Collaborator

Yes, as xlinkHref this should work in the upcoming 0.14 release.

palfrey added a commit to palfrey/pyrexia that referenced this issue Sep 27, 2015
Image embed doesn't work with React 0.13
facebook/react#2250

This branch upgrades to 0.14-rc1, which breaks Reagent
reagent-project/reagent#184
@mijamo
Copy link

mijamo commented Dec 2, 2015

xmlns:xlink is not required in HTML only if all the SVG is inline, but it is necessary for some tricky case: In my case, I need to have an image inside defs, to be used then by and to do that xmlns:xlink is apparently necessary.

@greypants
Copy link

Just confirming that xlinkHref does work in the 0.14.x releases! Hooray.

@BryceHayden
Copy link

BryceHayden commented May 17, 2016

I'm still getting this error, even when using react 0.14.x or the newer react 15.0.2. I'm not sure if I'm just missing something else that needs to be updated. I'm writing a library so I'm only using react, not react-dom...I'm not sure if it's babel or something else.

Here's the code:

import React, { PropTypes } from 'react'
import {doesBrowserSupportSVG} from '../../utils/doesBrowserSupportSvg.js';
var empty_png = require('../../assests/images/star-empty.png');
var whole_png = require('../../assests/images/star-whole.png');
var half_png = require('../../assests/images/star-half.png');

class RenderIcon extends React.Component {
  static propTypes = {
    data: PropTypes.shape({
      fill: PropTypes.oneOf(['whole', 'half', 'empty']).isRequired,
      size: PropTypes.string,
      cursor: PropTypes.string
    })
  };

  constructor(props, context) {
    super(props, context);
    const { size, cursor } = this.props;
    const SIZE = size ? size : '16px';
    const CURSOR = cursor ? cursor : 'auto';
    // options.fill ? options.fill : 'empty';

    this.state = {
      svgStyle: {
        cursor: CURSOR,
        fontSize: SIZE,
        width: SIZE,
        height: SIZE,
        lineHeight: SIZE,
        overflow: 'hidden'
      }
    }
  }

  render() {
    console.log('icon ----> ', `#star-${this.props.data.fill}`);
    if (doesBrowserSupportSVG()) {
      return (
        <svg style={this.state.svgStyle}>
          <use xlink:href={`#star-${this.props.data.fill}`} />
        </svg>
      );
    } else {
      switch (this.props.data.fill) {
        case "whole":
          return <img src={whole_png}/>
        case "half":
          return <img src={half_png}/>
        default:
          return <img src={empty_png}/>
      }
    }
  }
}



export default RenderIcon;

And here's my package.json file:


  "name": "ui-elements",
  "version": "0.6.0",
  "description": "A collect of commonly used ui elements/components written in react and built using webpack",
  "main": "./dist/ui.elements.js",
  "scripts": {
    "build:examples": "babel-node --presets es2015 examples/build.js",
    "build:umd": "webpack src/index.js dist/ui.elements.js --config webpack.config.development.js",
    "build:umd:min": "webpack src/index.js dist/ui.elements.min.js --config webpack.config.production.js",
    "watch": "npm run build:umd -- --watch",
    "build": "npm run build:umd && npm run build:umd:min",
    "check": "npm run lint && npm run test",
    "clean": "rimraf lib dist coverage",
    "lint": "eslint src test examples",
    "preversion": "npm run clean && npm run check",
    "postversion": "git push && git push --tags && npm run clean",
    "prepublish": "npm run clean && npm run build",
    "test": "mocha --compilers js:babel/register --recursive",
    "test:examples": "babel-node examples/tests.js",
    "test:watch": "npm test -- --watch",
    "test:cov": "babel-node $(npm bin)/isparta cover $(npm bin)/_mocha -- --recursive",
    "version": "npm run build"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/QuietOmen/ui-elements.git"
  },
  "keywords": [
    "ui",
    "components",
    "elements",
    "react",
    "rating",
    "star",
    "button",
    "dropdown",
    "modal"
  ],
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/QuietOmen/ui-elements/issues"
  },
  "homepage": "http://quietomen.github.io/ui-elements",
  "peerDependencies": {
    "react": ">15.0.2"
  },
  "devDependencies": {
    "babel-cli": "^6.4.5",
    "babel-core": "^6.4.5",
    "babel-eslint": "^6.0.4",
    "babel-loader": "^6.2.1",
    "babel-plugin-flow-comments": "^6.3.19",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-preset-es2015": "^6.0.0",
    "babel-preset-react": "^6.0.0",
    "babel-preset-stage-0": "^6.0.0",
    "chai": "^3.2.0",
    "css-loader": "^0.23.1",
    "eslint": "^2.10.2",
    "eslint-config-airbnb": "9.0.1",
    "eslint-plugin-import": "^1.8.0",
    "eslint-plugin-jsx-a11y": "^1.2.0",
    "eslint-plugin-react": "^5.1.1",
    "expect": "^1.13.4",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.8.5",
    "isparta": "^4.0.0",
    "mocha": "^2.3.4",
    "node-libs-browser": "^1.0.0",
    "node-sass": "^3.4.2",
    "postcss-loader": "^0.9.1",
    "react": "^15.0.2",
    "rimraf": "^2.5.0",
    "sass-loader": "^3.1.2",
    "skin-deep": "^0.16.0",
    "style-loader": "^0.13.0",
    "url-loader": "^0.5.7",
    "webpack": "^1.12.11"
  },
  "npmName": "ui-elements",
  "npmFileMap": [
    {
      "basePath": "/dist/",
      "files": [
        "*.js"
      ]
    }
  ]
}

and finally the error (which is the same as others were getting):

ERROR in ./src/components/render-rating/index.js
Module build failed: SyntaxError: /Users/bhayden/Documents/personal/ui-elements/src/components/render-rating/index.js: Namespace tags are not supported. ReactJSX is not XML.

@zpao
Copy link
Member

zpao commented May 17, 2016

@QuietOmen you want <use xlinkHref= not <use xlink:href=

@BryceHayden
Copy link

@zpao thanks, for some reason I missed that commented above, so thanks for repeating it.

@kevinSuttle
Copy link
Contributor

Apologies if I missed this somewhere, but what about styling SVG inline?

<style type="text/css" >

      <![CDATA[
       circle {
         stroke: #006600;
         fill:   #cc0000;
    }

      ]]>
    </style>

@zpao
Copy link
Member

zpao commented Jun 29, 2016

<style> needs to use dangerouslySetInnerHTML (and you probably always needed to if you were putting them inline).

<style type="text/css" dangerouslySetInnerHTML={{__html: `
  <![CDATA[
    circle {
      stroke: #006600;
      fill:   #cc0000;
    }
  ]]>
`}}/>

@kevinSuttle
Copy link
Contributor

@zpao But then it's only static, though, right? Like, you can't eval props in there?

e.g.

stroke: `${props.color}`
stroke: {props.color}

@gaearon
Copy link
Collaborator

gaearon commented Jun 29, 2016

@kevinSuttle

What you pass is just a string. You can generate the string dynamically—either with template literals or good ol’ concatenation.

<style type="text/css" dangerouslySetInnerHTML={{__html: `
  <![CDATA[
    circle {
      stroke: ${props.color};
      fill:   #cc0000;
    }
  ]]>
`}}/>

should work fine.

@aweary
Copy link
Contributor

aweary commented Jun 29, 2016

Here's a JSFiddle with a working example: https://jsfiddle.net/yp0q6okn/

@saulwolfdev
Copy link

A mi me funciono reemplazando xmlns:xlink por xlinkHref y elimine un atributo mas xml:space="preserve" con eso me ando perfecto la referencia lo tome de un pagina

https://itnext.io/using-react-for-xml-svg-470792625278

@PachVerb
Copy link

PachVerb commented May 2, 2022

@dujuanxian's workaround helped me get through this, provided double (not single) braces are used, of course:

var svgString = '<svg /* React-unfriendly code here... */ </svg>';
<div dangerouslySetInnerHTML={{ __html: svgString }} />

it's work for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests