Liferay 7: hidden aui input won't set value based on parameter - liferay

I have an entity with a primary key and two other fields.
I am able to display them in a Search Container in my primary View JSP, and I want to implement an edit/update function, so I created a different JSP for that. I pass the properties of the entity I wish to edit in portlet:renderURL portlet:param tags just like this:
<portlet:renderURL var="editEntity">
<portlet:param name="jspPage" value="/update-page.jsp" />
<portlet:param name="primaryKey" value="<%= entityId %>" />
<portlet:param name="name" value="<%= entityName%>" />
<portlet:param name="description" value="<%= entityDesc%>" />
</portlet:renderURL>
In the update-page JSP if I set any input field hidden, the parameter based values disappear, so the controller cannot process the fields' values.
i.e.:
<aui:input name="primaryKey" type="hidden" value="${primaryKey}" />
<aui:input name="primaryKey" type="hidden" value="${name}" />
<aui:input name="primaryKey" type="hidden" value="${description}" />
Note: I only want to hide the primary key field, the controller servlet should be able to process it and update my entity based on the primary key, like this:
<aui:input name="primaryKey" type="text" value="${name}" />
<aui:input name="primaryKey" type="text" value="${description}" />
The funny thing is, that everything just works when I set the input fields text type, but I wouldn't want the users to enter the primary key, duh...
Any ideas how could I fix this?

It's work for me
view.jsp
<%# include file="init.jsp" %>
<portlet:actionURL name="testURL" var="testURL" />
<aui:form name="fm" method="post" action="<%= testURL.toString()%>">
<aui:input name="primaryKey" type="hidden" value="123" />
<aui:button-row>
<aui:button name="submit" type="submit" value="OK" />
</aui:button-row>
</aui:form>
TestmvcportletPortlet.java
package com.example.portlet;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import com.liferay.portal.kernel.util.ParamUtil;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.Portlet;
import javax.portlet.ProcessAction;
import org.osgi.service.component.annotations.Component;
#Component(
immediate = true,
property = {
"com.liferay.portlet.display-category=category.sample",
"com.liferay.portlet.instanceable=true",
"javax.portlet.display-name=Test Portlet",
"javax.portlet.init-param.template-path=/",
"javax.portlet.init-param.view-template=/view.jsp",
"javax.portlet.resource-bundle=content.Language",
"javax.portlet.security-role-ref=power-user,user"
},
service = Portlet.class
)
public class TestmvcportletPortlet extends MVCPortlet {
#ProcessAction(name = "testURL")
public void addBook(ActionRequest actionRequest,ActionResponse actionResponse) throws SystemException {
String a = ParamUtil.getString(actionRequest, "primaryKey");
System.out.println("Value is "+a);
}
}
have you found anything that you missed code?

I found a solution to the problem.
So, after long hours of testing I found out that I just could not get the values stored in parameters just as ${paramName} anywhere in a simple HTML tag, but I still don't know why.
What I did was request for the needed values stored within the parameters inside a JSP scriptlet just like this:
<%
String primaryKey = request.getParameter("primaryKey");
String name = request.getParameter("name");
String description = request.getParameter("description");
%>
Then I was good to go with my form:
<aui:form action="<%= updateAbbreviationURL %>" method="post">
<aui:input name="primaryKey" type="hidden" value="<%= primaryKey %>" />
<aui:input name="entityName" label="Name" type="text" value="<%= name %>" />
<aui:input name="entityDesc" label="Description" type="text" value="<%= description %>" />
<aui:button name="submit" value="submit" type="submit" />
<aui:button name="cancel" value="cancel" type="button" onClick="<%= viewURL %>" />
</aui:form>
I'd be really grateful if someone told me why my initial implementation didn't work, I mean referring to the parameter values as mentioned above, ${paramName}
Thanks in advance!

Related

Handling authentication failure in auto login in liferay

