Ajax Pagination in Liferay Search Container - ajax

I am trying to Ajax Call on Search Container Pagination. As there are more than one portlet on same page I don't want to each portlet to forcefully call render every time when I do Pagination.
There could be 2 possible solutions but I am facing some problem. Please help me to solve it.
1) Can you please tell me how to edit Liferay Search Container Pagination URL by changing its Portlet Life-cycle from 0 to 2 ? How to create hook ?
2) There is a tag called <liferay-ui:page-iterator/> in which there is a attribute called jsCall. It is used for pagination without page reloading. I am unable to find out how to use it ?
If it can be solved using 2nd option then it would be much helpful.
Thank You.

kanakhara,
Each time I faced that problem I had to implement manually a pagination because search-container is really embedded to be modified by a developer.
Maybe could be a solution to this problem but it's not sure that it exists.
You'll spend less time creating your own pagination for this purpose.
I hope it can help you.
Best wishes

Yes, I know how to use it.
I'll give you an example to do it:
<portlet:renderURL var="manageRelationsURL"
windowState="<%=LiferayWindowState.NORMAL.toString()%>">
<portlet:param name="action" value="manageRelations" />
</portlet:renderURL>
<%PortletURL iteratorURL = renderResponse.createRenderURL();
iteratorURL.setParameter("action", "manageRelations");
%>
<%
PortalPreferences portalPrefs = PortletPreferencesFactoryUtil.getPortalPreferences(request);
String orderByCol = ParamUtil.getString(request, "orderByCol");
String orderByType = ParamUtil.getString(request, "orderByType");
if (Validator.isNotNull(orderByCol) && Validator.isNotNull(orderByType)) {
portalPrefs.setValue("NAME_SPACE", "order-by-col", orderByCol);
portalPrefs.setValue("NAME_SPACE", "order-by-type", orderByType);
} else {
orderByCol = portalPrefs.getValue("NAME_SPACE", "order-by-col", "domainLabel");
orderByType = portalPrefs.getValue("NAME_SPACE", "order-by-type", "asc");
}
%>
<div style="">
<aui:form>
<liferay-ui:search-container delta="20" iteratorURL="<%=iteratorURL%>" emptyResultsMessage="There were not any match." orderByCol="<%= orderByCol %>" orderByType="<%= orderByType %>">
<liferay-ui:search-form
page="/WEB-INF/jsp/localAdministration/relations/search.jsp"
searchContainer="<%= searchContainer %>"
servletContext="<%= this.getServletConfig().getServletContext() %>"
showAddButton="true" />
<liferay-ui:search-container-results>
<%
List<RelationInstance> relationList = UtilsAdministration.getRelationListCache(themeDisplay.getUserId(),0, UtilsAdministration.getRelationListCacheSize(themeDisplay.getUserId()));
Collections.sort(relationList,RelationsComparator.getRelationsOrderByComparator(orderByCol, orderByType));
results = ListUtil.subList(relationList, searchContainer.getStart(),
searchContainer.getEnd());
if(relationList.size()<searchContainer.getEnd()){
results = ListUtil.subList(relationList, searchContainer.getStart(),
relationList.size());
total = relationList.size();
}else{
results = ListUtil.subList(relationList, searchContainer.getStart(),
searchContainer.getEnd());
total = relationList.size();
}
pageContext.setAttribute("results", results);
pageContext.setAttribute("total", total);
%>
</liferay-ui:search-container-results>
<liferay-ui:search-container-row className="RelationInstance" modelVar="aRelationInstance">
<liferay-ui:search-container-column-text name="First" value="<%=aRelationInstance.getFirstLabel()%>" orderable="<%= true %>" orderableProperty="domainLabel"/>
<liferay-ui:search-container-column-text name="Second" value="<%=aRelationInstance.getSecondLabel()%>" orderable="<%= true %>" orderableProperty="relationLabel"/>
<liferay-ui:search-container-column-text name="Third" value="<%=aRelationInstance.getRangeLabel()%>" orderable="<%= true %>" orderableProperty="rangeLabel"/>
<liferay-ui:search-container-column-jsp align="right" name="Acciones" path="/WEB-INF/jsp/localAdministration/relations/actionRelationButton.jsp"/>
</liferay-ui:search-container-row>
<liferay-ui:search-iterator />
</liferay-ui:search-container>
</aui:form>
</div>
In this case I retrieve the list to iterate from EhCache instead of DB.
IteratorURL must contains the same URL that the page you're invoking.
I hope it could be useful for you.

