XPages inputTextArea is not editable - xpages

When i use multiLine editbox (shown in FIRST ONE) It cannot be editable If the document is in editMode.
But SECOND ONE is editable. My point is if use formula at the value of inputTextArea It can not be editable.
I could not find what it is that i missed?
FIRST ONE:
<xp:inputTextarea id="muvName" rows="2" cols="70"><xp:this.value><![CDATA[#{javascript:#Implode(document1.getItemValue("muvName"))+ #NewLine() + "C/o";}]]></xp:this.value></xp:inputTextarea>
SECOND ONE:
<xp:inputTextarea id="muvName" rows="2" cols="70" value="#{document1.muvName}">
</xp:inputTextarea>

Use the property defaultValue to define a default value:
<xp:inputTextarea
id="muvName"
rows="2"
cols="70"
value="#{document1.muvName}">
<xp:this.defaultValue><![CDATA[#{javascript:
#Implode(document1.muvName)+ #NewLine() + "C/o"
}]]></xp:this.defaultValue>
</xp:inputTextarea>
and use property value for binding a document's item (or a scope variable) to the editable field. value has to be an object to which XPage can write the submitted content to.
In your first example you calculate a string and it's impossible to write something back to a calculated string. That's why the field is read only.
Update:
If you want to correct document field's value before editing then use a custom converter instead:
<xp:inputTextarea
id="muvName"
rows="10"
cols="70"
value="#{document1.muvName}">
<xp:this.converter>
<xp:customConverter
getAsObject="#{javascript:value}">
<xp:this.getAsString><![CDATA[#{javascript:
if (!value.endsWith("C/o")) {
value += #NewLine() + "C/o";
}
value
}]]></xp:this.getAsString>
</xp:customConverter>
</xp:this.converter>
</xp:inputTextarea>

Related

Xpages: Validation using java bean with multiple instances of a custom control

