How to add success message and failure messages in Liferay? - liferay

I have requirement that:
After submitting the request, Liferay displays the message
Your request processed successfully
Instead of that I have to add custom messages and display them like course created
successfully, course deleted successfully, course modified successfully etc..
Is it possible? Is there any way to display the success or failure message?
<%#page import ="javax.portlet.PortletURL" %>
<%# page import="javax.portlet.RenderResponse" %>
<%# page import="javax.portlet.ActionRequest" %>
<%# page import="com.liferay.portal.kernel.util.Validator" %>
<%
PortletURL searchCourseURL=renderResponse.createActionURL();
searchCourseURL.setParameter(ActionRequest.ACTION_NAME,"findCourses");
%>
<script type="text/javascript" src="/html/js/jquery/jquery.js"></script>
<form action="<%=searchCourseURL%>" method="post">
<div class="label1">Enter Course Name</div><input type="text" id="cname" name="cname" value=" "/>
<input type="submit" name="submit" value="Submit"/>
</form>
In the above example, after submitting the request it displays like request process successfully instead I have to display the message:
search is completed

Success messages
In the JSP:
<liferay-ui:success key="key" message="message" />
<liferay-ui:success key="key1" message="message1" />
In Language.properties file
message=search is completed...
message1=search is completed...
In Controller
SessionMessages.add(request, "key");
SessionMessages.add(request, "key1");
Error (failure) messages
In the JSP:
<liferay-ui:error key="error-key" message="error-message" />
<liferay-ui:error key="error-key1" message="error-message1" />
In Language.properties file:
error-message=search couldn't be completed...
error-message1=search couldn't be completed...
In Controller:
SessionErrors.add(request, "error-key");
SessionErrors.add(request, "error-key1");

Related

Worldpay Token Confusion

Trying to implement Worldpay integration. The docs at https://online.worldpay.com/docs/take-card-details-templates mention a token. I have tested the page and I dont get any token. Wandering how i can get this token.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="payment2.aspx.cs" Inherits="payment2" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src= "https://cdn.worldpay.com/v1/worldpay.js">
</script>
<script type='text/javascript'>
window.onload = function () {
Worldpay.setClientKey('T_C_a453a70e-c5e6-4618-9c7b-96f787f0fa04');
Worldpay.reusable = false;
Worldpay.useTemplate('payment-form', 'my_payment_section', 'inline');
}
</script>
</head>
<body>
<form action="/complete" id="payment-form" method="post">
<!— all other fields you want to collect, e.g. name
and shipping address -->
<div id='my_payment_section'></div>
<div>
<input type="submit" value="Place Order" />
</div>
</form>
</body>
</html>
When the window.onload executes, it puts the WorldPay card capture form on your page. By the looks of it, you haven't disabled their Save Payment button, so are you trying to use your own submit button?? If you are trying to use your submit button, then you should add the onclick attribute to submit the worldpay template.
<input type="submit" value="Place Order" />
<form action="/complete" id="payment-form" method="post">
<div id="my_payment_section"></div>
<div>
<input id="submitCard" onclick="Worldpay.submitTemplateForm()" value="Confirm Payment" />
</div>
</form>
Once the form submits, worldpay.js takes over, and it will handle the sensitive card information, validate it and if all is ok, it will replace the cardDetails div with a single hidden input field which is the token.
If that all happens correctly, with no errors, after the token input has been placed in the DOM, the form will submit to your action "/complete", and the token will be part of the submitted values of the form.
Hope that helps.
Your script is missing the callback to generate the token in useTemplate()
See: https://developer.worldpay.com/jsonapi/docs/template-form
The callback generates the hidden input with the token value for you which posts to worldpay.
your script should be:
<script type='text/javascript'>
window.onload = function() {
Worldpay.useTemplateForm({
'clientKey':'T_C_a453a70e-c5e6-4618-9c7b-96f787f0fa04',
'form':'paymentForm',
'paymentSection':'paymentSection',
'display':'inline',
'reusable':false,
'callback': function(obj) {
if (obj && obj.token) {
var _el = document.createElement('input');
_el.value = obj.token;
_el.type = 'hidden';
_el.name = 'token';
document.getElementById('paymentForm').appendChild(_el);
document.getElementById('paymentForm').submit();
}
}
});
}
</script>
You also need the onclick="Worldpay.submitTemplateForm()" attribute on your submit too.

Issue with Liferay UI tab Navigation

