RE: Open Portlet Automatically in the Liferay Created Page

Avinash kumar, modified 6 Years ago. New Member Posts: 19 Join Date: 7/10/17 Recent Posts
Hi All ,

I have two portlet . One portlet I have embedded in the theme header . It contains search box and submit button .

When I search some keyword and click on submit , My Result is loaded in the 2nd Portlet which I have added in a Page created in liferay .

Now I have the situation like I need to manually click on the page to see the results displayed in the 2nd portlet.

Does anyone know who we can automatically load the page where my 2nd portlet is added after I click on the 1st portlet from the theme header ?

Help is needed soon .

Thanks,
​​​​​​​Avinash
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hi Avinash, 

All you have to do is make the url from the header portlet a renderURL targeting the second portlet on the page where it lives. Rather than using a <portlet:renderURL/> instead use teh <liferay-portlet:renderURL/> and make sure you set the portletName attribute to the portlet name for the portlet on the other page, and that you send the plid equal to the plid of the other page. Soemthing like this --
<liferay-portlet:renderurl var="searchRenderURL" portletName="com_abc_company_web_portlet_SearchResults" plid="1234" />

<aui:form name="fm" action="${searchRendeURL}&quot;">
​​​​​​​...
</aui:form>

.. to get the plid for the other page you can use the LayoutLocalService to lookup the page based on the friendly url.
Avinash kumar, modified 6 Years ago. New Member Posts: 19 Join Date: 7/10/17 Recent Posts
Thanks for the reply but I am using IPC via public render parameter and I have 1st portlet using <liferay-portlet:actionURL>

and in action method of first portlet I use processAction to set the renderResponse which will be used in the 2nd portlet.


Also in the example you mentioned you are hard coding the plid . 

Is there some other way to dynamically open the portlet added in any page of liferay when clicked from one portlet?

And if I use <liferay-portlet:renderURL> in 1st portlet how to pass the data from one portlet to another portlet using public render parameter?

Also my first portlet I load via theme in the header.

Regards,
Avinash
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hi Avinash,
Thanks for the reply but I am using IPC via public render parameter and I have 1st portlet using <liferay-portlet:actionURL>

and in action method of first portlet I use processAction to set the renderResponse which will be used in the 2nd portlet.

.. how to put this nicely... I can't, yuck. IPC to do this is gross, and completely unecessary if you ask me. IPC was introduced in Portlet 2.0 to allows portlets to talk to each other in a safer way than putting things in the top level request or session, but truthfully, after more than 10 years working with portals? I think there has been exactly one, maybe two times that I have found Eventing useful. Up to you I guess, but I wouldn't do that. 
Also in the example you mentioned you are hard coding the plid . 

.. I am hardcoding the pid as an example to show you that there is an attribute on the tag you can use. Of course you would get the pid dynamically. There is a method on the LayoutLocalService that you can use to get a  Layout for a group based on the friendly url. I am assuming that you would know the page the other portlet lives on -- for example /search or /details or something like that. So you would look up that plid either server side in your Command or Portlet class and pass it to the JSP, or handle it through a portlet configuration ir just grab it via service in the JSP using a scriptlet. I didn't realize you wanted me to actually code it for you. If you do, then you might want to actually provde me all the details emoticon

Is there some other way to dynamically open the portlet added in any page of liferay when clicked from one portlet?

And if I use <liferay-portlet:renderURL> in 1st portlet how to pass the data from one portlet to another portlet using public render parameter?

Also my first portlet I load via theme in the header.

... seems to me that maybe you need to read a little more about portlets and how they work. The answer I gave you, to create a render URL targeting the portlet and page, is all you need to do to achieve this. The public render parameter (which is IPC in fact) allows the parameter, which is not considered secure, hence why it is PUBLIC, to be available to ALL the portlets on the page. Once you configure it, it will make sense since the resulting page url has a p_r_p in the query string, and since all portlets can access the public url, they can see the parameter. 

embedding the portlet in the theme doesn't matter -- that just means that it is automatically there on every page so that you don't have to manually pass it. So let's say you have this ..

1. Home Page -- embedded portlet 
2. Search Results Page -- embedded portlet and results portlet

You user is on the homepage and types in some keywords into your embedded (search) portlet. Your form uses a RENDER URL that will pass the keywords value as a parameter (dynamically). Because you have configured the keywords to be a PRP in both portlets, when the form is submitted it will go into the url and because your RENDER URL is specifying a portlet that is on another page, the request will be routed to THAT portlet. That portlets RENDER method will be able to see the keywords, so it can read them, perform the search, and then render IT'S view.jsp which is on the Search Results Page. 

