I am trying to use localStorage to store and load the checked state of a checkbox. The values are being correctly stored and retrieved from localStorage, but the checkbox is not reflecting these values when the page loads.
Here’s a summary of my code:
const driver = window.driver.js.driver;
const roleBasedSteps = {
admin: {
commonSteps: [
{
element: '#themeSwitchBtn',
popover: {
title: 'Switch Theme',
description: `<p>Swtich between light and dark mode.</p>
<label><input type='checkbox' value='' class='startGuideOnLogin'> Always start guide on login</label>`,
position: 'auto'
// side: 'top', // left, top, right, bottom
// align: 'start' // start, center, end
}
},
{
element: '#navProfileBtn',
popover: {
title: 'More Options',
description: 'More options to handle your profile.',
position: 'auto'
}
},
{
element: '#dashboardBtn',
popover: {
title: 'Dashbaord',
description: 'Overview your overall progress in figures, charts and tables.',
position: 'auto'
}
},
{
element: '#emailBtn',
popover: {
title: 'Email',
description: 'Email box where you can send, receive and read emails.',
position: 'auto'
}
},
{
element: '#usersDropdown',
popover: {
title: 'Users List',
description: 'View all users list to manage them.',
position: 'auto'
}
}
],
'index.php': [
{
element: '#adminDashboardCountStats',
popover: {
title: 'Total Counts',
description: 'View all counts of meetings, clients, client interviews and placed clients.',
position: 'auto'
}
}
]
},
employee: {
commonSteps: [
{
element: '#themeSwitchBtn',
popover: {
title: 'Switch Theme',
description: 'Swtich between light and dark mode.',
position: 'auto'
}
},
{
element: '#navProfileBtn',
popover: {
title: 'More Options',
description: 'More options to handle your profile.',
position: 'auto'
}
},
{
element: '#dashboardBtn',
popover: {
title: 'Dashbaord',
description: 'Overview your overall progress in figures, charts and tables.',
position: 'auto'
}
},
{
element: '#emailBtn',
popover: {
title: 'Email',
description: 'Email box where you can send, receive and read emails.',
position: 'auto'
}
},
{
element: '#usersDropdown',
popover: {
title: 'Users List',
description: 'View all users list to manage them.',
position: 'auto'
}
}
],
'index.php': [
{
element: '#employeeDashboardCountStats',
popover: {
title: 'Total Counts',
description: 'View all counts of meetings, clients, client interviews and placed clients.',
position: 'auto'
}
}
]
},
candidate: {
commonSteps: [
{
element: '#themeSwitchBtn',
popover: {
title: 'Switch Theme',
description: 'Swtich between light and dark mode.',
position: 'auto'
}
},
{
element: '#navProfileBtn',
popover: {
title: 'More Options',
description: 'More options to handle your profile.',
position: 'auto'
}
},
{
element: '#dashboardBtn',
popover: {
title: 'Dashbaord',
description: 'Overview your overall progress in figures, charts and tables.',
position: 'auto'
}
},
{
element: '#emailBtn',
popover: {
title: 'Email',
description: 'Email box where you can send, receive and read emails.',
position: 'auto'
}
},
{
element: '#jobsListBtn',
popover: {
title: 'Jobs List',
description: 'View all listed jobs where you can check and give feedback to us.',
position: 'auto'
}
},
{
element: '#kanbanDropdown',
popover: {
title: 'Interviews Board',
description: 'Mnanage your interviews and their progress.',
position: 'auto'
}
},
{
element: '#accountDropdown',
popover: {
title: 'Account',
description: 'Manage your profile.',
position: 'auto'
}
},
{
element: '#calendarBtn',
popover: {
title: 'Calendar',
description: 'View calendar and events.',
position: 'auto'
}
},
{
element: '#collapseBtn',
popover: {
title: 'Collapse Sidebar',
description: 'Collapse sidebar menu.',
position: 'auto'
}
}
],
'index.php': [
{
element: '#dashboardTotalCounts',
popover: {
title: 'Total Counts',
description: 'View all counts of jobs, interviews and meetings.',
position: 'auto'
}
},
{
element: '#dashboardAppliedJobsCount',
popover: {
title: 'Applied Jobs Graph',
description: 'View graphical representation below based on selected date range of applied jobs.',
position: 'auto'
}
},
{
element: '#dashboardInterviewsListTable',
popover: {
title: 'Interviews List Table',
description: 'View tabular view of your interviews.',
position: 'auto'
}
}
],
'email.php': [
{
element: '.composeEmailBtn',
popover: {
title: 'Compose Email',
description: 'Opens compose emails section.',
position: 'auto'
}
},
{
element: '#emailSidebarSection',
popover: {
title: 'Email Folders',
description: 'View emails in each folder.',
position: 'auto'
}
},
{
element: '#load-folder-emails',
popover: {
title: 'Emails List',
description: 'View all emails of specific folder.',
position: 'auto'
}
}
],
'jobs_list.php': [
{
element: '#jobsListPageSearch',
popover: {
title: 'Search Job',
description: 'Search from jobs list.',
position: 'auto'
}
},
{
element: '#jobsListAction',
popover: {
title: 'Give Rating',
description: 'Rate any job by clicking action button against the job.',
position: 'auto'
}
},
{
element: '#jobsListAction',
popover: {
title: 'Give Review',
description: 'Review any job by clicking action button against the job.',
position: 'auto'
}
}
],
'kanban.php': [
{
element: '#kanbanInterviews',
popover: {
title: 'Pending Interviews',
description: 'Here is the list of all upcoming interviews.',
position: 'auto'
}
},
{
element: '#kanbanStage1',
popover: {
title: 'First Stage',
description: 'Here is the list of interviews of first stage.',
position: 'auto'
}
},
{
element: '#kanbanStage2',
popover: {
title: 'Second Stage',
description: 'Here is the list of interviews of second stage.',
position: 'auto'
}
},
{
element: '#kanbanRejected',
popover: {
title: 'Rejected',
description: 'Here is the list of failed interviews.',
position: 'auto'
}
},
{
element: '#kanbanOffer',
popover: {
title: 'Offer',
description: 'Here is the list of passed interviews.',
position: 'auto'
}
},
{
element: '.kanbanAddInterview1',
popover: {
title: 'Add New',
description: 'Opens pop up to add new item.',
position: 'auto'
}
},
{
element: '.kanbanAddInterview2',
popover: {
title: 'Add New',
description: 'Opens pop up to add new item.',
position: 'auto'
}
},
{
element: '.kanbanAddInterview3',
popover: {
title: 'Add New',
description: 'Opens pop up to add new item.',
position: 'auto'
}
},
{
element: '.kanbanAddInterview4',
popover: {
title: 'Add New',
description: 'Opens pop up to add new item.',
position: 'auto'
}
},
{
element: '.kanbanAddInterview5',
popover: {
title: 'Add New',
description: 'Opens pop up to add new item.',
position: 'auto'
}
}
]
}
};
function mergeGuideSteps(common, specific) {
return [...common, ...specific];
}
const steps = mergeGuideSteps(roleBasedSteps[userRole].commonSteps, roleBasedSteps[userRole][currentPage]) || [];
function expandHiddenAreas(steps) {
steps.forEach(step => {
const element = document.querySelector(step.element);
if (element) {
let parent = element.parentElement;
while (parent) {
if (parent.style.display === 'none' || parent.style.visibility === 'hidden') {
parent.style.display = '';
parent.style.visibility = '';
}
if (parent.classList.contains('collapsed')) {
parent.classList.remove('collapsed');
}
parent = parent.parentElement;
}
}
});
}
function isElementInCommonSteps(commonSteps, element) {
const result = commonSteps.some(step => step.element === element);
// console.log(`Checking if element ${element} is in common steps: ${result}`);
return result;
}
function expandSidebarIfNeeded(commonSteps, currentElement) {
const sidebar = document.querySelector('#navbarVerticalCollapse');
const isMobileScreen = window.innerWidth <= 990;
// console.log(window.innerWidth);
const cElement = "#" + currentElement;
if (isMobileScreen && isElementInCommonSteps(commonSteps, cElement)) {
sidebar.classList.add('show');
} else {
sidebar.classList.remove('show');
}
}
const driverObj = driver({
showProgress: true,
steps: steps,
onHighlightStarted: (element) => {
expandSidebarIfNeeded(roleBasedSteps[userRole].commonSteps, element.id);
}
});
document.addEventListener('click', function (event) {
if (event.target && event.target.classList.contains('startGuideOnLogin')) {
const checked = '1';
const unchecked = '0';
if (event.target.value === '0' || event.target.value === '') {
localStorage.setItem('startGuideOnLogin', checked);
localStorage.setItem('startGuideBox', 'true');
event.target.value = checked;
event.target.checked = true;
} else {
localStorage.setItem('startGuideOnLogin', unchecked);
localStorage.setItem('startGuideBox', 'false');
event.target.value = unchecked;
event.target.checked = false;
}
console.log('Checkbox value:', event.target.value);
}
});
document.getElementById('startGuide').addEventListener('click', function () {
expandHiddenAreas(steps);
driverObj.drive();
});
window.addEventListener('load', function () {
const isStartGuide = JSON.parse(localStorage.getItem('startGuideOnLogin'));
const isBoxChecked = JSON.parse(localStorage.getItem('startGuideBox'));
console.log('Start Guide: ' + isStartGuide);
console.log('Input Box: ' + isBoxChecked);
const checkbox = document.querySelectorAll('.startGuideOnLogin');
if (checkbox) {
checkbox.value = isStartGuide;
checkbox.checked = isBoxChecked;
console.log("values: " + checkbox.value + ", " + checkbox.checked);
}
if (isStartGuide === 1) {
expandHiddenAreas(steps);
driverObj.drive();
}
});
Issue:
- The values are correctly stored in localStorage and can be seen when I inspect localStorage in the browser’s developer tools.
- However, when the page loads, the checkbox does not reflect the checked state based on the values stored in localStorage.
Troubleshooting Steps Taken:
- Verified the localStorage values using console.log.
- Checked the JavaScript console for errors.
- Ensured the checkbox has the correct class and is present in the DOM when the script runs.
Question:
What could be the reason why the checkbox state is not being applied despite localStorage values being correctly stored and loaded? How can I fix this issue?
2
Answers
I debugged the issue and found that due to the dynamic loading of the DOM for tooltips, the checkbox state was not being accessed and set as desired. I used a MutationObserver to detect when the popover is added to the DOM, and it fixed my issue. Here is my updated code, which is now working as intended:
You may try to provide actual
boolean
value tocheckbox.checked
instead of0
or1
. You can do it byEither
Using the
Boolean
type casting:OR
Using a ternary operator to determine the state of
checkbox
:PS please use only one of the above workarounds.