Reputation: 353
I feel like I need to combine v-for
and v-if
but I know that's not possible.
Basically, I want to render a child component for every object in a prop. But I need to parse those objects to extract data that I can pass to the child component as props and use to perform conditional rendering checks.
I can do this pretty simply in react, but not sure how to implement in Vue, I'd appreciate your insight.
React component:
import { Svg } from './styles'
import DirectedEdge from './directed-edge'
import Vertice from './vertice'
type Props = {
time: number
vertices: object
edges: object
bottomRight: array
}
// render the graph at a given time (time)
const Graph = ({ time, edges, vertices, bottomRight }: Props) => {
return (
<Svg viewBox={`0 0 ${bottomRight[0]} ${bottomRight[1]}`}>
{Object.entries(edges).map(([key, data]) => {
const [u, v] = JSON.parse(key)
return (
time >= data.timeRange[0] &&
time <= data.timeRange[1] &&
vertices[u]?.coord &&
vertices[v]?.coord && (
<DirectedEdge
key={key}
start={vertices[u].coord}
end={vertices[v].coord}
label={data.label}
/>
)
)
})}
{Object.entries(vertices).map(([key, data]) => {
return (
time >= data.times[0] && (
<Vertice
key={key}
center={data.coord}
label={data.label}
/>
)
)
})}
</Svg>
)
}
export default Graph
my edges prop data:
edges: {
"[0,10]": { label: 1, timeRange: [ 37, 54 ] },
"[0,1]": { label: 2, timeRange: [ 1, 34 ] }
}
vertices prop data:
vertices: {
coord: [ 368.75, 50 ] ,
label: "5" ,
memoized: false ,
times:[ 0, 36, 56 ]
}
Upvotes: 0
Views: 789
Reputation: 11037
You can use both v-for and v-if, you just have to use the v-for on a template
element. The template
element is somewhat similar to React Fragments.
I've converted your React code to Vue, though it might be closer to pseudo code as I haven't checked if it works.
<script>
export default {
props: {
time: Number,
edges: Object,
vertices: Object,
bottomRight: Array,
},
computed: {
edgeValues() {
return Object.entries(this.edges).map(([key, data]) => {
const [u, v] = JSON.parse(key);
return { u, v, data };
});
},
},
};
</script>
<template>
<svg :viewBox="`0 0 ${bottomRight[0]} ${bottomRight[1]}`">
<template v-for="{ u, v, data } in edgeData">
<directed-edge
v-if="
time >= data.timeRange[0] &&
time <= data.timeRange[1] &&
vertices[u] &&
vertices[u].coord &&
vertices[v] &&
vertices[v].coord
"
:key="u + v"
:start="vertices[u].coord"
:end="vertices[v].coord"
:label="data.label"
/>
</template>
<template v-for="(data, key) in edges">
<Vertice
v-if="time >= data.times[0]"
:key="key"
:center="data.coord"
:label="data.label"
/>
</template>
</svg>
</template>
Upvotes: 1