I am using <liferay-ui:tabs> for displaying jsp pages as tabs. I am able to see my pages as tabs but If I navigate to one of my pages in the tab and on click of the button then it is navigating to some other page, that it showing in a separate page instead of showing under that tab. I need to click of button events the control should be still under the tabs. my Code is as follows,
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%><%#include file="/html/users/init.jsp"%>
<portlet: defineObjects />
<portlet:renderURL var="navigateTabURL"/>
<% String navigateTab = ParamUtil.getString(request, "tabs1","Current"); %>
<liferay-ui:tabs names="Current, Available" url="<%=navigateTabURL.toString()%>" >
<c:if test='<%= navigateTab.equalsIgnoreCase("Current")%>' >
<jsp:include page="current_members.jsp" flush="true" />
</c:if>
<c:if test='<%= navigateTab.equalsIgnoreCase("Available")%>' >
<jsp:include page="available_members.jsp" flush="true" />
</c:if>
</liferay-ui:tabs>
The pages "Current" and "Available" are showing correctly, But If I click any button in my Current page it is navigating to some other jsp I need that jsp also under that tabs only not showing as a separate page.
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%><%#include file="/html/users/init.jsp"%>
<portlet: defineObjects />
<%
List<User> userList = (List) request.getAttribute("UserGroupList");
//out.println(userList.size());
%>
<%!
List<User> users = null;
int totalNoOfUsers=0;
String value = null;
%>
<%
//totalNoOfUsers = UserLocalServiceUtil.getUsersCount();
totalNoOfUsers = userList.size();
users = userList;
%>
<liferay-ui:search-container delta="5" emptyResultsMessage="no-users-were-found" rowChecker="<%= new RowChecker(renderResponse) %>" >
<liferay-ui:search-container-results results="<%= ListUtil.subList(users,searchContainer.getStart(),searchContainer.getEnd()) %>"
total="<%= totalNoOfUsers %>">
</liferay-ui:search-container-results>
<liferay-ui:search-container-row className="com.liferay.portal.model.User" keyProperty="userId" modelVar="user">
<liferay-ui:search-container-row-parameter name="userIds" value="<%= user.getUserId()%>">
</liferay-ui:search-container-row-parameter>
<liferay-ui:search-container-column-text name="UserName" value="
<%= user.getScreenName()%>" />
<liferay-ui:search-container-column-text name="First Name" value="<%= user.getFirstName() %>">
</liferay-ui:search-container-column-text>
<liferay-ui:search-container-column-text name="Last Name" value="<%= user.getLastName() %>">
</liferay-ui:search-container-column-text>
<liferay-ui:search-container-column-jsp align="right" path="/html/users/custom_user_actions.jsp" />
</liferay-ui:search-container-row>
<liferay-ui:search-iterator />
</liferay-ui:search-container>
<liferay-ui:search-container delta="5" emptyResultsMessage="no-users-were-found" />
<portlet:actionURL name="viewEntry" var="viewEntryURL"></portlet:actionURL>
<aui:form action="<%= viewEntryURL %>" name="<portlet:namespace />fms">
<aui:button type="submit" value="Cancel"></aui:button>
</aui:form>
How do I navigate the tabs as dynamic requests. Any suggestions please!!
To retain a tab selection, "value" attribute of should be mentioned with name of tab to select.
If "value" attribute not specified then first tab will be considered as active.
For example, please refer following file in liferay portal sources.
portal-web/docroot/html/portlet/dockbar/add_panel.jsp
Also, below post in liferay forum should help.
http://www.liferay.com/en_GB/community/forums/-/message_boards/message/4809190

liferay-ui:captcha customization/localization in Liferay 6.2