Related

If search don't return values from database show an empty form

So i got a page that have a search form, and when the user search for a value if there are no records on database the form returns empty, but if there are records the form is populated with data.
What i was thinking was this
var db = Database.Open("myDataBase");
var selectCommand = "SELECT * FROM exportClient";
var searchTerm = "";
if(!Request.QueryString["searchField"].IsEmpty() ) {
selectCommand = "SELECT * FROM exportClient WHERE clientAccount = #0";
searchTerm = Request.QueryString["searchField"];
}
if(IsPost){
var selectedData = db.Query(selectCommand, searchTerm);
}
And Then:
<body>
<div class="col_12">
<form method="get">
<label>search</label><input type="text" class="col_3" name="searchField" />
<button type="submit" class="button red" value="search">search</button>
</form>
</div>
#if(!Request.QueryString["searchField"].IsEmpty() ){
foreach(var row in db.Query(selectCommand, searchTerm)) {
<div class="col_12 box">
<form method="post">
// HERE IS THE FORM POPULATED
</form>
</div>
}
} else {
<div class="col_12 box">
<form method="post">
// HERE IS THE FORM NOT POPULATED
</form>
</div>
}
</body>
But what is happening is that the form that is not populated is always showing up when i enter the page, and i need that the only thing that user see when enter the page is the input field to do the search.
What am i doing wrong ?
I'm not sure of having understood your goal, but in my opinion your main problem is to detect if either exists or not a query string.
I think that your code should be like this
#if(Request.QueryString.HasKeys())
{
if(!Request.QueryString["searchField"].IsEmpty() ){
<p>searchField has value</p>
} else {
<p>searchField hasn't value</p>
}
}
There are a number of potential issues I can see with your code, hopefully you can put these together to achieve what you wanted:
As Selva points out, you are missing the action attribute on your forms.
The selectedData variable you create inside your IsPost() block goes out of scope before you do anything with it. Perhaps you didn't include all your code though, so ignore this if it just isn't relevant to the question.
To answer the main question: if you don't want the empty form to appear when the user hasn't yet performed a search, surely you just need to completely remove the else block - including the empty form - from your HTML?
Hope that helps.

Proccess HTML tags to Spring MVC View

I'm currently struggling with the following problem. In my Spring web application I have different content types (e.g. text, images or code). Depending on the content type I need to display it in different ways:
text: <p>some text</p>
image: <img src="path/to/my.img" />
code <pre>some code</pre>
The HTML tags should be concatened to the actual content. The problem is, if I simply build the output text in my Java class, the HTML tags won't be resolved in my view, so that <p>some text</p> will be displayed.
Is it somehow possible that the HTML tags can be resolved in my view?
If it's just the escaping part that is the problem, use:
<c:out value="${model.snippets.html12}" escapeXml="false" />
(I am assuming your HTML string is in the model.snippets.html12).
Of course, the whole idea is bad. I am not affiliated with the MVC Police, but what is the point of using a MVC framework if you feel that it's a good idea to generate HTML inside your controller and pass it, as a string - into a view? From my point of view it's a bit of a schizophrenia.
You can save a lot of sanity by just rendering the whole thing in a switch, inside the template. I mean like:
<c:choose>
<c:when test="${thing.type == 'CODE'}">
<div> some code: ${thing.content} </div>
</c:when>
<c:when test="${thing.type == 'IMAGE'}">
<img src="${thing.src}" alt="${thing.whatever}" />
</c:when>
<!-- some other choices -->
</c:choose>
Even better, create a simple tag file that will let you reuse the logic anywhere you need it.
Or ditch MVC - be honest.
If you do have jquery, set the content type in your model. Set it to the HTML.
<input type = hidden id = contentType value = "${yourmodel.contentType}"
Add span to your elements
<span id = "textspan" style = "display:none"><p>some text</p></span>
<span id = "imgspan><img src="path/to/my.img" /></span>
<span id = "codespan><pre>some code</pre></span>
write a jquery
if($("contentType").val() == text){
$("#textspan").show();
}else if($("contentType").val() == img){
$("#imgspan").show();
}else{
$("#codespan").show();
}