I have a theme where I have a popup to ask for the login credentials .
It has 2 fields ,login id and password followed by a submit button.
<div class="x">
<div class="y">
<aui:input name="login" id="login" class="z"
type="text" placeholder="Email" showRequiredLabel="<%=false%>" label="" value="<%=login%>">
</aui:input>
</div>
</div>
<div class="x">
<div class="y">
<aui:input name="password" id="Password"
class="z" type="password" placeholder="Password"
showRequiredLabel="<%=false%>" label="" value="<%=password%>">
</aui:input>
</div>
</div>
<div class="x">
<div class="y">
<aui:button-row>
<aui:button type="submit" class="btn z"
value="Log in" id=z/>
</aui:button-row>
</div>
</div>
<script>
jQuery(document).ready(function($) {
$('#z').click(function(){
var textBoxEmail= $('#login').val();
var textBoxPassword= $('#Password').val();
var redirecturl="/home";
var url = Liferay.ThemeDisplay.getPortalURL()+"/c/portal/login?login=" + textBoxEmail + "&password=" +textBoxPassword+"&rememberMe=false&redirect=" + redirecturl;
$("#loginDetails").attr('action',url);
document.getElementById('loginDetails').submit();
}
});
</script>
This logins for the positive case , but if the password or the email entered is incorrecet it displays the
"This webpage is not available
ERR_CONTENT_DECODING_FAILED"
I want to show the failure message in the same page from where i am sending the login details or I want it to be redirected to some URL if the authentication fails.
I am using liferay-6.2-ce-ga3 and the theme is designed in the velocity.
You could redirect to /c/portal/login?redirect=currenturl which redirects to the current url. Writing a Hook is another option if you want to customize more.
So before you even start I would question your design from an architectural standpoint. In Liferay, the login functionality is actually its own portlet (called the login portlet). The correct way to modify the login functionality is via a hook. However, to answer your question more directly, I would modify your code as such (most of this is taken from Liferay's login.jsp).
<portlet:actionURL secure="<%= PropsValues.COMPANY_SECURITY_AUTH_REQUIRES_HTTPS || request.isSecure() %>" var="loginURL">
<portlet:param name="struts_action" value="/login/login" />
</portlet:actionURL>
<aui:form action="<%= loginURL %>" autocomplete='<%= PropsValues.COMPANY_SECURITY_LOGIN_FORM_AUTOCOMPLETE ? "on" : "off" %>' cssClass="sign-in-form" method="post" name="fm">
<aui:input name="saveLastPath" type="hidden" value="<%= false %>" />
<aui:input name="redirect" type="hidden" value="<%= redirect %>" />
<aui:input name="doActionAfterLogin" type="hidden" value="<%= portletName.equals(PortletKeys.FAST_LOGIN) ? true : false %>" />
<%
String loginLabel = null;
String authType = portletPreferences.getValue("authType", StringPool.BLANK);
if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
loginLabel = "email-address";
} else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
loginLabel = "screen-name";
} else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
loginLabel = "id";
}
%>
<aui:input autoFocus="<%= windowState.equals(LiferayWindowState.EXCLUSIVE) || windowState.equals(WindowState.MAXIMIZED) %>" cssClass="clearable" label="<%= loginLabel %>" name="login" showRequiredLabel="<%= false %>" type="text" value="<%= login %>">
<aui:validator name="required" />
</aui:input>
<aui:input name="password" showRequiredLabel="<%= false %>" type="password" value="<%= password %>">
<aui:validator name="required" />
</aui:input>
<span id="<portlet:namespace />passwordCapsLockSpan" style="display: none;"><liferay-ui:message key="caps-lock-is-on" /></span>
<aui:button-row>
<aui:button type="submit" value="sign-in" />
</aui:button-row>
</aui:form>
<aui:script use="aui-base">
var password = A.one('#<portlet:namespace />password');
if (password) {
password.on('keypress', function(event) {
Liferay.Util.showCapsLock(event, '<portlet:namespace />passwordCapsLockSpan');
});
}
</aui:script>
I agree, go with the Login hook or with authentication pipeline using pre and post login filters. The redirection can be done from filters.

Invoke action of core Liferay's portlet (Document Library) using custom portlet's form

