I am working on a small project to get into Vue js. It is supposed to be a Habittracker. I currently have a bug, if you reload the page and add new habits, my function that is supposed to change the background does not work properly.
here it shows the bug and here is how my array looks:
0
:
{id: 0, title: "1", ready: false}
1
:
{id: 1, title: "123", ready: false}
2
:
{id: 2, title: "123", ready: false}
3
:
{id: 0, title: "123", ready: true}
I get why it is not working because I am using a counter to assign the id, which resets to 0 when reloaded.
<div v-for="(habit, index) in habits" :key="habit.id">
<q-card :id="habit.id" ref="card">
<q-card-section>
<q-checkbox
id="checkbox"
v-model="habit.ready"
@click="changeToTransparent(habit)"
>
</q-checkbox>
{{ habit.title }}
<q-btn-dropdown flat icon="more_horiz">
<q-list>
<q-item clickable v-close-popup @click="deletehabit(index)">
<q-item-section>
<q-item-label>Delete</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="edithabitbutton(index)">
<q-item-section>
<q-item-label>Edit</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</q-card-section>
</q-card>
<div>
let counter = 0;
const habits = ref([]);
const addHabit = () => {
habits.value.push({ id: counter , title: habittitle.value, ready: false });
savetolocalstorage();
habittitle.value = "";
};
const changeToTransparent = (habit) => {
if(document.getElementById(habit.id) != null) {
if (habit.ready) {
document.getElementById(habit.id).style.backgroundColor =
"rgba(170,193,200,0.25)";
savetolocalstorage();
} else {
document.getElementById(habit.id).style.backgroundColor = "";
savetolocalstorage();
}
}
}
Any ideas on how I could fix this?
CodePudding user response:
You need to load your localStorage and set the length to the counter value. I made a working example here. I also improved your code so that it's more in line with Vue's concepts. As @Rahul Purohit pointed out, you will need to JSON.stringify
the result when saving and JSON.parse
it when loading.
<template>
<q-input label="Title" v-model="habitTitle" />
<q-btn label="Add habit" @click="addHabit" />
<div v-for="(habit, index) in habits" :key="habit.id">
<q-card
:id="habit.id"
:ref="(el) => (cardRefs[habit.id] = el)"
>
<q-card-section>
<q-checkbox
id="checkbox"
v-model="habit.ready"
@click="changeToTransparent(habit)"
>
</q-checkbox>
{{ habit.id }} {{ habit.title }}
<q-btn-dropdown flat icon="more_horiz">
<q-list>
<q-item clickable v-close-popup @click="deletehabit(index)">
<q-item-section>
<q-item-label>Delete</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="edithabitbutton(index)">
<q-item-section>
<q-item-label>Edit</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</q-card-section>
</q-card>
</div>
</template>
<script setup>
const { ref, onMounted } = require("vue");
// it can be just a let.
const counter = ref(0);
const habits = ref([]);
const habitTitle = ref("test");
const cardRefs = ref({});
const saveToLocalStorage = () => console.log("saved");
const addHabit = () => {
habits.value.push({
id: counter.value ,
title: habitTitle.value,
ready: false,
});
saveToLocalStorage();
habitTitle.value = "";
};
const changeToTransparent = (habit) => {
if (cardRefs.value[habit.id] != null) {
if (habit.ready) {
cardRefs.value[habit.id].$el.style.backgroundColor =
"rgba(170,193,200,0.25)";
saveToLocalStorage();
} else {
cardRefs.value[habit.id].$el.style.backgroundColor = "";
saveToLocalStorage();
}
}
};
onMounted(() => {
// Load habits from localStorage
// This is just an example
habits.value = [
{
id: 0,
title: "Testing new habit",
ready: true,
},
{
id: 1,
title: "Testing new habit",
ready: false,
},
{
id: 2,
title: "Testing new habit",
ready: false,
},
];
counter.value = habits.value.length;
});
</script>
CodePudding user response:
Ok from the given context, I believe you're not using any backend and are saving all the entries on the local storage.
If that is the case, you must be storing your data in some array to LS like habits: []
Here instead of initiating counter to 0 you can add a lifecycle method.
beforeMount() {
counter = JSON.parse(localStorage.getItem("habits")).length
}