MVC3 Drop Down or ListBox with dynamic check boxes

I have an MVC3 C#.Net web app. I have a requirement to display a list of check boxes (either in a drop down or a List Box) dynamically based on a table in our db. The table can contain 1:500 entries. I then need to pass the selected check boxes to the Controller in order to perform an action on each selection. Any ideas on an implementation?
There are many ways to go about this but here is a general demo.
You can pass a list of the checkbox values and descriptions either on the Model (as this example does), ViewData[""] dictionary or ViewBag (MVC3+).
Then in your view loop through them and add them to your form using the name="chxBxGroupName" to group them.
Now create a controller action to post to that takes a List of the value type (in this example int) with the parameter naming matching the name="chxBxGroupName".
It will post a list of checked values.
The post page will just print out:
123
456
// This is your landing page. It gathers the data to display to the user as checkboxes.
public ViewResult MyPageWithTheCheckboxes()
{
// For example: Assume a Dictionary with the checkbox value and description
// Replace with DB call, etc.
return View(new Dictionary<int, string> { { 123, "Foo" }, { 456, "Bar" } });
}
<%# Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<Dictionary<int,string>>" %>
<!-- Rest of HTML page... -->
<form id="frm1" action="<%=Url.Action("MyPost")%>" method="post">
<% foreach (var item in Model) { %>
<input type="checkbox" id="chxBx<%=item.Key%>" name="chxBxGroupName" value="<%=item.Key%>"/>
<label for="chxBx<%=item.Key%>"><%=item.Value%></label>
<br/><br/>
<% } %>
<input type="submit" value="Go!"/>
</form>
<!-- Rest of HTML page... -->
public ContentResult MyPost(List<int> chxBxGroupName)
{
return Content(string.Join(Environment.NewLine, chxBxGroupName ?? new List<int>()), "text/plain");
}
the answer provided by Jay accomplishes exactly what you need. If you want to put the items in a list you can do it by surrounding the markup with a div control lie below
<div style="height:40px;overflow:auto;">
<% foreach (var item in Model) { %>
<input type="checkbox" id="chxBx<%=item.Key%>" name="chxBxGroupName" value="<%=item.Key% >"/>
<label for="chxBx<%=item.Key%>"><%=item.Value%></label>
<br/><br/>
<% } %>
</div>
unfortunately you cant have checkboxes in a <select />, but if you really wanted it to look like a select list you could add some JQuery that processes onclick of a textbox and shows the div. This obviously would require some jQuery and might not be worth it

How to rerender part of page after ajax submit of form in Lift (Scala)

