Reputation: 81
I want to take the index value of v-for (which is in path tag) as a parameter in a function stateData(index)
defined in computed property in Vue. I have tried to do this by v-model="stateData[index]"
but the console box is showing an error that path tag is not supporting v-model(you can see by running the snippet).
Does anyone have any idea?
var app = new Vue({
el: "#app",
data(){
return {
statesJson: null,
}
},
methods:{
axiosCall() {
axios.all([axios.get('https://raw.githubusercontent.com/smlab-niser/CRiAPGraph/master/India.json')])
.then(axios.spread((user1) => (
this.statesJson=user1.data
)))
.catch(error => {
console.log(error)
})
},
},
computed: {
// Typical projection for showing all states scaled and positioned appropriately
projection () {
return d3.geoMercator().scale(900).translate([-1030, 700])
},
// Function for converting GPS coordinates into path coordinates
pathGenerator () {
return d3.geoPath().projection(this.projection)
},
// Combine the states GeoJSON with a rank-based gradient
stateData (index) {
return this.statesJson ? this.statesJson.features.map(feature => {
return {
feature
}
}):[]
}
},
created:function(index){
this.axiosCall();
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<svg id="svg" ref="svg" height="600" width="510">
<path class="bar" v-for="(state, index) in stateData" v-model="stateData[index]" :d="pathGenerator(state.feature)" :style="{
stroke: 'darkslategray'
}">
</path>
</svg>
</div>
</div>
Upvotes: 0
Views: 665
Reputation: 1621
See below an example on how to use objects in for loops. I've simplified your code, I don't think there is any need to use the index, as you can see below.
I've removed the statesData
function, since it basically maps an array to an array, so you can simplify that by accessing the statesJson.features
object immediately on the v-for
.
I than use the state
from the v-for
as input in a new calcFill
function. Inside that function, which is in the methods
propery of your Vue component, you can calculate the gradient by rank. Using the state
object, we can now simply access state.rank
immediately, no need for using the index
.
This is just an example showing that sometimes it's better to keep objects as they are and work with those object directly as method parameters.
When you run the snippet, you see each state is now color coded by it's rank.
var app = new Vue({
el: "#app",
data(){
return {
statesJson: null,
}
},
methods:{
axiosCall() {
axios.all([axios.get('https://raw.githubusercontent.com/smlab-niser/CRiAPGraph/master/India.json')])
.then(axios.spread((user1) => (
this.statesJson=user1.data
)))
.catch(error => {
console.log(error)
})
},
calcFill(state) { // Here you can do your rank based gradient
let l = this.statesJson.features.length
let rank = state.rank
let num = (rank / l) * 255 // Calculate color code
return 'rgb(' + num + ', ' + num + ', ' + num + ')'
}
},
computed: {
// Typical projection for showing all states scaled and positioned appropriately
projection () {
return d3.geoMercator().scale(900).translate([-1030, 700])
},
// Function for converting GPS coordinates into path coordinates
pathGenerator () {
return d3.geoPath().projection(this.projection)
}
},
created:function(index){
this.axiosCall();
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<!-- Only show if statesJson is loaded -->
<div v-if="statesJson">
<svg id="svg" ref="svg" height="600" width="510">
<!-- Loop directly on statesJson, keeping the object -->
<path class="bar" v-for="(state, index) in statesJson.features" :d="pathGenerator(state)" :style="{
stroke: 'darkslategray', fill: calcFill(state)
}">
</path>
</svg>
</div>
</div>
Upvotes: 1