how to read an entry in a hashmap from SSJS? - xpages

I have in a viewScope a hashmap stored but how can I read an entry from it e.g. from a computed text in SSJS ?
var pm = viewScope.get("person");
var entry = pm.entrySet();
return entry.getValue("email")

entrySet() is a way for you to iterate your Map. For example:
Map<String, String> m = new HashMap<String, String>();
m.put("one", "1");
m.put("two", "2");
for (Map.Entry<String, String> entry : m.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
will print:
one=1
two=2
If you want to read a specific key from a map it's actually very simple:
<xp:text value="#{viewScope.person.email}" />
or if you need dynamic (where you would replace the literal value expressed with the quotes with another dynamic variable of your choosing):
<xp:text value="#{viewScope.person['email']}" />

Related

xpages managed bean property of an array returns the reference instead of the values

must be a rookies problem:
in a managed bean i want to put values of a multivalue notes item into a bean variable:
my snippet goes like:
private String[] typevalues;
public void setTypevalues(String[] typevalues) {
this.typevalues = typevalues;
}
public String[] getTypevalues() {
return typevalues;
}
and in the loadPreferences function I do sth like:
Vector <String> vt = profdoc.getItemValue("ideetypes");
typevalues = vt.toArray(new String[vt.size()]);
(didn't find a better way to bring a getItemValue vector into an Array)
on the xpage my test item:
<xp:text escape="true" id="computedField1"
value="#{APr.typevalues}">
</xp:text>
doesn't show the values of that String array, but it's reference like [Ljava.lang.String;#74987498
Am I missing sth, or is a String[] Array the wrong container for such a bean property?
thanks in advance, Uwe
I like using ArrayList and not Arrays. Then you can use the following to convert from a Vector to the ArrayList.
Collections.list( rtnVector.elements())
Howard

How do I pass objects from the request map into a method expression after rendering a component?

I'm writing a custom datatable component, and I'm trying to allow other developers to use the var of the current iteration to be passed to a method expression.
Here's an example:
<my:dataTable value="#{contactController.viewEntities}" var="contact">
<p:column headerText="Whatever">
<p:commandButton value="Edit"
ajax="false"
actionListener="#{contactController.setSelectedContact(contact)}"
action="contact"/>
</p:column>
</my:dataTable>
As you can see, I'm trying to pass the "contact" var into a setter method for later use. That var is stored in the request map during rendering, like so:
...
Map<String, Object> requestMap = context.getExternalContext()
.getRequestMap();
for (Object obj : collection) {
requestMap.put(table.getVar(), obj);
for (UIColumn column : columns) {
column.encodeAll(context);
}
requestMap.remove(table.getVar());
}
...
However, when I run the project, the only value passed to the controller is null.
The question becomes, how do I make that object available for each row to use in expression language? I've looked at PrimeFaces'/ICEFaces' datatables, but I don't see how they differ from mine
Thanks in advance!
So, I finally solved this issue! When extending UIData, the method setRowIndex(index) becomes available. By setting this value, the clientId of each row's component will be prepended with the index number, thus making them unique per row. The trick was to set this value while iterating over the underlying collection. Expression language can now evaluate the var parameters.
int index = 0;
Map<String, Object> requestMap = context.getExternalContext()
.getRequestMap();
for (Object obj : collection) {
requestMap.put(table.getVar(), obj);
table.setRowIndex(index);
for (UIColumn column : columns) {
column.encodeAll(context);
}
requestMap.remove(table.getVar());
index ++;
}

How to prevent duplicates of SelectItem in Set collection

I am trying to add SelectItem objects to Set collection. However, duplicate values are being added. Is there any way to prevent these duplicate values?
for(String s: list) {
Set<SelectItem> typeSet = new HashSet<SelectItem>();
typeSet.add(new SelectItem(s));
}
Just use Set<String> instead of Set<SelectItem>. The SelectItem#equals()/#hashCode() isn't implemented at all to take the actual value into account.
private Set<String> typeSet;
#PostConstruct
public void init() {
List<String> list = getItSomehow();
typeSet = new LinkedHashSet<String>(list);
}
It's since JSF2 just usable on <f:selectItems> as well.
<f:selectItems value="#{bean.typeSet}" />
See also:
Our selectOneMenu wiki page

JSF-2 f:selectItems with Map does not display itemLabel

When I use f:selectItems to display items in a Map I cannot display the value of the Map item, only the key. f:selectItems does not use the itemLabel at all. When I use a List instead things work.
The following does make use of the itemLabel to display the "description" of an item in a List:
<h:selectOneMenu>
<f:selectItems value="#{testBB.testList}" var="s"
itemLabel="TEST #{s.description}" itemValue="#{TEST s.name}" />
</h:
selectOneMenu>
The following attempt to display the value of an item in a Map does not work. It displays the item's key, but not using the itemLabel attribute, as can be discerned by that lack of output of the "TEST" text.
<rich:select>
<f:selectItems value="#{testBB.testMap}" var="s"
itemLabel="TEST #{s.value}" itemValue="TEST #{s.key}" />
</rich:select>
The simple backing bean used follows:
public class TestBB {
private Map<String, String> testMap;
private List<TestItem> testList;
public TestBB() {
testMap = new HashMap<String, String>();
testMap.put("1_key", "Item One");
testMap.put("2_key", "Item Two");
testMap.put("3_key", "Item Three");
testList = new ArrayList<TestItem>();
testList.add( new TestItem("name_1", "description_1") );
testList.add( new TestItem("name_2", "description_2") );
testList.add( new TestItem("name_3", "description_3") );
}
public Map<String, String> getTestMap() {
return testMap;
}
public List<TestItem> getTestList() {
return testList;
}
}
So, any ideas on how to make this work, that is, how to effectively use a Map with selectItems?
Your question is sound, but the code makes it confusing and ambiguous. I'll just ignore your code in this answer.
As to the concrete question "How to use Map in <f:selectItems>", you need to realize that map keys are by default been used as item labels and that map values are by default been used as item values. You seem to expect it to be the other way round (honestly, I'd intuitively also expect that, but that was just a design desicion --the map key forces uniqueness and option labels should in UI perspective definitely be unique, but option values does not necessarily need to be unique).
So, this should do (note that I use LinkedHashMap here as it maintains the insertion order):
map = new LinkedHashMap<String, String>();
map.put("Label 1", "value1");
map.put("Label 2", "value2");
map.put("Label 3", "value3");
with
<f:selectItems value="#{bean.map}" />
If you want so swap the keys and values, then you should be iterating over Map#entrySet(). This works only when your environment supports EL 2.2 as you have to invoke it by a direct method invocation as there's no getter for that.
E.g.
map = new LinkedHashMap<String, String>();
map.put("value1", "Label 1");
map.put("value2", "Label 2");
map.put("value3", "Label 3");
with
<f:selectItems value="#{bean.map.entrySet()}" var="entry"
itemValue="#{entry.key}" itemLabel="#{entry.value}" />
See also:
Our selectOneMenu wiki page

How to make javax.faces.model.SelectItem selected

I'm creating a List of javax.faces.model.SelectItem (in a bean) for use with a h:selectManyCheckbox but I cannot figure out how to make a SelectItem selected.
How to do this? Must be possible, right?...
public List<SelectItem> getPlayerList(String teamName) {
List<SelectItem> list = new ArrayList<SelectItem>();
TeamPage team = (TeamPage) pm.findByName(teamName);
List<PlayerPage> players = pm.findAllPlayerPages();
for (PlayerPage player : players) {
boolean isMember = false;
if (team.getPlayerPages().contains(player)) {
isMember = true;
}
SelectItem item;
if (isMember) {
// TODO: Make SelectItem selected???
item = null;
} else {
item = new SelectItem(player.getId(), createListItemLabel(player), "", false, false);
}
list.add(item);
}
return list;
}
Assume we have this JSF code:
<h:selectManyCheckbox value="#{bean.selectedValues}">
<f:selectItems value="#{bean.playerList}"/>
</h:selectManyCheckbox>
then the selected values (i.e. the checked checkboxes) are stored in the bean.selectedValues property.
Thus, in your Java code, you must handle the selectValues by putting the correct ID in the selectedValues property.
If anybody is working with selectOneMenu and populating elements dynamically:
While creating a SelectItem, if you provide some value(first parameter) as follows:
new SelectItem("somevalue", "someLabel", "someDescription", false, false);
It translates to this in the html:
<option value="somevalue">someLabel</option>
If you do not provide a value as follows:
new SelectItem("", "someLabel", "someDescription", false, false);
, it translates to this
<option value="" selected="selected">someLabel</option>
Hence if you want an element to be the default on page load(like "Select one of these"), do not provide a value. If you create more than one element without a value, any one of them are chosen for default on page load(probably preference based on ascending alphabetical order).

Resources