Xpages, Compute combo box value - xpages

I have a combo box its values are 10, 20, 30, 40, 50 when I create a document and display it in a view the number is appeared but I want to display its labels (labels are text) not numbers.
Can someone please help me find out how to solve this issue.
Thanks

I tend to add values of a given checkbox into a Resource Bundle, and then access that Resource Bundle both from the xp:selectItems and the xp:viewColumn values.
First, I'll create a Resource Bundle which I set as "label", with the following values:
itemsList_status=Draft|0,Published|1,Archived|-1
itemsList_delimiter=,
Here's an example of the xp:selectItems for an xp:combobox:
<xp:selectItems>
<xp:this.value>
<![CDATA[#{javascript:return getSelectItems('status');}]
</xp:this.value>
</xp:selectItems>
Here's my getSelectItems() SSJS function:
var getSelectItems : function(key) {
try {
var returnObj = new Array();
var items = null;
switch(key) {
case "status" :
items = #Text(label.itemsList_status).split(label.itemsList_delimiter);
break
}
for( var n=0, l=items.length; n < l; n++) {
returnObj.push(items[n]);
}
return returnObj;
} catch(e) {
print(database.getTitle() + " SSJS Error for getSelectItems()");
print(e.toString());
}
}
Run this function, and it'll return 3 options that read Draft, Published, and Archived while actually storing 0, 1, and -1 respectively. The problem that you're running into - and what using this abstracted method of storing your labels:values in a Resource Bundle + SSJS to address - is when you go to read the value but actually want to display the label...
Here's my getSelectedValue() function:
var getSelectedValue : function(key, thisValue) {
try {
var returnObj = new Array();
var items = null;
switch(key) {
case "status" :
items = #Text(label.itemsList_status).split(label.itemsList_delimiter);
break
}
var s = "";
var l = "";
for( var n=0, i=items.length; n < i; n++) {
if(items[n].indexOf("|") == -1) {
s = items[n];
l = items[n];
} else {
s = items[n].split("|").pop();
l = items[n].split("|").shift();
}
if(thisValue == s) {
return l;
}
}
return thisValue;
} catch(e) {
print(database.getTitle() + " SSJS Error for getSelectedValue()");
print(e.toString());
}
}
Now you'd pass the current value and the desired label:value Resource Bundle item handle, and this function spits out the correlating label. Here is how I use it in an xp:viewColumn:
<xp:viewColumn
id="viewColumn_status">
<xp:this.value><![CDATA[#{javascript:return ""}]]></xp:this.value>
<xp:text
value="#{javascript: return
getSelectedValue('status',thisEntry.getDocument().getItemValueString('status'))}" />
<xp:viewColumnHeader
value="#{label.viewColumnHeader_posts_status}"
id="viewColumnHeader_status">
</xp:viewColumnHeader>
</xp:viewColumn>
... and that's about it - the Resource Bundle entry to "itemList_status" acts as the authoritative master for the label:value pairs, so you just check that for the input building and deconstruct it for the labeling of stored values.
Hope this helps!

Using aliases is analog to the usage in a normal form.
Use a formula item for the values:
return ["- Please select -|", "ten|10", "twenty|20", "thirty|30"];
But keep in mind that the values that is stored is always TEXT and not a number.

Related

Auto populate item amount in custom field

How to auto-populate item amount in custom field on cash sales.
I am new to client script and here is the snippet which i have tried but it doesn't function as expected.Please suggest.
function custItemAmount(type)
{
if(type == 'edit')
{
var record = nlapiLoadRecord(nlapiGetRecordType(), nlapiGetRecordId());
var itemCount = record.getLineItemCount('item');
for(i=1; i<=itemCount; i++)
{
//fetch amount of each item
var item_amount=record.getLineItemValue('item', 'amount', i);
if (item_amount != null && item_amount != '') {
record.setLineItemValue('item', 'custbody_itemamount', i, item_amount);
//set total amount to custom item amount field
}
}
var id = nlapiSubmitRecord(record, true);
}
}
It looks like you're trying to set the wrong field for the line item. Is custbody_itemamount really the field you want? Seems like a body field to me, not a line item field. I'd expect it be called custcol_lineitemamount
Try the following instead, though check to make sure the field names are correct, since I've made some assumptions.
{
if(type == 'edit')
{
var record = nlapiLoadRecord(nlapiGetRecordType(), nlapiGetRecordId());
var itemCount = record.getLineItemCount('item');
for(i=1;i<=itemCount;i++)
{
//fetch amount of each item
var item_amount=record.getLineItemValue('item', 'amount', i);
if (item_amount != null && item_amount != '') {
record.setLineItemValue('item', 'custcol_itemamount', i, item_amount);
//set total amount to custom item amount field
}
}
var id = nlapiSubmitRecord(record, true);
}
When do you want to see the custom column populated? Is it after the User has added the line? If yes, then you script is incorrect. The script you shared looks to be a User Event script. These types of script only execute when you either load or save a record.
Resolved with below simple script..Thanks for your help.
==
function custItemAmount(type)
{
if(type == 'item'){
var item_amount=parseFloat(nlapiGetLineItemValue('item','amount'));
//nlapiSetFieldValue('custcol_item_amount',item_amount);
nlapiSetCurrentLineItemValue('item','custcol_item_amount',nlapiFormatCurrency(item_amount));
}
return true;
}

Sub Grid Total In Crm

I have a primary Entity (Self-Insurance) and a secondary entity (Compensation). They have a 1:N relationship. So in my main form of Self Insurance I have a sub-grid with the name 'Worker_Compensation' where i am adding up some payroll values.
I have 2 questions. . .
1: The thing I want is that when I add some values in the sub-grid. I need to show a sum of all payrolls in the text below of my main form named as 'TOTAL'.
2: Where should i call this java script(On which event) Onload or Onsave of form ? or else where because I can seems to locate the events on Subgrid.
I am using a java script for this purpose.
enter code here
function setupGridRefresh() {
var targetgrid = document.getElementById("Worker_Compensation");
// If already loaded
if (targetgrid.readyState == 'complete') {
targetgrid.attachEvent("onrefresh", subGridOnload);
}
else {
targetgrid.onreadystatechange = function applyRefreshEvent() {
var targetgrid = document.getElementById("Worker_Compensation");
if (targetgrid.readyState == 'complete') {
targetgrid.attachEvent("onrefresh", subGridOnload);
}
}
}
subGridOnload();
}
function subGridOnload() {
//debugger;
var grid = Xrm.Page.ui.controls.get('Worker_Compensation')._control;
var sum = 0.00;
if (grid.get_innerControl() == null) {
setTimeout(subGridOnload, 1000);
return;
}
else if (grid.get_innerControl()._element.innerText.search("Loading") != -1) {
setTimeout(subGridOnload, 1000);
return;
}
var ids = grid.get_innerControl().get_allRecordIds();
var cellValue;
for (i = 0; i < ids.length; i++) {
if (grid.get_innerControl().getCellValue('new_estannualpayroll', ids[i]) != "") {
cellValue = grid.get_innerControl().getCellValue('new_estannualpayroll', ids[i]);
cellValue = cellValue.substring(2);
cellValue = parseFloat(cellValue);
sum = sum + cellValue;
}
}
var currentSum = Xrm.Page.getAttribute('new_payrolltotal').getValue();
if (sum > 0 || (currentSum != sum && currentSum != null)) {
Xrm.Page.getAttribute('new_payrolltotal').setValue(sum);
}
}
This piece of code is not working. after i add values in the grid my textbox remains empty!
Thanks in advance
If you are upgrading to Microsoft CRM 2015 soon or are already on Microsoft CRM 2015, you can do this without any JavaScript by simply creating a new calculated rollup field and placing that underneath the sub grid, or wherever you wish to place it on the form. Note that this field is calculated ever 12 hours, but if you wish to, it could be calculated on form load via JavaScript. You can see details about that at https://msdn.microsoft.com/en-us/library/dn817863.aspx -"Calculated and Rollup Attributes". The TechNet document, "Define rollup fields" at https://technet.microsoft.com/library/dn832162.aspx has some good examples, scenarios, and discussion about the limitations of the rollup fields.
You can do it with subgrid's onRefresh. This is also unsupportted way but it works. You must add this functions to your javascript
function AddEventToGridRefresh(gridName, functionToCall) {
// retrieve the subgrid
var grid = document.getElementById(gridName);
// if the subgrid still not available we try again after 1 second
if (grid == null) {
setTimeout(function () {AddEventToGridRefresh(gridName, functionToCall);}, 1000);
return;
}
// add the function to the onRefresh event
grid.control.add_onRefresh(functionToCall);
}
// function used in this example
function AdviseUser() {
alert("Sub-Grid refreshed");
}
For more information, here is the link

Getting ViewPanel Headers programmatically

This code does provide me the values I am wanting in my comboBox, but I am wondering if there is a way to get the viewColumn ID, viewColumnHeader ID, and number of columns in the viewPanel programmatically. The viewPanel is using a JDBCQuery as the datasource.
var itemList:java.util.Vector = new java.util.Vector;
var colID = "viewColumn"; //default id assigned
var colHeaderID = "viewColumnHeader"; //default id assigned
var end = 10; //max # of viewPanel columns
itemList.add("Select Column");
for(x=1;x<end;x++) {
try {
if(getComponent(colID + x) == null) {
throw ("Only " + (x-1) + " columns in ViewPanel");
x=end;
} else {
var disColID = getComponent(colID + x).getColumnName();
}
var disColHeaderID = getComponent(colHeaderID + x).getValue();
itemList.add(disColHeaderID + "|" + disColID);
} catch (e) {
dBar.info(e.toString());
}
}
itemList
The current way is obviously restricted to only 9 columns and ensuring the viewColumn ID and viewColumnHeader ID have a specific naming structure which would be nice to get away from.
All the columns of a view panel can be accessed by getting the child components of view panel using viewPanelObj.getChildren(). The column headers are a part of view column and after you get the handle of view column you can access the header using viewColumnObj.getHeader().
So a sample SSJS code to access all the view columns and view headers would look something like this:
var viewPnl:com.ibm.xsp.component.xp.XspViewPanel = getComponent("viewPanel1");
var list:java.util.List = viewPnl.getChildren();
for (var i=0 ; i<list.size() ; i++) {
var viewCol:com.ibm.xsp.component.xp.XspViewColumn = list.get(i);
var viewHdr:com.ibm.xsp.component.xp.XspViewColumnHeader = viewCol.getHeader();
// Perform required operations on objects of viewCol & viewHdr
}

How to Handle textbox values on sever side

I have three textboxes.In textbox1 and in textbox2 i entered a number Like ->
Textbox1-0123456789
Textbox2-0123-456-789
Textboxe3-0123-456-789
Now on server side i.e on aspx.cs page i need to check the numbers is it same or not and only one distinct number will be saved in database
//Get the values from text box and form a list
//validate against a regular expression to make them pure numeric
//now check if they are all same
List<string> lst = new List<string>()
{
"0123-456-A789",
"0123-456-A789",
"0123-456-789"
};
Regex rgx = new Regex("[^a-zA-Z0-9]");
//s1 = rgx.Replace(s1, "");
for (int i = 0; i < lst.Count; i++)
{
var value = lst[i];
value = rgx.Replace(value, "");
lst[i] = value;
}
if (lst.Any(num => num != lst[0]))
{
Console.WriteLine("All are not same");
}
else
{
Console.WriteLine("All are same");
}
//if all are same, pick an entry from the list
// if not throw error
HOPE THIS MAY GIVE U AN IDEA !!!!
If we apply replace("-","") than from every textbox it will remove dash.The number which is same like in
textbox1-0123456789
textbox2=0123-456-789
textbox3=678-908-999
than replace will remove dash from textbox3 also which we dont want.
so For this we have to apply not exists operation of linq.
List strMobileNos = new List();
Regex re = new Regex(#"\d{10}|\d{3}\s*-\s*\d{3}\s*-\s*\d{4}");
!strMobileNos.Exists(l => l.Replace("-", "") == Request.Form["txtMobNo2"].Replace("Mobile2", "").Replace("-", ""))

Dropdown field - first item should be blank

Using sharepoint build in lookup column and it set to required field. SharePoint automatically selects the first item in the dropdown box (kinda misleading for the end users).
Is there a way to display blank or Null for the first row of this drop down box?
(I am open to any solution. I prefer javascript type solution)
For Choice fields, the default value is configured in the column settings. If the "Default value" input box is populated, delete the value in order to use no default value.
Edit
For Lookup fields, the field seems to change dramatically if it is required. Fields that are NOT required have a "(None)" value by default. However, toggling the field to required will remove the "(None)" value and the first value is selected automatically.
One thing I found, is that if you use JavaScript to add the null value to the dropdown and then try to press OK you get an error page: "An unexpected error has occurred." As a workaround, I wrote some more code to do a quick validation that the field has a value before the form is submitted. If the field has no value, then it will prompt the user and cancel the submit. (Note: this code is only attached to the OK buttons so you may get errors while editing EditForm.aspx.. just choose a value for your lookup field and you'll be able to edit like normal)
Anyways, onto the code... I think the only line you'll need to change is var fieldTitle = 'Large Lookup Field'; to update it to the name of your field.
<script type="text/javascript">
function GetDropdownByTitle(title) {
var dropdowns = document.getElementsByTagName('select');
for (var i = 0; i < dropdowns.length; i++) {
if (dropdowns[i].title === title) {
return dropdowns[i];
}
}
return null;
}
function GetOKButtons() {
var inputs = document.getElementsByTagName('input');
var len = inputs.length;
var okButtons = [];
for (var i = 0; i < len; i++) {
if (inputs[i].type && inputs[i].type.toLowerCase() === 'button' &&
inputs[i].id && inputs[i].id.indexOf('diidIOSaveItem') >= 0) {
okButtons.push(inputs[i]);
}
}
return okButtons;
}
function AddValueToDropdown(oDropdown, text, value, optionnumber){
var options = oDropdown.options;
var option = document.createElement('OPTION');
option.appendChild(document.createTextNode(text));
option.setAttribute('value',value);
if (typeof(optionnumber) == 'number' && options[optionnumber]) {
oDropdown.insertBefore(option,options[optionnumber]);
}
else {
oDropdown.appendChild(option);
}
oDropdown.options.selectedIndex = 0;
}
function WrapClickEvent(element, newFunction) {
var clickFunc = element.onclick;
element.onclick = function(event){
if (newFunction()) {
clickFunc();
}
};
}
function MyCustomExecuteFunction() {
// find the dropdown
var fieldTitle = 'Large Lookup Field';
var dropdown = GetDropdownByTitle(fieldTitle);
if (null === dropdown) {
alert('Unable to get dropdown');
return;
}
AddValueToDropdown(dropdown, '', '', 0);
// add a custom validate function to the page
var funcValidate = function() {
if (0 === dropdown.selectedIndex) {
alert("Please choose a value for " + fieldTitle + ".");
// require a selection other than the first item (our blank value)
return false;
}
return true;
};
var okButtons = GetOKButtons();
for (var b = 0; b < okButtons.length; b++) {
WrapClickEvent(okButtons[b], funcValidate);
}
}
_spBodyOnLoadFunctionNames.push("MyCustomExecuteFunction");
</script>
In response Kit Menke, I've made a few changes to the code so it will persist previous value of the dropdown. I have added the following lines of code to AddValueToDropdown()....
function AddValueToDropdown(oDropdown, text, value, optionnumber){
var selectedIndex
if (oDropdown.options.selectedIndex)
selectedIndex = oDropdown.options.selectedIndex;
else
selectedIndex = -1;
// original code goes here
// changed last line of code (added "selectedIndex+1")
oDropdown.options.selectedIndex = selectedIndex+1;
}
To improve on top of Aaronster's answer: AddValueToDropdown can be done that way:
var injectedBlankValue = false;
function AddValueToDropdown(oDropdown, text, value, optionnumber) {
for (i = 0; i < oDropdown.options.length; i++) {
option = oDropdown.options[i];
if(option.getAttribute('selected')) // If one is already explicitely selected: we skip the whole process
return;
}
var options = oDropdown.options;
var option = document.createElement('OPTION');
option.appendChild(document.createTextNode(text));
option.setAttribute('value', value);
if (typeof (optionnumber) == 'number' && options[optionnumber]) {
oDropdown.insertBefore(option, options[optionnumber]);
}
else {
oDropdown.appendChild(option);
}
// changed last line of code (added 'selectedIndex+1')
oDropdown.options.selectedIndex = 0;
injectedBlankValue = true;
}
This is needed for document libraries where "add" and "set properties" are two distinct pages.
And funcValidate starts with:
var funcValidate = function () {
if (!injectedBlankValue)
return true;
All these changes is to make the whole thing work with document libraries.

Resources