Search code examples
javascriptformsliferay-7

Liferay 7: Using URL params and Javascript to prefill a form


I've been working with Liferay 7 for a while and needed to create a feedback form with prefilled values. I created a feedback form and a page, where it's shown and where I could add Javascript.

The user clicks on a link ("Did you find this helpful? Yes/No") and it takes you to the feedback page with the page and answer as URL parameters.

URL: {feedback-page-url/} ?pageUrl=/services&answer=Yes

enter image description here

Now here's where the problems began. Liferay updates it's values very confusingly and while generic document.getElementsByName(...) etc. seemed to work at first, they updated back when clicking the page. The difficult thing is to update the right values in right elements, so they won't be overrun by Liferay.

I provided an answer to my question below. Feel free to ask me anything, I'll try to help :)


Solution

  • Full code block in the end!
    So I found out a solution to this problem. Liferay creates an instance (_com_liferay...) and uses it's values to be up to date, so we need to get a hold of it and update it's values. You can do it manually by inspecting and finding your instance, but I have an automatic code that should get it for you.

    The id we are searching for is for DDMFormPortlet and the String we get this way is close to perfect. The String that document.querySelector() finds begins with p_p_id_com..., so we can use .substring to remove the unnecessary part and then add +"form" in the end to make it complete. If you find a better way to find this, please share it :)

    // _com_liferay_dynamic_data_mapping_form_web_portlet_DDMFormPortlet_INSTANCE_randomkey_form
    const idFinder = function() {
        const idString = document.querySelector('[id*="DDMFormPortlet"]').id;
        return(idString.substring(6) + "form");
    }

    Now that we have the correct String text, we'll find the element, that corresponds to it:
    const formFieldArray = window[idFinder()];

    Now if you try it just by itself, it most likely won't find anything, because it's loads slowly. I put all of this into try-catch with setTimeout() to make sure everything works as intended. Now all we need to do is collect the information from our URL and set it to the correct places.

    const params = new URLSearchParams(location.search);
    
    const formAutoFiller = function (params) { 
        try {
            const formFieldArray = window[idFinder()];
            // make sure you have the numbers according to your form!
            formFieldArray.pages[0].rows[0].columns[0].fields[0].value=params.get('pageUrl');
            formFieldArray.pages[0].rows[1].columns[0].fields[0].value=params.get('answer');
            // ...
        }
    }

    And finally, as the changed values update to the form after clicking an input field, we'll move the selection focus to one of the input fields after the other code is ran:
    document.getElementsByClassName("ddm-field-text")[1].focus();

    A bit cleanup for myself and we're done! Full Javascript here:

    const params = new URLSearchParams(location.search);
    
    const idFinder = function() {
        const idString = document.querySelector('[id*="DDMFormPortlet"]').id;
        return(idString.substring(6) + "form");
    }
    
    const formAutoFiller = function (params) { 
        try {
            const formFieldRows = window[idFinder()].pages[0].rows;
            formFieldRows[0].columns[0].fields[0].value=params.get('pageUrl');
            formFieldRows[1].columns[0].fields[0].value=params.get('answer');
            document.getElementsByClassName("ddm-field-text")[1].focus();
        } catch (e) {
            setTimeout(formAutoFiller, 500, params);
        }
    }
    
    formAutoFiller(params);