I have a custom control for an editable field, and validation is done via a java bean. I want to set the isValid() property to set bootstrap styling like so:
However, this does not work if I place the cc on a page more than once, because I am searching on the component's ID to set the Valid property.
I need to either compute the id of the field in the CC, or do something else like this post describes.
I believe I can compute the ID of the text field like so:
<xp:inputText
id="${javascript:compositeData.fieldName}"
type="text"
loaded="${!empty compositeData.placeholder}"
required="${compositeData.required}"
disableClientSideValidation="true">
<xp:this.attrs>
<xp:attr
name="placeholder"
value="${compositeData.placeholder}" />
</xp:this.attrs>
<xp:this.binding><![CDATA[#{javascript:compositeData.dataSource[compositeData.fieldName]}]]></xp:this.binding>
</xp:inputText>
However, there are a few places where I need to compute the component, such as
<xp:this.styleClass><![CDATA[#{javascript:"form-group" + (getComponent("inputText1").isValid() ? "" : " has-error" )}]]></xp:this.styleClass>
I have to replace the "inputText1" with the computed ID, but cannot figure out how to do so.
Is there a better/easier way?
Why would you not use the compositeData.fieldName everywhere you reference the id?
<xp:this.styleClass><![CDATA[#{javascript:"form-group" + (getComponent(compositeData.fieldName).isValid() ? "" : " has-error" )}]]></xp:this.styleClass>

Xpages Extlib dataView control sets "display:none;" style when column has empty value

I have a xpage with Extension Library DataView control. I have defined several extra columns there.
<xe:dataView id="dataView1"
<xe:this.data>
<xp:dominoView var="vMyView" />
</xe:this.data>
<xe:this.summaryColumn>
<xe:viewSummaryColumn columnName="$DateFrom"
columnTitle="Date From">
</xe:viewSummaryColumn>
</xe:this.summaryColumn>
<xe:this.extraColumns>
<xe:viewExtraColumn columnName="$DateTo"
styleClass="hidden-xs" headerStyleClass="hidden-xs" columnTitle="Date To"
style="hidden-xs">
</xe:viewExtraColumn>
<xe:viewExtraColumn columnName="$Information"
columnTitle="Information">
</xe:viewExtraColumn>
</xe:this.extraColumns>
</xe:dataView>
My view data source contains same cells where information is empty. Those cells are rendered with style="display:none;".
How can I avoid this attribute and display those empty cells? I'd like not to change my view to fill empty cells with i.e. "-" char
An empty column value gets rendered with style="display:none;":
You can avoid this if you add a custom converter to your column definition and replace an empty value by a space:
<xe:viewExtraColumn columnName="$Information"
columnTitle="Information">
<xe:this.converter>
<xp:customConverter>
<xp:this.getAsString><![CDATA[#{javascript:value == "" ? " " : value}]]></xp:this.getAsString>
<xp:this.getAsObject><![CDATA[#{javascript:value}]]></xp:this.getAsObject>
</xp:customConverter>
</xe:this.converter>
</xe:viewExtraColumn>
It gets rendered to a "normal" grid cell without display:none then:
The code for getAsObject doesn't matter as long as the cell is not editable. So it's OK to just leave the value as it is.
Instead of using a converter to "fake" some content, you could also adjust the css. Just implement
.lotusTable TD {
display: inline !important;
}
in a style sheet resource used in your custom control(s).
So you also won't have to apply a converter to every potentially empty column.

xpages hiding/showing fields based on a combobox value

I'm using a <xe:djTabContainer> with 10 <xe:djTabPane> containing numerous fields components.
There is a principal combobox whose value will determine which fields to be showed or not and in this way the document structure will be achieved.
If I will use this approach, then for all my >50 fields which I want to show/hide, I will use only the onChange event of the combobox?
Considering the fact that there are >50 fields which enter in this category < showing&hiding them >, should I use another approach / method? Thanks for your time.
<xp:comboBox value="#{Contr.txt_tipcontractcv}" id="comboBox4"> <xp:selectItems id="selectItems1">
<xp:this.value><![CDATA[#{javascript:return ""}]]></xp:this.value>
</xp:selectItems>
<xp:selectItems id="selectItems2">
<xp:this.value><![CDATA[#{javascript:#DbColumn(#DbName(),"SetupvwTipuriContracteC",1);}]]> </xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="false"> <xp:this.script><![CDATA[XSP.partialRefreshPost("#{id:FisaP}", {
});
]]></xp:this.script> </xp:eventHandler> </xp:comboBox>
and the panel:
<xp:panel id="FisaP">
<xp:label id="label4"
style="color:rgb(128,0,0);font-family:verdana;font-size:9pt;font-weight:bold">
<xp:this.value><![CDATA[#{javascript:"Fisa contract "+ Contr.getItemValueString("txt_tipcontractcv")}]]></xp:this.value>
<xp:this.rendered><![CDATA[#{javascript:
Contr.getItemValueString("txt_tipcontractcv") != ""
}]]></xp:this.rendered>
</xp:label>
</xp:panel>
I would turn it around. Let the labels and fields ask the combobox if they should be rendered or not. Let the combobox's onchange event initiate a partial refresh of a panel which includes all fields you want to show/hide.
If your >50 fields are all on one place you can frame them with a panel and set the rendered property there.
If your combobox is bound to a viewScope variable the rendered property of fields/labels would be
rendered="#{javascript:viewScope.tipcontractcv1 == 'Vanzare-Cumparare'}"
or if it is bound to a document field then
rendered="#{javascript:document1.getItemValueString('txt_tipcontractcv1') === 'Vanzare-Cumparare'}"
Update:
Based on your code in your answer https://stackoverflow.com/a/25636661/2065611 take the following steps so get it to work with the Dojo Tab Container:
1.
Put the labels and fields in panels which do have an id but don't have a rendered attribute
<xp:panel id="panel1">
<xp:label value="Persoane spre informare" ... id="label2">
<xp:this.rendered><![CDATA[#{javascript:
Contr.getItemValueString("txt_tipcontractcv1") == "Vanzare-Cumparare"
}]]></xp:this.rendered>
</xp:label>
... other label and fields ...
</xp:panel>
You can create other panels "panel2", "panel3", ... too. They can be placed in different djTabPanes.
2.
Change the onchange event of your combobox and execute client side code to refresh the panels
<xp:eventHandler
event="onchange"
submit="false">
<xp:this.script><![CDATA[
XSP.partialRefreshPost("#{id:panel1}", {
onComplete: function() {
XSP.partialRefreshPost("#{id:panel2}");
}
});
]]></xp:this.script>
</xp:eventHandler>
3.
You can optimize your code if you put labels and fields with the same rendered attribute together into an additional panel
<xp:panel id="panel1">
<xp:panel id="panelRendered1"
<xp:this.rendered><![CDATA[#{javascript:
Contr.getItemValueString("txt_tipcontractcv1") == "Vanzare-Cumparare"
}]]></xp:this.rendered>
<xp:label value="Persoane spre informare" ... id="label2" />
... other label and fields ...
</xp:panel>
</xp:panel>
First... never do this:
if (comboVal == "Vanzare-Cumparare")
Even though it's called "SSJS".. it's really not "JavaScript"... you're pretty much working with Java. In Java everything is an object. Even a literal string. So by entering "Vanzare-Cumparare" you're pretty much creating a new Object. You can see this in the typeahead of the SSJS editor. Try typing "anything". <-- Note you NEED to type in that period.
The way to do that if statement is:
if ("Vanzare-Cumparare".equalsIgnoreCase(comboVal)
you could reverse it I think:
if (comboVal.equalsIgnoreCase("Vanzare-Cumparare")
Should give you the same result. I think sometimes you can get away with using the == but mostly likely it's going to bite you at some point no matter what. So I recommend never doing that.
I'm not sure I'm following your approach here. I guess it makes some sense but if it were me I'd do it differently. I know that personally I've NEVER tried to grab the component in SSJS like this: var combo:javax.faces.component.UIComponent - I've never seen the need.
I'd prefer to use a scoped variable and then in the label's rendering property grab that scoped variable and use that to determine your rendering value - true or false.
I see a real problem. If the component is not currently rendered, you cannot get a handle to it with getComponent. If you simply change the display value, then the component is always there, even if it's not displayed.
Something like this:
var combo:javax.faces.component.UIComponent = getComponent("txt_tipcontractcv1");
var comboVal = combo.getValue();
if (comboVal.equalsIgnoreCase("Vanzare-Cumparare")) {
document.getElementById("#{id:label2}").style.display = "block"; // or "inline"
} else {
document.getElementById("#{id:label2}").style.display = "none";
}
You need to ensure that the label2 element is always rendered, so that the style indicates whether it is visible.

Xpages datatable cell colour based on cell value

I am trying to use an xpages datatable and set the cell colour of the cells in a column to be different based on the cell value. What I am finding is that although the datatable is bound to a view and the collection is specified (to get the row value) this seems to not be available to the style section.
Here is an example:
<xp:dataTable id="dataTable8" rows="30" var="doc1">
<xp:this.value><![CDATA[#{javascript:var View:NotesView = DivisionsView;
View.getAllEntriesByKey("ViewName")}]]></xp:this.value>
<xp:column id="column1" style="width:75px;font-family:Tahoma">
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:doc1.getColumnValues()[1]
}]]></xp:this.value>
<xp:this.style><![CDATA[#{javascript:v=doc1.getColumnValues()[1];
if(v=="Yes"){"background-color:rgb(255,0,0)"}}]]></xp:this.style>
</xp:text>
<xp:this.facets>
<xp:label value="Header" id="label1" xp:key="header">
</xp:label>
</xp:this.facets>
</xp:column>
</xp:dataTable>
This just shows a doc1 not found error. Does this mean the data bound to the datatable is not available to the style part of it? Is there a way to do this?
Any suggestions would be appreciated!
Edit: I cannot change the table cell style based on the view entries value, here is an exmaple that throws the doc1 not found error:
<xp:column id="column1">
<xp:this.style><![CDATA[#{javascript:v=doc1.getColumnValues()[1];
if(v=="Yes"){"background-color:rgb(255,0,0)"}}]]></xp:this.style>
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:doc1.getColumnValues()[1]
}]]></xp:this.value>
</xp:text>
<xp:this.facets>
<xp:label value="Header" id="label1" xp:key="header">
</xp:label>
</xp:this.facets>
</xp:column>
The stylesheet property is rendered not only for every value in the column, it is calulated for each row. This incudes the facet too.
This means if your column has a header and/or a footer, the stylesheet property is calculated for these invisible rows, but there is no row value (doc1).
If you change your code and add a try/catch you can see the result.
<xp:column id="column1">
<xp:this.style>
<![CDATA[#{javascript:
try{
v=doc.getColumnValues()[1];
if(v=="Yes"){"background-color:rgb(255,0,0)"}
}catch(e){
return "background-color:rgb(255,0,255)";
}}]]>
</xp:this.style>
...
...
</xp:column>
There are a few things I would like you to check in your code.
First the code to bind data:
var View:NotesView = DivisionsView;
View.getAllEntriesByKey("ViewName")
What is DivisionsView? The actual code to bind would look something like this:
var View:NotesView = database.getView("ViewName");
View.getAllEntriesByKey("KeyName")
Second, in your code to add style you have used single = rather than == in if condition. So the code would be something like this:
v = doc1.getColumnValues()[1];
if (v=="Yes") {
"background-color:rgb(255,0,0)"
}
Do these suggestions make it work?
I have given up on a datatable and got things to work using a repeat on a table row. That way I can control the style of the entire row and therefore each cell, it appears you cannot do this in a datatable as the options are all data column based. Thanks for your help though

How to retrieve and show list of values in listbox and text corresponding to list item in textarea

I need to use a list box to show some values from database and do further processing when a single value from the list is selected.
At the PrimeFaces showcase site the example loads fixed (static) data into the listbox and there is one PrimeFaces command for each list item. How do I show items in a list box dynamically, when I may not know the number of items beforehand?
I also need to show some text corresponding to the item selected in list, in a textarea. Do I have to use an event listener for this purpose? I would like to leave the text area blank at the beginning. Only when a value is selected in the list box, then I want to use a bean to retrieve and store data using that textarea. Is this possible? How do I implement this?
How do I show items in a list box dynamically, when I may not know the number of items beforehand?
Use <f:selectItems> which you bind to a List<T> property. Basic example, assuming you're using EJB/JPA to interact with DB:
private Item selectedItem; // +getter+setter
private List<Item> availableItems; // +getter
#EJB
private ItemService service;
#PostConstruct
public void init() {
availableItems = service.list();
}
with
<p:selectOneListbox value="#{bean.selectedItem}" converter="itemConverter">
<f:selectItems value="#{bean.availableItems}" var="item"
itemValue="#{item}" itemLabel="#{item.someLabel}" />
</p:selectOneListbox>
The itemConverter should implement javax.faces.convert.Converter and convert from the Item object to its unique string representation (usually its DB identifier) in getAsString() and convert the other way round getAsObject().
I also need to show some text corresponding to the item selected in list, in a textarea. Do I have to use an event listener for this purpose?
Just put a <p:ajax> (the PrimeFaces equivalent of standard JSF <f:ajax>) in the listbox which updates the textarea. E.g.
<p:selectOneListbox value="#{bean.selectedItem}" converter="itemConverter">
<f:selectItems value="#{bean.availableItems}" var="item"
itemValue="#{item}" itemLabel="#{item.someLabel}" />
<p:ajax update="textarea" />
</p:selectOneListbox>
<p:inputTextarea id="textarea" value="#{bean.selectedItem.someText}" />
It'll be invoked when you select an item.
See also:
Our h:selectOneMenu wiki page - same applies to PrimeFaces p:selectOneListbox
Yes, for demonstration purposes most of the examples are loaded with static data. But if you look at the same example on PF showcase, the second listbox code is as follows:
<h:outputText value="Scrollbar: " />
<p:selectOneListbox id="scroll" value="#{autoCompleteBean.selectedPlayer1}"
converter="player" style="height:100px">
<f:selectItems value="#{autoCompleteBean.players}"
var="player" itemLabel="#{player.name}" itemValue="#{player}" />
</p:selectOneListbox>
and f:selectItems value attribute can point to a collection, an array, a map or a SelectItem instance. So coming to the above example players could be any list that is being populated using a database in the managed bean.
But if the instance is not a SelectItem, the labels are obtained by calling a toString on each object and finally the selected itemValue is set to the selectedPlayer1 attribute but you can also see that there is a converter in between so the incoming itemValue string is converted back to a player object and then set to selectedPlayer1.
And if you want to display the selected item in a text area, you can do something like this:
<h:outputText value="Scrollbar: " />
<p:selectOneListbox id="scroll" value="#{autoCompleteBean.selectedPlayer1}"
converter="player" style="height:100px">
<f:selectItems value="#{autoCompleteBean.players}"
var="player" itemLabel="#{player.name}" itemValue="#{player}" />
<p:ajax update="displayArea"/>
</p:selectOneListbox>
<p:inputTextarea id="displayArea" value="#{autoCompleteBean.selectedPlayer1}" />
Here the inputTextarea is updated using ajax with the value selected by the user.

Resources