this is probably a stupid question but I cannot figure out how to do it.
So I'm new to Scala/Lift and I read the ajax form chapter in http://simply.liftweb.net/index-4.8.html#toc-Section-4.8 but the "RedirectTo" in the example does not seem to be very "ajaxian" to me. Often in case of submitting a form via ajax, you would just partially rerender the same page, right?
So that's what I'm trying to do and am completely failing right now.
How do I let Lift rerender just a part of the same page after I submit the form via ajax?
Any hints would be appreciated. Thanks.
Basically, what I have looks like this:
<div id="main" class="lift:surround?with=default;at=content">
<h2>Welcome to your project!</h2>
<div class="lift:Test">
<div>
<form class="lift:form.ajax">
<fieldset>
<label for="name">Name:</label>
<input id="name" name="name" type=text>
<p></p>
<input id="save" type="submit" value="Save">
</fieldset>
</form>
</div>
<div>
<span id="theName">Name</span>
</div>
</div>
</div>
class Test {
def render = {
var name = ""
def process(): JsCmd = {
Thread.sleep(500)
S.notice("Entered name is: %s".format(name))
Noop
}
"#theName " #> "This shall be updated with the name given in the form above" &
"#name" #> (SHtml.text(name, name = _) ++ SHtml.hidden(process))
}
}
How would I update "theName" when submitting the form?
Have a look at http://lift.la/shtmlidmemoize-simple-ajax-updating (Example Code). There is SHtml.memoize and SHtml.idMemoize which automatically caches the HTML code. Not sure why it is not used in this example in the Simply Lift book.
You have a 2 step form right? The above poster is correct.
Save your transformation in a RequestVar.
in your above example, the method you want to save is render, so 1st memoize the transform:
private def renderTest= SHtml.memoize { render }
Then, you can save this memoized transformation in a RequestVar (lasts for 1 request), or maybe a TransientRequestVar depending on your needs.
private object testTemplate extends RequestVar(renderTest)
When you want to replay the transform, from an ajax event - testTemplate.is.applyAgain.
I might have misunderstood the original question, b/c if you want to do a 2 step form, you don't really need the memoize. The memoize is if something changes on your current form, and you want to update it via an ajax event, i.e. on click or on change, b/c normally the form wouldn't update unless you did an ajax submit.

How to get model's field name in custom editor template

I'm building my first custom editor template for a text area control. My code so far is -
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%= Html.TextAreaFor( Model => Model , 2, 30,
new { #class = "html", #placeholder = ViewData.ModelMetadata.Watermark }) %>
It's not much so far, but it does work. But we need to add a character counter field to show remaining number of characters that the user can type in. I know how to do all the JavaScript to make this work.
So to keep naming system same, I'm going to add a control named ".charCounter" to display number of remaining characters left. My problem is that I cannot figure out the correct syntax to be able to retrieve the field name for the model.
The final version will look something like (JavaScript omitted) -
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%= Html.TextAreaFor( Model => Model , 2, 30,
new { #class = "html", #placeholder = ViewData.ModelMetadata.Watermark }) %>
<span class="xxx">Remaining characters -
<input readonly type="text" name="<fieldName>.charCounter" />
</span>
You could use ViewData.TemplateInfo.HtmlFieldPrefix, like this:
<input
readonly="readonly"
type="text"
name="<%= ViewData.TemplateInfo.HtmlFieldPrefix %>.charCounter"
/>
I ran into an issue where the PropertyName wasn't returning the Model prefix eg Contact.FirstName. I was able to have it return the HTML field Id using this:
#ViewData.TemplateInfo.GetFullHtmlFieldId("")
Returns:
Contact_FirstName
Respectively you can return the field name using:
#ViewData.TemplateInfo.GetFullHtmlFieldName("")
Returns:
Contact.FirstName
ViewData.ModelMetadata.PropertyName works nicely in MVC3.
In razor:
<input readonly="readonly" type="text" name="#ViewData.ModelMetadata.PropertyName">
Getting just the model name/Id (e.g BirthDate):
ViewData.ModelMetadata.PropertyName;
Getting the model name with prefixes for complex objects (e.g Identity.Person.BirthDate):
#Html.NameFor(m => Model);
or
ViewData.TemplateInfo.HtmlFieldPrefix;
Getting the model Id with prefixes for complex objects (e.g Identity_Person_BirthDate):
#Html.IdFor(m => Model)
or
#Html.IdForModel()

Resources