Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

JackJones's avatar

Data property is null despite being updated in axios request

I can't get a data property to not be null when I'm using axios, I don't know whether it is because the request takes time and the value is set before it is run, I just don't know

The property in question is responseBaseCalendarShifts

data() {
        return {
            dateList: [],
            year: new Date().getFullYear(),
            monthNumbers: Array.from(Array(12).keys()),
            lastDateClicked: null,
            responseBaseCalendarShifts: null
        }
    },

        getDates() {
            let dateArray = [];
            let currentDate = new Date(this.year, 0, 1);

            this.getBaseCalendarShifts();
            let baseCalendarShifts = this.responseBaseCalendarShifts;
            console.log(this.responseBaseCalendarShifts)

            while (currentDate <= new Date(this.year, 11, 31)) {
                let dateProperties = {
                    id: currentDate.getFullYear() + "-" + currentDate.getMonth() + "-" + currentDate.getDate(),
                    date: currentDate,
                    year: currentDate.getFullYear(),
                    month: currentDate.getMonth(),
                    day: currentDate.getDate(),
                    dayOfWeek: currentDate.getDay(),
                    active: false
                };

                dateArray.push(dateProperties);

                currentDate = currentDate.addDays(1);
            }

            this.dateList = dateArray;
        },

        getBaseCalendarShifts() {
            axios.post(this.route, null, {
                params: {
                    year: this.year
                }
            })
                .then(response => {
                    this.responseBaseCalendarShifts = response.data;
                })
                .catch(function (error) {
                    flash('error', error);
                })
        }
    },

Please help

0 likes
4 replies
besartzeka's avatar

It looks like you're having issues due to the asynchronous nature of the Axios request. When you call getBaseCalendarShifts(), it initiates an HTTP request, but the response might not be available immediately. Meanwhile, your code continues to execute, and this.responseBaseCalendarShifts remains null until the response is received.

I'm pasting a modified version of your code, that I got from CHATGPT:

getDates() {
    let dateArray = [];
    let currentDate = new Date(this.year, 0, 1);

    this.getBaseCalendarShifts().then(() => {
        // Now you can access responseBaseCalendarShifts safely here
        let baseCalendarShifts = this.responseBaseCalendarShifts;
        console.log(this.responseBaseCalendarShifts);

        while (currentDate <= new Date(this.year, 11, 31)) {
            let dateProperties = {
                id: currentDate.getFullYear() + "-" + currentDate.getMonth() + "-" + currentDate.getDate(),
                date: currentDate,
                year: currentDate.getFullYear(),
                month: currentDate.getMonth(),
                day: currentDate.getDate(),
                dayOfWeek: currentDate.getDay(),
                active: false
            };

            dateArray.push(dateProperties);

            currentDate = currentDate.addDays(1);
        }

        this.dateList = dateArray;
    });
},

getBaseCalendarShifts() {
    return axios.post(this.route, null, {
        params: {
            year: this.year
        }
    })
    .then(response => {
        this.responseBaseCalendarShifts = response.data;
    })
    .catch(error => {
        flash('error', error);
    });
}
gych's avatar
gych
Best Answer
Level 29