Basically, the render url will take the user to the other page automatically because that it what you have configured the url to do by specifying the plid for the new page.

​​​​​​​



 
Avinash kumar, modified 6 Years ago. New Member Posts: 19 Join Date: 7/10/17 Recent Posts
Thanks for the response . 

Just a quick question :-

I am trying to retrieve the value of text field from the first portlet in my 2nd Portlet .

Previously I was getting it easily since I used action url ,But after using Render Url and passing the 2nd portllet name , 

The render directly goes to 2nd portlet so I am not able to retrieve the value of text field in my 2nd portlet .

I tried this in my 2nd portlet render method but no luck

String query = ParamUtil.getString(request,"SEARCH_QUERY");

Can you tell me how to get the form data from first portlet in the 2nd portlet using the <portlet:renderUrl> after the form is submit in 1st portlet ?

Your help is needed .

Also if you have any example project tht will be great.

Regards,
​​​​​​​Avinash
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hi Avinash,

I'm going to assume a couple of things there. 

1. You mentioned a <portlet:renderURL/> but you actually meant the <liferay-portlet:renderURL/> 

2. You have configured the public render parameters and now see a p_r_p prefix in one of your URL params

.. assuming both of those things are true, then your parameter should be part of the publicParameterMap. I think you should be able to retrieve it using renderRequest.getParameter and you can use the GetterUtil.getXXX if you need a specific type. That same call should be able to retrieve the portlet for both portlet 1 and portlet 2, assuming you configured the PRP on both of them (which you should have)
Avinash kumar, modified 6 Years ago. New Member Posts: 19 Join Date: 7/10/17 Recent Posts
I got your point but still I am not able to retrieve the value in my second portlet when I enter the text field value in first portlet .

I have implemented IPC and it was working fine before but now the situation is to load the 2nd portlet automatically when clicked on

submit button of first portlet . The action directly goes to the 2nd portlet class so my Public render parameter is not getting set .

Here is my JSP for First portlet :-
<liferay-portlet:actionurl var="SearchAction" name="Search" windowstate="normal" portletmode="view" portletname="MySearchPortletResult_WAR_liferaymysearchportlet" plid="15515">
</liferay-portlet:actionurl>

<div class="search" id="mysearch-new-container">
    <form name="SearchForm" method="post" class="aui-form" id="SearchForm" action="<%=SearchAction%>">
        <div id="mysearch-new-container-top">
            <input type="text" size="30" name="<portlet:namespace/><%=MySearchPortlet.SEARCH_QUERY%>" list="suggestion-datalist" id="mySearchtext" placeholder="What are you looking for?" onkeypress="doAutoComplete()" autocomplete="false" class="search" style="width: 272px">
            <datalist id="suggestion-datalist"></datalist>
            <input type="hidden" name="_3_groupId" value="0">
            <input type="submit" class="button" value="search" onclick="javascript:return doFormSubmit()">
        </div>
    </form>
</div>

After click on the submit button it doesn't go to the first portlet Action class but it goes to the 2nd portlet action class . So my PRP is not getting set .

Here is my 2nd portlet class where I am trying to retrieve the value of the text field entered in the 1st portlet .

@ProcessAction(name = "Search")
public void searchProcess(ActionRequest request, ActionResponse response){

    String query = ParamUtil.getString(request,"mysearchresponse");
  // = request.getParameter("mysearchresponse");
    LOG.info("Query in 2nd Portlet is "+query);
    String searchResponsesPortlet2=ParamUtil.getString(request,"mysearchresponse");
    response.setRenderParameter("mysearchresponse",query);
    LOG.info("Data in 2nd Portlet is "+searchResponsesPortlet2);

}
 But it always comes NULL . 

Can you please help me to find the solution ??
Avinash kumar, modified 6 Years ago. New Member Posts: 19 Join Date: 7/10/17 Recent Posts
Can anyone help on this ??
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
:|

My god man -- how many times in this thread did I say RENDER URL. Apart from the fact that action URLs use a POST which means your URLs are never going to get added to the URL, it's also the wrong type of URL to create.