I need to call document library portlet's EditFileEntryAction (core liferay) on submitting my custom form.
I have created following actionURL:
<liferay-portlet:actionURL var="editFileEntryURL" portletName="<%=PortletKeys.DOCUMENT_LIBRARY %>" doAsGroupId="${scopeGroupId}" refererPlid="${plid}">
<portlet:param name="struts_action" value="/document_library/edit_file_entry" />
<portlet:param name="uploader" value="classic" />
</liferay-portlet:actionURL>
and I want to submit below form:
<aui:form action="<%= editFileEntryURL %>" cssClass="lfr-dynamic-form" enctype="multipart/form-data" method="post" name="fm">
<aui:input name="<%= Constants.CMD %>" type="hidden" />
<aui:input name="uploadProgressId" type="hidden" value="<%= uploadProgressId %>" />
<aui:input name="repositoryId" type="hidden" value="${themeDisplay.scopeGroupId}" />
<aui:input name="folderId" type="hidden" value="${categoryFolderId}" />
<aui:input name="fileEntryId" type="hidden" value="0" />
<aui:input name="workflowAction" type="hidden" value="<%= WorkflowConstants.ACTION_PUBLISH %>" />
<aui:input name="file" style="width: auto;" type="file">
<aui:validator name="acceptFiles">
'<%= StringUtil.merge(PrefsPropsUtil.getStringArray(PropsKeys.DL_FILE_EXTENSIONS, StringPool.COMMA)) %>'
</aui:validator>
</aui:input>
<aui:input name="title">
<aui:validator errorMessage="you-must-specify-a-file-or-a-title" name="custom">
function(val, fieldNode, ruleValue) {`enter code here`
return ((val != '') || A.one('#<portlet:namespace />file').val() != '');
}
</aui:validator>
</aui:input>
<aui:button type="submit" value="save" name="save" />
</aui:form>
I'd recommend to not have the HTTP-level cross-dependency on Liferay's document library portlet. Rather implement your own upload portlet and use the document library API to store the file yourself.

How to have editable fields through liferay search container?

I am new to liferay development.
I have done good work to display the liferay grid by using liferay search container.
But now the requirement is that some of the fields in the grid should have provision to be modified by user.
Is it possible through liferay search container or do I need to follow any other approach to achieve editable liferay grid?
You can use <liferay-ui:search-container-column-jsp tag or directly use <aui-input /> inside the <liferay-ui:search-container-column-text tag.
Example (I have included code comments with the code sample for your understanding):
<liferay-ui:search-container
emptyResultsMessage="no-assets-selected"
iteratorURL="<%= configurationRenderURL %>"
total="<%= assetEntries.size() %>"
>
<liferay-ui:search-container-results
results="<%= assetEntries.subList(searchContainer.getStart(), searchContainer.getResultEnd()) %>"
/>
<liferay-ui:search-container-row
className="com.liferay.portlet.asset.model.AssetEntry"
escapedModel="<%= true %>"
keyProperty="entryId"
modelVar="assetEntry"
>
<aui:form action="doesThisWork?">
<%-- this is the normal way --%>
<liferay-ui:search-container-column-text
name="type"
value="<%= assetRendererFactory.getTypeName(locale, false) %>"
/>
<liferay-ui:search-container-column-date
name="modified-date"
value="<%= assetEntry.getModifiedDate() %>"
/>
<%--
this is the JSP way
You can include anything in the JSP like <input /> fields, textarea, select drop-down etc.
--%>
<liferay-ui:search-container-column-jsp
align="right"
path="/html/portlet/asset_publisher/asset_selection_action.jsp"
/>
<%--
Here is including <input /> field inside the column text field.
Notice I am not using the "value" attribute of this tag, instead I am
writing HTML inside the body of this tag.
--%>
<liferay-ui:search-container-column-text
name="type"
>
<aui:input type="text" name="enterSomething" value="I can enter input here" />
<aui:input type="text" name="enterSomething" value="<%=assetEntry.getTitle %>" />
<aui:input type="hidden" name="enterSomething" value="this is a hidden field of the form" />
</liferay-ui:search-container-column-text>
</aui:form>
</liferay-ui:search-container-row>
<liferay-ui:search-iterator paginate="<%= total > SearchContainer.DEFAULT_DELTA %>" />
</liferay-ui:search-container>
In the above example, there would be a <form> for each row, so you can have a submit button at the end of each row to submit the data for that row.
But you can do it in other ways as well:
You can write the <form> outside the Search-container tag so that you just have one form and can submit all the row data togather
Or else you can have a <form> somewhere down the page and through javascript populate the value in the form and then submit.
Or else you can use ajax and other stuff to accomplish this. Or a combination of several approaches.
I leave this upto you to figure out.
Disclaimer: I have not test this code. But as per my understanding this should work. :-)

how to prevent aui-form from submission , when aui required filed validator is empty

