1

We have built a custom Joomla! component that has multiple sections and edit screens. In many cases, our component pages are related to each other and it makes sense for users to move from one to another. To facilitate this quickly, we thought of putting links in our component edit screens so that users could quickly move to related data items. The problem is, if you use a standard link the original item the user opened stays locked.

What is the best way for users to be able to move between edit screens that unlocks the one they are leaving?

1 Answer 1

1

I came to a solution on this problem, but it was more detailed than originally expected. Include the following JavaScript in your admin pages:

jQuery(document).ready(function($){
    const form = $('form[name="adminForm"]');
    const form_id = form.attr('id');
    const initial_form_state = $('form[name="adminForm"]').serialize();
    const obj_name = form_id.replace('-form', '');

    let clicked_url = '';

    /**
     * Checks in the current form and then redirects to the URL selected by the user
     *
     * @return {void}
     */
    function checkInThenRedirect(){
        // Set the task to cancel
        $(form).find('input[name="task"]').val(`${obj_name}.cancel`);

        $.ajax({
            cache: false,
            contentType: false,
            data: new FormData($('form')[0]),
            method: 'POST',
            processData: false,
            url: $('form').attr('action')
        }).done(function(data){
            window.location = clicked_url;
        });
    }

    // Listen for any changes to files
    $('form :file').change(function(){
       $('form').data('changed',true);
    });

    // Listen for clicks on links
$('#content a').not('[target="_blank"]').not('[href^="#"]').not('.modal').not('[class*="group-add"]').not('[class*="group-remove"]').not('[class*="button"]').click(function(event){
        event.preventDefault();
        clicked_url = $(this).attr('href');

        // Get the current from state
        const form_state = $(`#${form_id}`).serialize();

        // If changes were made, prompt the user to see if they want to save
        if(initial_form_state !== form_state || $('form').data('changed')){
            event.preventDefault();

            // Add a modal to the screen
            $('body').append(`
                <div class="modal" id="confirmLeaveModal" style="margin-left: -150px; text-align: center; width: 300px;">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal">&times;</button>
                        <h3>Unsaved Changes</h3>
                    </div>
                    <div class="modal-body">
                        <p style="padding: 20px;">You have unsaved changes. Would you like to save them?</p>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn" id="confirmLeaveNo">No</button>
                        <button type="button" class="btn btn-primary" id="confirmLeaveYes">Yes</button>
                    </div>
                </div>`);
            return;
        }

        checkInThenRedirect();
    });

    // Bootstrap's modal close doesn't work on dynamic modals. Fixing that
    $('body').on('click', '#confirmLeaveModal .close', function(event){
        $('#confirmLeaveModal').remove();
    });

    // If the user does not want to save changes
    $('body').on('click', '#confirmLeaveNo', function(event){
        event.preventDefault();
        checkInThenRedirect();
    });

    // If the user agrees to save changes
    $('body').on('click', '#confirmLeaveYes', function(event){
        event.preventDefault();

        // Get the form URL
        let target = $('form').attr('action');

        // Add a return with the clicked_url
        target += '&return=' + encodeURI(window.btoa(clicked_url));

        // Add the new target to the form
        $('form').attr('action', target);

        // Cause the form to be submitted
        Joomla.submitform(`${obj_name}.save`, document.getElementById(form_id));
    });
});

The above code will automatically check-in the resource that the user had locked when they navigate to a new admin screen. If they made changes to the current screen, it will prompt them for what to do first.

1
  • Please award your self-answer the green tick to signal that this page is resolved (and prevent the community from continually bumping it to the top of the question list). Dec 15, 2021 at 12:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.