Action URLs are supposed to be used when you "take action on data". So for example, if you are editing a record, or deleting a file, etc. -- for lack of a better explanation, CRUD operations are normally how you can easily identify Portlet Action URLs. In your case you are not CHANGING any data you are technically loading a different view. Your first view is "no results" and now you are trying to load a view w/ results. 

It looks like you are using Liferay 6.2 based on what you just posted -- there are tons of examples online from all sorts of bloggers showing examples. You just need to use those examples, but where they don't place the portletName or plid parameters in your URL, you will continue to use yours. 

There are also lots of exmples in the Liferay code base since there are many portlets that use PRPs to auto filter content like Assets, Message Boards, etc.

Try it again and if you are still struggling post a github repo or something with your plugin and I'll take a look at it.
Avinash kumar, modified 6 Years ago. New Member Posts: 19 Join Date: 7/10/17 Recent Posts
Thanks for your patience for helping me .

Now I have this in my first portlet view.jsp :-
<liferay-portlet:renderurl var="SearchAction" windowstate="normal" portletmode="view" portletname="MySearchPortletResult_WAR_liferaymysearchportlet" plid="15515">
    <liferay-portlet:param name="mysearchresponse" value="<%=renderRequest.getParameter(SEARCH_QUERY)%>"></liferay-portlet:param>
</liferay-portlet:renderurl>
Now some how it works finally but there is one issue .

The value in the parameter is not getting initially when i type some text and click on submit button .

What happens it if I type "ABC" and click on submit button I see the result for the previous typed "PRQ" keyword result.

How to fix this ? I need to pass the same value what ever user enter in the text box .how to do this?

Thanks
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Two questions.

1. Can you send me your XML files so I can see your prp configs?

​​​​​​​2. I thought you were embedding a portlet in the header? It looks to me like youre just dumping a form in the header maybe?
Avinash kumar, modified 6 Years ago. New Member Posts: 19 Join Date: 7/10/17 Recent Posts
Now it works partially . I am embedding the portlet in header only .

there is some issue . I did this now
<liferay-portlet:renderurl var="SearchAction" windowstate="normal" portletmode="view" portletname="MySearchPortletResult_WAR_liferaymysearchportlet" plid="15515">
<liferay-portlet:param name="mysearchresponse" value="<%=renderRequest.getParameter(SEARCH_QUERY)%>"></liferay-portlet:param>
</liferay-portlet:renderurl>
The value in the parameter is not getting initially when i type some text and click on submit button .

What happens it if I type "ABC" and click on submit button I see the result for the previous typed "PRQ" keyword result.

How to fix this ? I need to pass the same value what ever user enter in the text box .how to do this?

​​​​​​​I have also attached the xml for PRP config
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hi Avinash,

Ok -- the configs look good, and I am glad that you cleared up the fact that you are embedding the portlet (even though you are only sharing the view.jsp code). At this point I think it would be easiest if you could zip up your plugins (the portlet and the theme) and send it over to me so that I can try it and debug on my side. 

Is that possible?
Avinash kumar, modified 6 Years ago. New Member Posts: 19 Join Date: 7/10/17 Recent Posts
I am afraid sharing the complete plugin will be not possible as it is my client code .

But I was managed not make it work partially . Now I am able to render from one portlet to another . 

But I have one issue while passing the value to the PRP via url . 

I am not able to retrieve the same keyword which user type in the text box . The issue is when user types some keyword and click on the Search button it searches based on the previous typed keyword.

So to be precise i need to pass the current value what ever user type in the textbox to the Render URL PRP value .

Do you know How to do this ?

This is how my JSP looks

<script type="text/javascript" language="javascript">
    function doFormSubmit() {
        <%

        String query = ParamUtil.getString(request, SEARCH_QUERY);
        System.out.println("Query in JSP is" + query);
       %>
        document.getElementById('SearchForm').submit();

    }
</script>
 <liferay-portlet:renderurl var="SearchAction" windowstate="normal" portletmode="view" portletname="MySearchPortletResult_WAR_liferaymysearchportlet" plid="<%=plid%>"> 
<liferay-portlet:param name="mysearchresponse" value="<%=query%>"></liferay-portlet:param> </liferay-portlet:renderurl>

