I want to create a list of actions (each of which is a component) conditionally if the object variable store.plan
is not empty, I have tried v-if
which works well for rendering but not for creating the component.
I get an error:
Uncaught (in promise) TypeError: action is undefined
The full code of this component can be found here .
Can you please tell me how can I handle this problem? thanks in advance.
<template>
<div class="planlist" v-if="parse">
<ul id="planOl">
<Action
v-for="action in store.plan"
:action_id="action.act_id"
:actor="action.actor"
:color="action.color"
:size="action.size"
:lego_name="action.lego"
:pick_pos="action.pick"
:place_pos="action.place"
:blocked="action.blocked"
:status="action.status"
:key="action.act_id"
/>
</ul>
</div>
</template>
<script>
import Action from '../components/Action.vue';
import { store } from '../js/store.js'
export default {
name: 'Plan',
data() {
return {
store,
}
},
computed: {
parse() {
if (store.plan.length > 0) {
return true;
}
return false;
}
},
components: {Action}
}
</script>
Did you try with optional chaining
:
parse() {
return store?.plan?.length > 0 ? true : false
}
and don't mix v-if and v-for. Try to create wrapper div with v-if around your component:
<ul id="planOl">
<div v-if="parse">
<Action
v-for="action in store.plan"
:action_id="action.act_id"
:actor="action.actor"
:color="action.color"
:size="action.size"
:lego_name="action.lego"
:pick_pos="action.pick"
:place_pos="action.place"
:blocked="action.blocked"
:status="action.status"
:key="action.act_id"
/>
</div>
</ul>
It is recommended not to use v-if
and v-for
directives together on the same element due to the syntax ambiguity.
As per your code, Computed property parse
is used to check the length of an array. You can move the v-if to a container
element (eg ul
).
In template :
<ul id="planOl" v-if="parse">
<Action v-for="action in store.plan">...</Action>
</ul>
Script :
computed: {
parse() {
return store.plan.length > 0 ? true : false;
}
}
store.plan
to a computed property to use inside the template and parse
property.store.plan.length
from the computed property will do the job too instead of returning true and false based on condition.v-if
just outside the Action
component, you can use template
to do this. No need for an extra element.So, below changes can help fixing the issues-
<template>
<div class="planlist">
<ul id="planOl">
<template v-if="parse">
<Action
v-for="action in plan"
:key="action.act_id"
:action_id="action.act_id"
:actor="action.actor"
:color="action.color"
:size="action.size"
:lego_name="action.lego"
:pick_pos="action.pick"
:place_pos="action.place"
:blocked="action.blocked"
:status="action.status"
/>
</template>
</ul>
</div>
</template>
<script>
import Action from "../components/Action.vue";
import { store } from "../js/store.js";
export default {
name: "Plan",
components: {
Action,
},
computed: {
// A computed property to access the plan ()
plan() {
return store.plan;
},
parse() {
/**
* 1. The plan should be available (not null or empty or undefined)
* 2. The plan should be an array so length property can be applied
* 3. If its an array then it should have data (length in other words)
*/
return this.plan && Array.isArray(this.plan) && this.plan.length;
},
},
};
</script>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.