Try to use async with await

    async getDates() {
            let dateArray = [];
            let currentDate = new Date(this.year, 0, 1);

            const baseCalendarShifts = await this.getBaseCalendarShifts();

			// rest of your code
async getBaseCalendarShifts() {
    try {
        const response = await axios.post(this.route, null, {
            params: {
                year: this.year
            }
        });
        return response.data; 
    } catch (error) {
        flash('error', error);
    }
}

When you use this approach you can remove this.responseBaseCalendarShifts

JackJones's avatar

I tried but now other methods are failing, there is a bit too much code for me to paste so I will have to try and whittle it down

I've tried adding

    async created() {
        await this.getDates();
    },

But it still says certain properties aren't defined

Here is the whole code

import CalendarMonth from "./CalendarMonth.js";
import CalendarShifts from "./CalendarShifts.js";

export default {
    components: {CalendarMonth, CalendarShifts},

    template: `
        <fieldset class="border rounded pb-2 my-4 border-gray-300">
            <legend class="mx-2 text-sky-800">Select Days</legend>

            <button v-for="(day, key) in dayTexts"
                    @click="selectDays(key + 1 === 7 ? 0 : key + 1)"
                    :key="day"
                    class="rounded bg-slate-800 text-white px-2 py-0 mx-1 hover:bg-slate-700"
            >{{ day }}
            </button>
            <button class="rounded bg-orange-700 text-white px-2 py-0 mx-1 hover:bg-orange-600" @click="clearActive">
                Clear
            </button>
        </fieldset>

        <div class="flex flex-wrap items-center justify-center text-gray-900 text-3xl my-2">
            <button @click="changeYear('decrease')" class="border border-gray-300 px-2 py-0 bg-gray-100 text-gray-800">
                <svg class="w-[30px] h-[30px] text-gray-800" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
                     width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
                    <path fill-rule="evenodd"
                          d="M13.729 5.575c1.304-1.074 3.27-.146 3.27 1.544v9.762c0 1.69-1.966 2.618-3.27 1.544l-5.927-4.881a2 2 0 0 1 0-3.088l5.927-4.88Z"
                          clip-rule="evenodd"/>
                </svg>
            </button>
            <span class="mx-6 font-bold">{{ year }}</span>
            <button @click="changeYear('increase')" class="border border-gray-300 px-2 py-0 bg-gray-100 text-gray-800">
                <svg class="w-[30px] h-[30px] text-gray-800" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
                     width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
                    <path fill-rule="evenodd"
                          d="M10.271 5.575C8.967 4.501 7 5.43 7 7.12v9.762c0 1.69 1.967 2.618 3.271 1.544l5.927-4.881a2 2 0 0 0 0-3.088l-5.927-4.88Z"
                          clip-rule="evenodd"/>
                </svg>
            </button>
        </div>

        <div class="flex">
            <div class="grow grid md:grid-cols-2 lg:grid-cols-3 gap-4">
                <calendar-month
                    v-for="monthNumber in monthNumbers"
                    :monthNumber="monthNumber"
                    :dates="filterMonth(monthNumber)"
                    :dayTexts="dayTexts"
                    :monthTexts="monthTexts"
                    :key="monthNumber"
                    @single-click="singleClick"
                    @shift-click="shiftClick"
                    @ctrl-click="ctrlClick"
                ></calendar-month>
            </div>

            <calendar-shifts :date="activeList[0]" v-if="activeList.length"></calendar-shifts>

        </div>
    `,

    data() {
        return {
            dateList: [],
            year: new Date().getFullYear(),
            monthNumbers: Array.from(Array(12).keys()),
            lastDateClicked: null
        }
    },

    props: {
        route: String,
        dayTexts: Array,
        monthTexts: Array
    },

    created() {
        this.getDates();
    },

    methods: {
        clearActive() {
            this.activeList.forEach(a => {
                a.active = false;
            });
        },

        singleClick(date) {
            this.clearActive();

            date.active = true;

            this.lastDateClicked = date;
        },

        shiftClick(date) {
            if (this.activeList.length === 0) {
                this.singleClick(date)
            } else {
                let minDate = null;
                let maxDate = null;

                if (date.date <= this.lastDateClicked.date) {
                    minDate = date.date;
                    maxDate = this.lastDateClicked.date;
                } else {
                    minDate = this.lastDateClicked.date;
                    maxDate = date.date;
                }

                this.dateList.forEach(a => {
                    if (a.date >= minDate && a.date <= maxDate) {
                        a.active = true;
                    }
                });
            }
        },

        ctrlClick(date) {
            date.active = !date.active

            if (date.active === true) {
                this.lastDateClicked = date;
            }
        },

        changeYear(direction) {
            if (direction === 'decrease' && this.year > 2020) {
                this.year--;
            } else if (direction === 'increase' && this.year < 2050) {
                this.year++;
            }

            this.getDates();
        },

        getDates() {
            let dateArray = [];
            let currentDate = new Date(this.year, 0, 1);
            // this.getBaseCalendarShifts();


            while (currentDate <= new Date(this.year, 11, 31)) {
                let merged = {
                    id: currentDate.getFullYear() + "-" + currentDate.getMonth() + "-" + currentDate.getDate(),
                    date: currentDate,
                    year: currentDate.getFullYear(),
                    month: currentDate.getMonth(),
                    day: currentDate.getDate(),
                    dayOfWeek: currentDate.getDay(),
                    active: false
                };

                dateArray.push(merged);

                currentDate = currentDate.addDays(1);
            }

            this.dateList = dateArray;
        },

        filterMonth(month) {
            return this.dateList.filter(a => a.month === month);
        },

        selectDays(day) {
            this.dateList.forEach(a => {
                if (a.dayOfWeek === day) {
                    a.active = true;
                }
            });
        }
    },



    computed: {
        activeList() {
            return this.dateList.filter(a => a.active === true);
        }
    }
}

If I add the async stuff then the :dates property on the <calendar-month> component doesn't work

JackJones's avatar

I used the answer above (I've marked it best answer, I had to make a tiny adjustment to my template:

<calendar-month
                    v-if="dateList.length"

Now it is working as expected

Please or to participate in this conversation.