how do I get key/value in sightly from java use class hashmap - aem

I have a basic java use class object that extends WCMUSE and a simple hashmap method - in the sightly code - I have something like
${item}
${item.key}
${item.value}
does not work - how do I return key/value pair in sightly code

There is an example at Sightly Intro Part 3 and the use of ${item} and ${itemList} as a variables is documented on the AEM Docs Sightly Page. This page also gives the following example for accessing dynamic values:
<dl data-sly-list.child="${myObj}">
<dt>key: ${child}</dt>
<dd>value: ${myObj[child]}</dd>
</dl>
Here is an example with a simple HashMap.
HTML with Sightly:
<div data-sly-use.myClass="com.test.WcmUseSample" data-sly-unwrap>
<ul data-sly-list.keyName="${myClass.getMyHashMap}">
<li>KEY: ${keyName}, VALUE: ${myClass.getMyHashMap[keyName]}</li>
</ul>
</div>
Java:
package com.test;
import java.util.HashMap;
import java.util.Map;
import com.adobe.cq.sightly.WCMUse;
public class WcmUseSample extends WCMUse {
private Map<String, String> myHashMap;
public void activate() throws Exception {
myHashMap = new HashMap<String, String>();
for (int i = 0; i < 10; ++i) {
myHashMap.put(""+i, "Hello "+i);
}
}
public Map<String,String> getMyHashMap() {
return myHashMap;
}
}

You can also try the following (AEM 6.4) :
Note the data-sly-test.hashMap for emptycheck.
<div data-sly-use.pageController="com.corp.wcms.core.pages.anypage.PageController"
<div data-sly-test.hashMap="${pageController.myHashMap}" data-sly-unwrap>
<ul data-sly-list.keyName="${hashMap}">
<li>KEY: ${keyName}, VALUE: ${hashMap[keyName]}</li>
</ul>
</div>
</div>

Related

ZK MVVM : Passing parameter to another viewmodel using <include>

