skip to Main Content

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:

  1. The values are correctly stored in localStorage and can be seen when I inspect localStorage in the browser’s developer tools.
  2. However, when the page loads, the checkbox does not reflect the checked state based on the values stored in localStorage.

Troubleshooting Steps Taken:

  1. Verified the localStorage values using console.log.
  2. Checked the JavaScript console for errors.
  3. 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


  1. Chosen as BEST ANSWER

    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:

    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>
                        <input type='checkbox' class='startGuideOnLogin'>&nbsp;<label>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: `<p>Swtich between light and dark mode.</p>
                        <input type='checkbox' class='startGuideOnLogin'>&nbsp;<label>Always start guide on login</label>`,
                        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: `<p>Swtich between light and dark mode.</p>
                        <input type='checkbox' class='startGuideOnLogin'>&nbsp;<label>Always start guide on login</label>`,
                        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.getElementById('startGuide').addEventListener('click', function () {
        expandHiddenAreas(steps);
        driverObj.drive();
    });
    
    // Retrieve and set checkbox state
    function setCheckboxState() {
        const storedValue = localStorage.getItem('startGuideOnLogin');
        const checkbox = document.querySelector('.startGuideOnLogin');
        if (checkbox) {
            // Default value is checked if no value is stored
            checkbox.checked = storedValue === null ? true : storedValue === '1';
    
            checkbox.addEventListener('change', function() {
                localStorage.setItem('startGuideOnLogin', this.checked ? '1' : '0');
            });
        }
    }
    
    // Attach event listener only once after document is loaded
    document.addEventListener('DOMContentLoaded', function() {
        const observer = new MutationObserver(() => {
            setCheckboxState();
        });
    
        observer.observe(document.body, { childList: true, subtree: true });
    });
    
    window.addEventListener('load', function () {
        let isStartGuide = localStorage.getItem('startGuideOnLogin');
    
        // If the value is not present in localStorage, set it to the default value '1'
        if (isStartGuide === null) {
            isStartGuide = '1';
            localStorage.setItem('startGuideOnLogin', isStartGuide);
        }
    
        // Convert the string to a number
        isStartGuide = parseInt(isStartGuide, 10);
    
        if (isStartGuide === 1) {
            expandHiddenAreas(steps);
            driverObj.drive();
        }
    });
    

  2. You may try to provide actual boolean value to checkbox.checked instead of 0 or 1. You can do it by

    Either

    Using the Boolean type casting:

    /*
    * Existing code
    */
    if (checkbox) {
        checkbox.value = isStartGuide;
        checkbox.checked = Boolean(isBoxChecked);
    /*
    * Remaining existing code.
    */
    

    OR

    Using a ternary operator to determine the state of checkbox:

    /*
    * Existing Code
    */
    if (checkbox) {
        checkbox.value = isStartGuide;
        checkbox.checked = isBoxChecked == 1 ? true : false;
    /*
    * Remaining Existing Code.
    */
    

    PS please use only one of the above workarounds.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search