After migration to Liferay 6.2 <liferay-ui:captcha> customization stopped working:
original input is no longer hidden
refresh link appeared (we need it hidden, or translate label and remove bugged tooltip - it flickers on hover)
LFR 6.1 code:
xmlns:form="http://www.springframework.org/tags/form"
xmlns:liferay-ui="http://liferay.com/tld/ui"
<liferay-ui:captcha url="${captchaURL}"/>
<label for="captchaText" >
Opiste text z obrazku
</label>
<form:input id="captchaText" path="captcha" />
What is the proper way to customize captcha component?
I tried replacing our ids to match ids of fields generated by Liferay, but it did not work.
Code generated by Liferay:
<div class="taglib-captcha" id="yui_patched_v3_11_0_1_1425121596007_13262">
<img alt="Text to Identify" class="captcha"
id="_pspmlmuserportlet_WAR_pspmlmuserportlet_captcha"
src="..."/>
<span class="refresh" onmouseover="Liferay.Portal.ToolTip.show(this, 'Refresh CAPTCHA')"
data-title="" id="yui_patched_v3_11_0_1_1425121596007_13261">
<a href="javascript:;" class=" taglib-icon" id="_pspmlmuserportlet_WAR_pspmlmuserportlet_refreshCaptcha">
<img id="refreshCaptcha" src=".../refresh.png" alt="Refresh CAPTCHA" title="Refresh CAPTCHA"/>
<span class="taglib-text hide-accessible">Refresh CAPTCHA</span>
</a>
</span>
<div class="form-group" id="yui_patched_v3_11_0_1_1425121596007_14890">
<label class="control-label" for="_pspmlmuserportlet_WAR_pspmlmuserportlet_captchaText">
Text Verification <span class="label-required">(Required)</span>
</label>
<input class="field form-control" id="_pspmlmuserportlet_WAR_pspmlmuserportlet_captchaText"
name="_pspmlmuserportlet_WAR_pspmlmuserportlet_captchaText" type="text" value="" size="10"/>
</div>
</div>
I can probably do it by jQuery, but I would be interested in a proper way to do it.
Thanks
I think the best way should be working in ext environment, for modify your UI taglib code... I'm not sure you can hook a taglib.
You can customize the UI taglib: captcha via hook. Here's an example enter link description here. In this example I set the theme of the reCaptcha via properties.
Liferay 6.2 code for create a simple captcha
<%# taglib uri="http://alloy.liferay.com/tld/aui" prefix="aui"%>
<%# taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%# taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %>
This URL will be invoked before showing the CAPTCHA image
<portlet:resourceURL var="captchaURL"/>
This is the Html code to display the image
<aui:column columnWidth="10" first="true">
<div class="input-piwest-captcha">
<liferay-ui:captcha url="<%=captchaURL%>" />
</div>
<div class="input-piwest-captchaError">
<liferay-ui:error key="errorMessage" message="Code does not match. Please try again."/>
</div>
</aui:column>
Java Code
import com.liferay.portal.kernel.captcha.CaptchaException;
import com.liferay.portal.kernel.captcha.CaptchaUtil;
#ResourceMapping
public void serveResource(ResourceRequest resourceRequest,
ResourceResponse resourceResponse) throws IOException {
CaptchaUtil.serveImage(resourceRequest, resourceResponse);
}
private String getCaptchaValueFromSession(PortletSession session) {
Enumeration<String> atNames = session.getAttributeNames();
while (atNames.hasMoreElements()) {
String name = atNames.nextElement();
if (name.contains("CAPTCHA_TEXT")) {
return (String) session.getAttribute(name);
}
}
return null;
}
Validate the CAPTCHA TEXT
PortletSession session = actionRequest.getPortletSession();
String enteredCaptchaText = ParamUtil.getString(actionRequest, "captchaText");
String captchaText = getCaptchaValueFromSession(session);
if (Validator.isNull(captchaText) || !StringUtils.equals(captchaText, enteredCaptchaText)) {
throw new CaptchaException("Invalid captcha text. Please reenter.");
}

FacesContext redirect with POST parameters

I need to redirect page into external site with POST parameters, but I cannot use vanilla HTML <form action="url"> like it is explained here:
JSF commandButton - passing POST params to an external site
because then the form would be within a jsf form - and it doesn't work.
Is it possible to use:
FacesContext.getCurrentInstance().getExternalContext().redirect("http://example.com");
with POST parameters without additional vanilla form somehow? Or maybe there is other way to acheive this without form?
Try something like this:
JAVASCRIPT:
function redirect() {
document.getElementById("mySubmitButton").submit();
}
XHTML:
<h:form>
<span onclick="javascript:redirect()" class="linkClass">REDIRECT</span>
</h:form>
<div style="display:none:"> <!-- If you want it hidden -->
<form action="http://external/myplace.html" method="post">
<input type="hidden" value="value1"></input>
<input type="submit" id="mySubmitButton"</input>
</form>
</div>
EDIT: Added another test.
PASSING DYNAMIC PARAMETER:
In this example we assume that we are always going to send a value.
JAVASCRIPT:
function redirect(dynamicValue) {
document.getElementById("dynamicField").value = dynamicValue;
document.getElementById("mySubmitButton").submit();
}
XHTML:
<h:form>
<span onclick="javascript:redirect('myValue')" class="linkClass">REDIRECT</span>
</h:form>
<div style="display:none:"> <!-- If you want it hidden -->
<form action="http://external/myplace.html" method="post">
<input id="dynamicField" type="hidden" value=""></input>
<input type="hidden" value="value1"></input>
<input type="submit" id="mySubmitButton"</input>
</form>
</div>