I have a form and a required field as shown below.
I added aui field validator for preventing form from submitting if the required field is empty.
But its not working.
Somebody please help me.
<aui:form id="fm" name="fm" method="post" action="<%= someURL %>">
<aui:input id="txtArea" label="value" name="preferences--txtArea--" type="textarea" style="width:330px;height:65px;" >
<aui:validator name="required" />
</aui:input>
<aui:input name="termsAndCondition" id="termsAndCondition" type="checkbox" label="termsAndConditons"/> <br>
<aui:button type="button" value="save" onClick="showDialog()" />
</aui:form>
<aui:script>
function showDialog()
{
var termsAndCondition= A.one('#<portlet:namespace/>termsAndCondition').attr('value');
var r=confirm("Are you sure to change data?");
if (r==true && termsAndCondition=="true")
{
A.one('#<portlet:namespace/>fm').submit();
}
}
</aui:script>
Try with this approach
<aui:form id="fm" name="fm" method="post" action="<%= someURL %>" onSubmit="check();>
<script type="text/javascript">
function check()
{
}
</script>
OR
you can return false from your function showDialog()
Hope this will help you
I found mistake in my code..
I used button type = "button" as you can see
<aui:button type="button" value="save" onClick="showDialog()" />
but for using aui field validator work according to requirement, to prevent from submitting the form when required field is empty. use button type="submit". so corrected line is
<aui:button type="submit" value="save" onClick="showDialog()" />
Now its working fine :) :)

How to convert a portal URL to its corresponding friendly URL

I have implemented friendly-url successfully for few of my custom portlets and it is working fine.
When click-able links are generated, it correctly shows the friendly-url.
Now my requirement is that, I need to send this render-URL (say URL01) as a parameter (param02) to another URL (URL02) and this URL01 then would be displayed on another page.
This is how URL01 is generated:
<portlet:renderURL var="URL01" windowState="<%=WindowState.MAXIMIZED.toString() %>">
<portlet:param name="redirect" value="<%= currentURL %>" />
<portlet:param name="myId" value="<%= String.valueOf(myObject.getMyId()) %>" />
<portlet:param name="title" value="<%= myObject.getTitle() %>" />
<portlet:param name="name" value="<%= myObject.getName() %>" />
</portlet:renderURL>
This is how URL02 is generated
<portlet:renderURL var="URL02" windowState="<%= LiferayWindowState.POP_UP.toString() %>">
<portlet:param name="redirect" value="<%= currentURL %>" />
<portlet:param name="URL01" value="<%=URL01 %>" />
<portlet:param name="ownerId" value="<%= String.valueOf(ownerId) %>" />
<portlet:param name="groupId" value="<%= String.valueOf(scopeGroupId) %>" />
</portlet:renderURL>
This URL02 would open a pop-up and the URL01 would be displayed as below in the JSP:
URL: <%= ParamUtil.getString(request, "URL01") %>
But this shows URL01 (unfriendly-URL) as:
URL: http://localhost:8080/web/guest/mypage?p_p_id=my_WAR_myportlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_my_WAR_myportlet_myId=10989&_my_WAR_myportlet_title=This+is+miine&my_WAR_myportlet_name=What+name
If this is a clickable link it generates perfectly as (friendly-URL):
Click me!
So I need a utility which can convert my unfriendly-url to friendly-URL, something like if a String of unfriendly-url is passed - it would convert that to the friendly-url shown above.
Or I have to create an implementation of my own to achieve this?
Edit:
<route>
<pattern>/{myId:\d+}/{title:.+}/{name:.+}/{p_p_state}</pattern>
<ignored-parameter name="redirect" />
<implicit-parameter name="p_p_id">my_WAR_myportlet</implicit-parameter>
<implicit-parameter name="p_p_lifecycle">0</implicit-parameter>
<implicit-parameter name="p_p_mode">view</implicit-parameter>
</route>
And yes the URL01 is written above the URL02 in the JSP.
I think you can create your own <portlet-url-class> and it will be used when you create the portlet URL with the <portlet:renderURL> tag.
In liferay-portlet.xml, you can define the <portlet-url-class> entry.
If you check the source code of PortletResponseImpl.java, the method createLiferayPortletURL() checks for the PortletURLGenerationListener for that portlet.
I think, you can create a this one and modify URL as you want to.

Resources