Reputation: 3411
I'd need to dynamically bind fill attribute of a SVG rect element but it doesn't work. Here is my simple VueJS component to demonstrate what I am trying to do (also available in codepen)
<template>
<div>
<!-- this works but id and fill attributes are hardcoded -->
<svg class="green" width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="gradient1">
<stop stop-color="red" offset="0%" />
<stop stop-color="blue" offset="100%" />
</linearGradient>
<rect width="100" height="50" fill="url(#gradient1)" />
</svg>
<!-- this doesn't work... -->
<svg class="green" width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
<linearGradient :id="myid">
<stop stop-color="red" offset="0%" />
<stop stop-color="blue" offset="100%" />
</linearGradient>
<rect width="100" height="50" :fill="myfill" />
</svg>
</div>
</template>
<script>
new Vue({
el: 'body',
data: {
title: 'Vuejs SVG binding example',
myid: 'gradient2',
myfill: 'url(#gradient2)'
},
});
</script>
Notice that fill
attribute uses url()
which takes element id as argument which complicates the thing. As far as I know the only way for fill
attribute to use linearGradient
defined in the same component is to reference it by element id
attribute.
The reason I am trying to do this is because I want to avoid hardcoding id
s inside components. Since I will have many instance of this component on the webpage, there will be multiple elements with same id
value which should not happen.
Upvotes: 3
Views: 2070
Reputation: 1512
Yes it is possible to do what want to do. I have done something a bit similar but with just a div not and not svg.
Bind a dynamic css class name to the svg and and put the fill in that class. this link shows how to us css for a css CSS - Style svg fill with class name
My proposed solution assumes are passing in some value to the component via props
<template>
...
<rect width="100" height="50" :class="myfill" />
...
</template>
<script>
new Vue({
el: 'body',
data: {
title: 'Vuejs SVG binding example',
myid: 'gradient2',
myfill: somePropYouPassedIn
},
});
</script>
On trying out your fiddle, I think your were doing the coding correctly, you were just using an old version of Vuejs (this I notice when I was trying to get your fiddle to work). Anyway, I could not get your pen to work with vue so I created a totally new fiddle here https://jsfiddle.net/nkalait/ohmzxb7L/
Code
<div>
{{ title }}
<!-- this works but id and fill attributes are hardcoded -->
<svg class="green" width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect width="100" height="50" :fill="gradient1" />
</svg>
<!-- this doesn't work... -->
<svg class="green" width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect width="100" height="50" :fill="gradient2" />
</svg>
// I HAVE PUT THE GRADIENTS IN THERE OWN SVG
<svg aria-hidden="true" focusable="false" style="width:0;height:0;position:absolute;">
<linearGradient id="gradient1">
<stop stop-color="yellow" offset="0%" />
<stop stop-color="blue" offset="100%" />
</linearGradient>
<linearGradient id="gradient2">
<stop stop-color="red" offset="0%" />
<stop stop-color="green" offset="100%" />
</linearGradient>
</svg>
</div>
Upvotes: 2