model undefined on page reload

I'm trying example from this site. It works fine. But if i separate views,models,routers into separate file it gives me a problem. There is 3 views. WineList view, WineListItemView and winedetails view. WineList view takes collection of wine models as model and winelistItem and winedetails view takes wine as a model.
Router's code is like this
var app = app || {};
app.AppRouter = Backbone.Router.extend({
routes:{
"":"list",
"wines/:id":"wineDetails"
},
initialize:function () {
$('#header').html(new app.HeaderView().render().el);
},
list:function () {
this.wineList = new app.WineCollection();
this.wineListView = new app.WineListView({model:this.wineList});
this.wineList.fetch();
$('#sidebar').html(this.wineListView.render().el);
},
wineDetails:function (id) {
if(this.wineList == undefined)
{
this.wineList = new app.WineCollection();
this.wineListView = new app.WineListView({model:this.wineList});
this.wineList.fetch();
$('#sidebar').html(this.wineListView.render().el);
}
this.wine = this.wineList.get(id);
if (app.router.wineView) app.router.wineView.close();
this.wineView = new app.WineView({model:this.wine});
$('#content').html(this.wineView.render().el);
}
});
On page load it fetches models from server and displays list of wines in sidebar div of page. When i click on particular wine item its details will be displayed in content div of page. That all works fine. But when i reload that page which now contains details of particular,wine model of Winedetails view gives undefined .
I'm intializing the router on main page like this
app.js
var app = app || {};
$(function() {
})
app.router = new app.AppRouter();
Backbone.history.start();
index.html
<!DOCTYPE HTML>
<html>
<head>
<title>Backbone Cellar</title>
<link rel="stylesheet" href="../css/styles.css" />
</head>
<body>
<div id="header"><span class="title">Backbone Cellar</span></div>
<div id="sidebar"></div>
<div id="content">
<h2>Welcome to Backbone Cellar</h2>
<p>
This is a sample application part of of three-part tutorial showing how to build a CRUD application with Backbone.js.
</p>
</div>
<div>
Next page
</div>
<!-- Templates -->
<script type="text/template" id="tpl-header">
<span class="title">Backbone Cellar</span>
<button class="new">New Wine</button>
</script>
<script type="text/template" id="tpl-wine-list-item">
<a href='#wines/<%= id %>'><%= name %></a>
</script>
<script type="text/template" id="tpl-wine-details">
<div class="form-left-col">
<label>Id:</label>
<input type="text" id="wineId" name="id" value="<%= id %>" disabled />
<label>Name:</label>
<input type="text" id="name" name="name" value="<%= name %>" required/>
<label>Grapes:</label>
<input type="text" id="grapes" name="grapes" value="<%= grapes %>"/>
<label>Country:</label>
<input type="text" id="country" name="country" value="<%= country %>"/>
<label>Region:</label>
<input type="text" id="region" name="region" value="<%= region %>"/>
<label>Year:</label>
<input type="text" id="year" name="year" value="<%= year %>"/>
<button class="save">Save</button>
<button class="delete">Delete</button>
</div>
<div class="form-right-col">
<img height="300" src="../pics/<%= picture %>"/>
<label>Notes:</label>
<textarea id="description" name="description"><%= description %></textarea>
</div>
</script>
<!-- JavaScript -->
<script src="js/lib/jquery.min.js"></script>
<script src="js/lib/underscore.js"></script>
<script src="js/lib/backbone.js"></script>
<script src="js/models/WineModel.js"></script>
<script src="js/collections/WineListCollection.js"></script>
<script src="js/Views/WineListView.js"></script>
<script src="js/Views/WineListItemView.js"></script>
<script src="js/Views/WineDetailsView.js"></script>
<script src="js/Views/HeaderView.js"></script>
<script src="js/routers/routers.js"></script>
<script src="js/app.js"></script>
</body>
</html>
I'm new to this backbone technology. please tell me what am i missing
this.wineList.fetch();
fires an asynchronous request to your server, which means that the content will arrive (or not) at some point after executing this line, but your application execution continues whether the response arrived or not. On page reload (assume you have wines/:id in the URL) first you have to fetch the complete list of wines before accessing any particular wine from the collection.
You have to wait until is download the collection, and access the wine with id, after this request is finished.
So after initiating the request continue your application logic in the success callback:
this.wineList.fetch({
success: function(model) {
...
this.wine = model.get(id);
...
}
});

Resources