What I want to do is passing value from page1.zul to page2.zul through <include> and viewModel.
From page1.zul, I have
<include processId="#bind(vm.selectedProcess.id)" src="#load('page2.zul')"></include>
And then it should pass to a viewModel in page2.zul
#Init
public void init(#ExecutionArgParam("processId") String processId){
System.out.println("processInstanceId : " + processId);
}
However, I always get a null value. Any idea how to do this thing ? page2.zul looks something like this :
<div apply="org.zkoss.bind.BindComposer"
viewModel="#id('vm') #bind('com.mrye.viewModel')">
<label value="#load(vm.processId)"></label>
</div>
First of all, make distinguish names for Id's of the VM.
Then zul :
<div apply="org.zkoss.bind.BindComposer"
viewModel="#id('vm') #init('com.mrye.viewModel', processId = parentVM.selectedProcess.id )">
And VM2:
#Init
public void init (#BindingParam("processId") MyObject processID) {
Edit after the comment :
As you can see in this fiddle it works, but your parameter has to be initialized.
If you want to have "live data" passed to other zul (not other viewmodel), you can use #ref or just use parentVM.
If the live data need's to be in the viewmodel itself, you can use a non visible textbox where you load the data from parentVM and save it in the includedVM just before some action happens.
See updated fiddle here.
Here you can check
Index.zul
<?page title="URL Parameters Test" contentType="text/html;charset=UTF-8"?>
<zk>
<window title="URL Parameters Test" border="normal">
<include src="header.zul?test=5" />
</window>
</zk>
In above code you can check it pass argument with URL here test is argument name and value=5
<?page contentType="text/html;charset=UTF-8"?>
<zk>
<window border="none" width="100%" height="100%" apply="pkg$.HeaderComposer">
<label id="lblHeader" />
<div>
Load from EL [ <label value="${param.test}" />]
</div>
</window>
</zk>
In this page we used ${param.test} to get the parameter passed in index.zul , HeaderComposer.java
import org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zk.ui.util.*;
import org.zkoss.zk.ui.ext.*;
import org.zkoss.zk.au.*;
import org.zkoss.zk.au.out.*;
import org.zkoss.zul.*;
public class HeaderComposer extends GenericForwardComposer{
Label lblHeader;
#Override
public void doAfterCompose(Component comp) throws Exception {
try {
super.doAfterCompose(comp);
}
catch (Exception e) {
e.printStackTrace();
}
/*
* retrieve url parameters
*/
String[] parameter = (String[]) param.get("test");
if (parameter != null)
lblHeader.setValue( "Congratulations! Your parameters value is " + parameter[0] );
else
lblHeader.setValue( "No parameters found. URL should be something like http://yourserver/yoursite/main.zul?parameter=param-value" );
}
}
for more way you can check http://zkframeworkhint.blogspot.in/2014/05/zk-include-how-to-pass-and-get.html
Just be sure on VM1 the value vm.selectedProcess.id is correctly initialized and it has a value, in the VM2 add the #AfterCompose lifecycle annotation then on #Init get the value, according to your code this should work on VM2:
Long processId;
#AfterCompose
public void initAfterCompose(#ContextParam(ContextType.VIEW) Component view) {
Selectors.wireComponents(view, this, false);
}
#Init
public void init() {
//get dynamic attribut
processId = (Long) Executions.getCurrent().getAttribute("processId");
}

data-sly-call in sightly not invoking

I was trying the sample example given at [a link]http://docs.adobe.com/docs/en/aem/6-0/develop/sightly/use-api-in-java.html. I have created the component SightlyTest in which the data-sly-call to the template does not work. Below are my files inside component:
extra.html
<template data-sly-template.extra="${# text}"
data-sly-use.extraHelper="${'ExtraHelper' # text=text}">
<p>${extraHelper.reversedText}</p>
</template>
ExtraHelper.java
package apps.AEMProject.components.content.SightlyTest;
import com.adobe.cq.sightly.WCMUse;
public class ExtraHelper extends WCMUse {
private String reversedText;
public String getReversedText() {
return reversedText;
}
#Override
public void activate() throws Exception {
String text = get("text", String.class);
reversedText = new StringBuilder(text).reverse().toString();
System.out.print("reversedText ::: "+reversedText);
}
}
SightlyOp.java
package apps.AEMProject.components.content.SightlyTest;
import com.adobe.cq.sightly.WCMUse;
public class SightlyOp extends WCMUse {
private String lowerCaseTitle;
private String lowerCaseDescription;
#Override
public void activate() throws Exception {
lowerCaseTitle = getProperties().get("title", "").toLowerCase();
lowerCaseDescription = getProperties().get("description", "").toLowerCase();
}
public String getLowerCaseTitle() {
return lowerCaseTitle;
}
public String getLowerCaseDescription() {
return lowerCaseDescription;
}
}
SightlyTest.html
<div data-sly-use.sg="SightlyOp"
data-sly-use.extra="extra.html">
<h1>${sg.lowerCaseTitle}</h1>
<p>${sg.lowerCaseDescription}</p>
<div data-sly-call="${extra # text=properties.description}"></div>
</div>
sg.lowerCaseTitle & sg.lowerCaseDescription is working fine, but nothing display for data-sly-call
Thanks
Try this in SightlyTest.html instead,
<div data-sly-use.sg="SightlyOp" data-sly-use.extra1="extra.html">
<h1>${sg.lowerCaseTitle}</h1>
<p>${sg.lowerCaseDescription}</p>
<div data-sly-call="${extra1.extra # text=properties.description}"></div>
</div>
Modified to data-sly-use.extra1 to differentiate between the variable and the template being called.
I realize I've come to the party a little late, but I'd like to expand on Aditya's answer.
Think of the file extra.html more like a "library" of data-sly-templates rather, since it could contain as many of them as you want (each with a different name). So when you "use" the extra.html file you're sort of importing those templates into a namespace you provide on the use statement. You can then call the templates using that "namespace".
<div data-sly-use.sg="SightlyOp"
data-sly-use.extra="extra.html">
<!--/*${extra} is now a namespace for the templates in extra.html. (you can name it whatever you like for more clarity*/-->
<h1>${sg.lowerCaseTitle}</h1>
<p>${sg.lowerCaseDescription}</p>
<!--/*since your template is called extra, and it's in the namespace called extra you call it with ${extra.extra}*/-->
<div data-sly-call="${extra.extra # text=properties.description}"></div>
</div>

How to solve "Conversion Error setting value '2013-10-26' for 'null Converter'" in h:inputText with Date value?

when I press the insert button, I get the error indicated on the title
Conversion Error setting value '2013-10-26' for 'null Converter'
<h:form id="formulario">
<h:outputLabel for="date">Plazo</h:outputLabel>
<h:inputText id="date" required="true" requiredMessage="Campo Obligatorio" value="#{aaaNewDetalles.criterioAaa.plazo}"/>
<h:message for="date" style="color: red;"/>
<h:commandButton actionListener="#{aaaNewDetalles.add()}" value="Ingresar"/>
</h:form>
the form is managed by this class:
#ManagedBean(name = "aaaNewDetalles")
#ViewScoped
public class aaaNewDetallesBean {
private CriterioAaaController controller;
private CriterioAaa criterioAaa;
#PostConstruct
public void init(){
controller= new CriterioAaaController();
criterioAaa= new CriterioAaa();
}
public void add(){
controller.save(criterioAaa);
}
public CriterioAaa getCriterioAaa() {
return criterioAaa;
}
public void setCriterioAaa(CriterioAaa criterioAaa) {
this.criterioAaa = criterioAaa;
}
}
The object CriterioAaa:
import java.sql.Date;
#Table(name = "criterio_aaa", schema = "", catalog = "ciclos_calidad")
#Entity
public class CriterioAaa extends Entidad implements Serializable {
private Date plazo;
public Date getPlazo() {
return plazo;
}
public void setPlazo(Date plazo) {
this.plazo = plazo;
}
}
There are two problems in your current approach:
You should use java.util.Date instead java.sql.Date. JSF and other frameworks work with this type. Also, java.sql.Date extends java.util.Date but its purpose is basically for JDBC usage. More info about this: Date vs TimeStamp vs calendar?
<h:inputText> expects a String as value, and when sending the data to the managed bean, it also expects the class field is from String type as well. In cases like this, you need to use a converter to tell JSF that this String in fact represents a Date. For this, you may use <f:convertDateTime> tag component.
<h:inputText id="date" required="true" requiredMessage="Campo Obligatorio"
value="#{aaaNewDetalles.criterioAaa.plazo}">
<f:convertDateTime pattern="yyyy-MM-dd" />
</h:inputText>
As a recommendation, you may use a calendar component from third party libraries like PrimeFaces or RichFaces whose provide <p:calendar> and <rich:calendar> component respectively.
You should import the appropriate Date package :
import java.util.Date;
In Managed Bean You should use java.util.Date. and specify the converter.
e.g.
<h:inputText id="date" required="true" requiredMessage="Hire Date"
value="#{empBean.empDetail.hireDate}">
<f:convertDateTime pattern="yyyy-MM-dd" />
</h:inputText>
you can specify the pattern for DateTimeConverter also you can use dateStyle,timeStyle, type.

Output a list to a template in lift

How can I output a list of things in a template in Lift?
Let say for example that I have List[User] and I want to output it as a table. In Django, I would use a context variable "users" and iterate through it in the template like so:
//controller
user = User.objects.all()
context = {'users' : users}
return render_to_template('results.html', context}
//view
<table>
{% for user in users %}
<tr><td>{{user.name}}</td>
<td>{{user.email}}</td>
</tr>
{% endfor %}
</table>
I appreciate any help.
PS: Could you also show me an example of the scala side - as I am clueless about how to approach this problem.
Template
<ul>
<lift:UserSnippet.showAll>
<li><foo:userName />: <foo:age /></li>
</lift:UserSnippet.showAll>
</ul>
Snippet Class
I'm assuming users is a List[User].
import scala.xml.NodeSeq
import net.liftweb.util.Helpers
class UserSnippet {
def showAll(in: NodeSeq): NodeSeq = {
users.flatMap { user => Helpers.bind("foo", in, "userName" -> user.name, "age" -> user.age) }
}
}
See the lift wiki articles on designer friendly templates and snippets for more information.
if you're looking to use a pure java list, say an ArrayList from a seperate java call...you can do it this way....
Make sure to import the java conversions, and your java class file where your list is being created
(i'm assuming we have a list of "people" objects that is being returned from your java file, which would include a name, age, and sex properties)
//SCALA Code
import scala.collection.JavaConversions._
import my.java.package.something._
import scala.xml.NodeSeq
import net.liftweb.util.Helpers
class mySnippet {
//You want to run the ".toList" on your java list, this will convert it into a scala list
val myScalaList = my.java.package.something.buildMyList().toList
//This is the function that will bind the list to the html view
def displayPeople(html : NodeSeq) : NodeSeq = {
myScalaList.flatMap{person => bind("info", html,
"name", person.name,
"age", person.age,
"sex", person.sex)}
}
}
//HTML code
<table>
<tr>
<td>Name</td>
<td>Age</td>
<td>Sex</td>
</tr>
<lift:mySnippet.displayPeople>
<tr>
<td><info:name></info:name></td>
<td><info:age></info:age></td>
<td><info:sex></info:sex></td>
</tr>
</lift:mySnippet.displayPeople>
</table>
Hope this helps :)
-kevin

What's the Struts 2 equivalent of ASP.NET's Request.Form (or FormCollection)?

I'm dynamically adding textboxes to a form on my jsp page using Javascript. When that form is submitted to an action, how does my action get the values of those textboxes? (I'm using Struts 2, btw.) In ASP.NET, I was able to find them in Form.Request/FormCollection. Is there a Struts 2 equivalent? Thanks a million.
In Struts2, you create beans in the form to do submit values. In order to create the input text-box, use the <s> tag. For example :
<s:textfield name="loginBean.userName" label="UserName" required="true" />
Here loginBean is the bean passed to the jsp page when.
Bean consists of variable declarations and getters-setters for the variable.
Then in the back-end Java where the form is submitted to, you can access the same bean.
Declare getter-setter in Java and then you can access the properties of the bean.
public LoginBean getLoginBean() {
return loginBean;
}
public void setLoginBean(LoginBean loginBean) {
this.loginBean = loginBean;
}
public String authenticate() {
String username = loginBean.getUserName();
I would recommend looking at source codes of open-source Struts projects.
It sounds like you're trying to populate a dynamic list. To do that, you just have to use the [n] index syntax at the end of your Action class property name:
HTML:
<input type="text" name="yourCollection[0]" value="first value" />
<input type="text" name="yourCollection[1]" value="second value" />
<input type="text" name="yourCollection[2]" value="third value" />
Action Class:
public class YourAction extends Action {
public List<String> yourCollection;
public List<String> getYourCollection(){
return yourCollection;
}
public void setYourCollection(List<String> aCollection){
this.yourCollection = aCollection;
}
}