Search code examples
modal-dialogliferayrefreshliferay-6

Open liferay's portlet in pop-up and after success refresh the calling portlet


We have a requirement to open liferay's add/edit folder/document screen in a dialog pop-up of our custom plugin portlet.

And after successful (no exceptions or errors) save it should automatically close the pop-up and refresh just our plugin portlet on the page.

Following is the code we have used to open liferay's pop-up:

<liferay-portlet:renderURL var="addFolderURL" portletName="<%=PortletKeys.DOCUMENT_LIBRARY %>" windowState="<%=LiferayWindowState.POP_UP.toString() %>">
    <liferay-portlet:param name="struts_action" value="/document_library/edit_folder" />
    <liferay-portlet:param name="redirect" value="<%= currentURL %>" />
    <liferay-portlet:param name="repositoryId" value="<%= String.valueOf(repositoryId) %>" />
    <liferay-portlet:param name="parentFolderId" value="<%= String.valueOf(folderId) %>" />
</liferay-portlet:renderURL>

<%
String addFolderJavascript = "javascript:Liferay.Util.openWindow({dialog: {destroyOnHide: true}, id: 'addFolderPopUpId', title: '" 
                                + ((folder != null) ? UnicodeLanguageUtil.get(pageContext, "add-subfolder") : UnicodeLanguageUtil.get(pageContext, "add-folder")) 
                                + "', uri: '" + HtmlUtil.escapeJS(addFolderURL) + "'});";
%>

<aui:a href="<%= addFolderJavascript %>" label='<%= (folder != null) ? "subfolder" : "folder" %>' />

The difficulty is how would we know when the add/edit document is successful, how would we close the pop-up and then refresh the portlet since we don't have any control over the add/edit screen coming from liferay. And even if we do it through hook the problem is how to know the success/failure of the document.

Thanks


Solution

  • I never thought the answer would be in Liferay's code itself and was pretty simple.

    Liferay also uses such a functionality in Asset Publisher portlet, as shown below:

    enter image description here

    So liferay after adding the blogs, document etc closes the pop-up and refreshes the asset-publisher portlet. It does this with a simple redirect trick.

    Three things:

    1. you require a jsp which would have the redirect and close script.
    2. a redirect url which will call the above jsp after successful save.

      In liferay redirect parameter is always passed as a parameter to almost all action requests and on successful save it redirects to the URL passed in this parameter

    3. the popup-id which can be referenced from the jsp.

    The jsp is /asset_publisher/add_asset_redirect.jsp and its code is as shown below which can be used in your plugin as it is (I have used comments to explain somethings):

    <%
    String redirect = request.getParameter("redirect");
    
    redirect = PortalUtil.escapeRedirect(redirect);
    
    Portlet selPortlet = PortletLocalServiceUtil.getPortletById(company.getCompanyId(), portletDisplay.getId());
    %>
    
    <aui:script use="aui-base">
        Liferay.fire(
            'closeWindow', // closes the pop-up window
            {
                id: '<portlet:namespace />editAsset', // the id of the pop-up which we gave
                portletAjaxable: <%= selPortlet.isAjaxable() %>,
    
                <c:choose>
                    <c:when test="<%= redirect != null %>">
                        redirect: '<%= HtmlUtil.escapeJS(redirect) %>' // redirects the page to this URL
                    </c:when>
                    <c:otherwise>
                        refresh: '<%= portletDisplay.getId() %>' // refreshes only the portlet
                    </c:otherwise>
                </c:choose>
            }
        );
    </aui:script>
    

    So now lets achieve what we intend to step-by-step in our plugin:

    1. have a jsp similar to add_asset_redirect.jsp in your plugin.
    2. build the redirect url like:

      <%
      PortletURL customRedirectURL = liferayPortletResponse.createLiferayPortletURL(themeDisplay.getPlid(), portletDisplay.getId(), PortletRequest.RENDER_PHASE, false);
      
      customRedirectURL.setParameter("mvcPath", "/html/common/add_asset_redirect.jsp"); // mvcPath so that your custom portlet's render() calls this jsp when a redirect from liferay's page happens
      /* customRedirectURL.setParameter("redirect", themeDisplay.getURLCurrent()); // set this if you want to redirect to a certain page, if only refresh is your motto then leave this commented. */
      customRedirectURL.setWindowState(LiferayWindowState.POP_UP);
      
      String customRedirect = customRedirectURL.toString();
      
      // popUp-id while opening the pop-up. should be same as that in add_asset_redirect.jsp
      String customPopUpId = renderResponse.getNamespace() + "editAsset";
      %>
      
    3. build the code to open the pop-up:

      <liferay-portlet:renderURL var="addFolderURL" portletName="<%=PortletKeys.DOCUMENT_LIBRARY %>" windowState="<%=LiferayWindowState.POP_UP.toString() %>">
          <liferay-portlet:param name="struts_action" value="/document_library/edit_folder" />
          <liferay-portlet:param name="redirect" value="<%= customRedirect %>" />
          <liferay-portlet:param name="repositoryId" value="<%= String.valueOf(repositoryId) %>" />
          <liferay-portlet:param name="parentFolderId" value="<%= String.valueOf(folderId) %>" />
      </liferay-portlet:renderURL>
      
      <%
      String addFolderJavascript = "javascript:Liferay.Util.openWindow({dialog: {destroyOnHide: true}, id: '"
                                      + customPopUpId +"', title: '" 
                                      + ((folder != null) ? UnicodeLanguageUtil.get(pageContext, "add-subfolder") : UnicodeLanguageUtil.get(pageContext, "add-folder")) 
                                      + "', uri: '" + HtmlUtil.escapeJS(addFolderURL) + "'});";
      %>
      
      <aui:a href="<%= addFolderJavascript %>" label='<%= (folder != null) ? "subfolder" : "folder" %>' />
      
    4. that's all. Go check-it out.

    Hope this helps.