Search code examples
vue.jsfor-loopif-statementvuejs3pinia

Property 'campaign' was accessed during render but is not defined on instance


These are the issues i'm getting enter image description here

Here below is the code that produces the problems, this part in particular: enter image description here

When ever i;m trying to filter campaigns using company_id and product_id with v-if the problem occurs. Almost the same exact code works a few lines above filtering products. I have no idea what to do next. I tried refs and putting the mocked that into reactive variable and computeing it with a function but it didn;t work out.

<script setup>
    import CompanyItem from "./CompanyItem.vue";
    import ProductItem from "./ProductItem.vue";
    import CampaignItem from "./CampaignItem.vue";
    import { useCurrentCompanyStore } from "../stores/currentCompanyStore.js"
    import { useCurrentProductStore } from "../stores/currentProductStore.js"
    const companyStore = useCurrentCompanyStore();
    const productStore = useCurrentProductStore();
    const companies = 
    [
        {
            company_id: 1,
            name: 'Domain of Man',
            fund_balance: 100000,
            products_list: [
                {
                    product_id: 1,
                    name: 'gate'
                },
                {
                    product_id: 2,
                    name: 'exploration ship'
                },
                {
                    product_id: 3,
                    name: 'artifacts'
                }
            ]
        },
        {
            company_id: 2,
            name: 'Hegemony',
            fund_balance: 200000,
            products_list: [
                {
                    product_id: 1,
                    name: 'toothbrash'
                },
                {
                    product_id: 2,
                    name: 'ore'
                },
                {
                    product_id: 3,
                    name: 'food'
                }
            ]
        },
    ];
    const campaigns = [
        {
            campaign_id: 1,
            company_id: 1,
            product_id: 1,
            campaign_name: "Gates for everyone",
            keywords: [
                "one for each",
                "limited offer"
            ],
            bid_amount: 25000,
            status: true,
            town: "Tarnow",
            radius: "10"
        },
        {
            campaign_id: 2,
            company_id: 1,
            product_id: 3,
            campaign_name: "Get them while they last",
            keywords: [
                "rare",
                "one for each",
                "limited offer"
            ],
            bid_amount: 25000,
            status: false,
            town: "Tarnow",
            radius: "10"
        },
        {
            campaign_id: 3,
            company_id: 3,
            product_id: 1,
            campaign_name: "Let the shine power your ship",
            keywords: [
                "electricity",
                "green technology",
            ],
            bid_amount: 25000,
            status: true,
            town: "Tarnow",
            radius: "10"
        }
    ];
</script>

<template>
    <div class="container">
        <div class="companies" >
            <CompanyItem v-for="company in companies" v-bind:key="company.company_id" :company-id="company.company_id">
                <template #name>
                    {{ company.name }}
                </template>
                <template #budget>
                    {{ company.fund_balance }}
                </template>
            </CompanyItem>
        </div>
        <div class="products">
            <template v-for="company in companies">
                <ProductItem 
                    v-for="product in company.products_list" 
                    v-bind:key="product.product_id" 
                    :id="company.company_id" 
                    v-if="companyStore.companyId === company.company_id"
                    :product-id="product.product_id">
                    <template #name>
                        {{ product.name }}
                    </template>
                </ProductItem>
            </template>
        </div>
        <div class="campaigns">
            <CampaignItem 
                v-for="campaign in campaigns"
                v-if="companyStore.companyId === campaign.company_id"
                v-bind:key="campaign.campaign_id"
                :id="campaign.campaign_id"
                >
                <template #name>
                    {{campaign.campaign_name}}
                </template>
            </CampaignItem>
        </div>
    </div>
</template>

<style scoped>
.container {
    width: 100%;
    height: 100%;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: auto;
    grid-template-areas: 
    "companies products campaigns";
}

.companies {
    grid-area: companies;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.products {
    grid-area: products;
}

.campaigns {
    grid-area: campaigns;
}
</style>

Here are stores:

import { defineStore } from 'pinia'

export const useCurrentCompanyStore = defineStore({
  id: 'currentComapny',
  state: () => ({
    companyId: -1
  }),
  getters: {
    getCompanyId: (state) => state.companyId
  },
  actions: {
    change(newCompanyId) {
      this.companyId = newCompanyId;
    }
  }
})
import { defineStore } from 'pinia'

export const useCurrentProductStore = defineStore({
  id: 'currentProduct',
  state: () => ({
    productId: -1
  }),
  getters: {
    getCompanyId: (state) => state.productId
  },
  actions: {
    change(newProductId) {
      this.productId = newProductId;
    }
  }
})

Btw. if anybody wants to run it themself here is the git repo, its feature/frontend branch: https://github.com/kuborek2/campaign_planer


Solution

  • You must not use v-if and v-for on the same element because v-if will always be evaluated first due to implicit precedence.

    And exactly because of that, you are facing this error of undefined company_id as v-for is not executed yet and v-if is trying to access it.

    Make the changes as suggested below and it should fix your error.

    <CampaignItem 
       v-for="campaign in campaigns"
       :key="campaign.campaign_id"
       :id="campaign.campaign_id"
    >
       <template v-if="companyStore.companyId === campaign.company_id" #name>
           {{campaign.campaign_name}}
       </template>
    </CampaignItem>
    

    Click here for the reference