<div class="search" id="mysearch-new-container">
    <form name="SearchForm" method="post" class="aui-form" id="SearchForm" action="<%=SearchAction%>">
        <div id="mysearch-new-container-top">
            <input type="text" class="searchtext" size="30" name="<portlet:namespace/><%=SEARCH_QUERY%>" list="suggestion-datalist" id="mySearchtext" placeholder="What are you looking for?" onkeypress="doAutoComplete()" autocomplete="false">
            <datalist id="suggestion-datalist"></datalist>
            <input type="hidden" name="_3_groupId" value="0">
            <input type="submit" class="button" value="search" onclick="javascript:return doFormSubmit()">
        </div>
    </form>
</div>
 
Can you help to fix this value setting issue to the paramter after form submit?

Regards,
​​​​​​​Avinash
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Ok, I think I see what is happening. This is a bit of a mess -- I'm guessing you are maybe new to Liferay? emoticon 

Looking at your code.

1. I would enocourage you to use the aui taglibs so that you don't have to add the namespace to yourself
2. I removed the method from the form -- you don't need a post in this case
3. You have some parameters in the Render URL that are not required because they are in fact the defaults

Now the reason it's not working. When you define your render url you are doing this.
​​​​​​​<liferay-portlet:renderurl var="SearchAction" windowstate="normal" portletmode="view" portletname="MySearchPortletResult_WAR_liferaymysearchportlet" plid="<%=plid%>">&nbsp;
&nbsp;&nbsp; &nbsp;<liferay-portlet:param name="mysearchresponse" value="<%=query%>"></liferay-portlet:param>&nbsp;
</liferay-portlet:renderurl>

That tag is put together server side, when the page is being assembled which means your user has not yet entered any data. So the first time you go to the page, the parameter will contain a value of blank. So when you hit the submit button, you send across blank -- even though your user has entered ABC. On the results page you now created a render url with ABC. So the user enteres EFG, but your render url has ABC as the parameter. This is why you are always one behind. What you shoud be doing is this:
<liferay-portlet:renderurl var="SearchAction" portletName="MySearchPortletResult_WAR_liferaymysearchportlet" plid="<%=plid%>" />&nbsp;

<div class="search" id="mysearch-new-container">
&nbsp; &nbsp; <aui:form name="SearchForm" action="<%=SearchAction%>">
&nbsp; &nbsp; &nbsp; &nbsp; <div id="mysearch-new-container-top">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <aui:input type="text" cssClass="searchtext" size="30" name="<%=SEARCH_QUERY%>" list="suggestion-datalist" id="mysearchresponse" placeholder="What are you looking for?"    onkeypress="doAutoComplete()" autocomplete="false" />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <datalist id="suggestion-datalist"></datalist>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <aui:input type="hidden" name="groupId" value="0" />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <aui:input type="submit" cssClass="button" value="search" />
&nbsp; &nbsp; &nbsp; &nbsp; </div>
&nbsp; &nbsp; 
</aui:form></div>

NOTE: This code is untested as I have no project to run it through -- so all of this is from memory

The javascrpt has no value. All it is doing is outputting the wrong value (not the one entered by the user) and submitting the form, so I deleted it. The render url only needs to provide the target portlet and page. You set the form action to be the render url and the parameters in your form will be passed over automatically. Notice though that in my version the render url has no parameter defined in the tag itself. But, when you click the submit button, it will include the form parameters because that is what a submit action does. The input field is RENAMED to a name that must MATCH your public render parameter name. This way Liferay will detect that this parameter is supposed to be public and will put it in the correct parameter map. I've also changed your form to use the AUI taglibs so that you need only specify the name. The namespace is added automatically, and the id will be populated based on the name field (they will have the same value). 

I also noticed that you have a hidden field with _3_groupId. The _3_ is the portlet namespace for the search portlet in 6.2, so you don't need that here, groupId alone should suffice but if you are hard coding it to "0" to mean a global scope to retrieve content across all sites (that's what it means for the search portlet) then I would argue you can simply omit it as a parameter altogether and just implement that global scope logic in your handler. 
Avinash kumar, modified 6 Years ago. New Member Posts: 19 Join Date: 7/10/17 Recent Posts
Thanks for your suggestion finally I did it in diffrent way . I am noe creating the Portlet Render Url via JavaScript after form submit and during the call of javascript I can get the form data and pass it in the paramter of the Render Url and works fine .


Thanks for the support you provided.

Regards,
​​​​​​​Avinash
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hi Avinash,

I still maintain that the JS is a layer that isn't necessary for what you are trying to do, but if you are happy with the solution, and it works then I suppose that's what counts in the end. 

​​​​​​Let us know if anything else comes up -- the community is always here to help.