#dbcolumn in session.evaluate in xpages - lotus-notes

I am trying to execute this code for a listbox but its not working, this gives me the error 500. If i directly write the #formula in listbox it works fine.
return session.evaluate("#DbColumn(#DbName(), \"viewName\", 1)").elementAt(0)
but if i write below code it works fine.
return session.evaluate("#Unique").elementAt(0);
I am working in xpages on Lotus Notes 8.5.3

You receive a 500er Error because the #DbColumn for SSJS has a parameter less than the "original" #DbColumn-Version which will be executed if you are using the evaluate method.
For XPages, the option for caching and class got lost.
This is the syntax for the evaluate statement:
#DbColumn( class : cache ; server : database ; view ; columnNumber )
This is the XPages syntax:
#DbColumn( server : database , view , columnNumber );
And you have to use the native Notes #Formula syntax, f.e. use semicolons instead commas.

session.evaluate works with original #Formula syntax, not with SSJS one.
So use #DbColumn( ""; #DbName; "view", column ) instead.

Here is the solution:
In SSJS you can code the following directly...
#DbColumn(#DbName(),"viewName",1)
If you want to do the same using the session.Evaluate(), then you can try the following.
//#DbColumn(#DbName(),"viewName",1) --> in SSJS
//#DbColumn( class : cache ; server : database ; view ; columnNumber ) --> in Formula using Evaluate
var colValues = "#DbColumn(\"\":\"\";" + #DbName() + ";\"viewName\";1)";
print ("colValues[0]" + colValues[0]); // will print #DbColumn( "":""; ServerName ; viewName; 1)
print ("colValues[1]" + colValues[1]); // will print #DbColumn( "":""; DatabaseName; viewName; 1)
return session.evaluate(colValues[1]) // It will return the expected value in listbox
Because #DbName() will return both the server name and the database name. Whereas we need only the database name. This is only for the current server. For different server we need to specify the server name. I hope this will help...!!!

Related

How to associate id and its value in Combobox Domino designer(lotus script)

I am new to Domino designer and lotus script,
I have a form ,which has a combobox ,In combobox I have a formula for combobox:
(#DbColumn("" : "NoCache"; ""; "myview"; 2)
now I want to associate the ID and its name
Example : id :1 name(to display in combo) :Benz
id :2 name : Fiat
id :3 name : Yamaha
now my combobox must display only fiat,yamaha,benz but the corresponding id must be saved (not the name)
currently I'm displaying only names and saving names(I want to link it to id)
How can I achieve this ?
Your view needs to contain the values in format Name|ID (this is a pipe sign) in order to achieve what you want.
Column values:
Benz|1
Fiat|2
Yamaha|3
Response to your comment: Best practice (performance- wise) is, to create a separate column in your view with the formula Name + "|" + ID (you can hide it, if you use the view for users AND DBColumn, what would be bad practice by the way).
if you don't want to do this, then your formula could look like this:
_names := #DbColumn("" : "NoCache"; ""; "myview"; 2);
_ids := #DbColumn("" : "NoCache"; ""; "myview"; 1);
_names + "|" + #Text(_ids)
You REALLY should take a training in Lotus Notes Design, as these are all basics, if you once understood how Notes works.
The formula above is bad in a lot ways:
Usage of "NoCache" is a real performance- killer. Don't do it in big applications
doing two lookups instead of one doubles your response- times
Every lookup HAS to have an error handling, otherwise your form will not open anymore, if there is an error in it.
If the return of your DBColumn is >32k of data (large lists) this whole thing will fail due to field restrictions in Lotus Notes
A "best practice" way to do this (ignoring the possible 32k error) would be:
Create a view with a (hidden) third column with formula Name + "|" + ID
Use this code:
_view := "myview";
_col := 3;
_lkp := #DBColumn( "" : "Cache" ; "" ; _view; _col );
#If( #IsError( _lkp ) ; "" ; _lkp )

getting a list of forms that contain a specified field, is there a better method

The following code is a script object on an XPage in it I loop through an array of all the forms in a database, looking for all the forms that contain the field "ACIncludeForm". My method works but it takes 2 - 3 seconds to compute which really slows the load of the XPage. My question is - is there a better method to accomplish this. I added code to check to see if the sessionScope variable is null and only execute if needed and the second time the page loads it does so in under a second. So my method really consumes a lot of processor time.
var forms:Array = database.getForms();
var rtn = new Array;
for (i=0 ; i<forms.length; ++i){
var thisForm:NotesForm = forms[i];
var a = thisForm.getFields().indexOf("ACIncludeForm");
if (a >= 0){
if (!thisForm.isSubForm()) {
if (thisForm.getAliases()[0] == ""){
rtn.push(thisForm.getName() + "|" + thisForm.getName() );
}else{
rtn.push(thisForm.getName() + "|" + thisForm.getAliases()[0] );
}
}
}
thisForm.recycle()
}
sessionScope.put("ssAllFormNames",rtn)
One approach would be to build an index of forms by yourself. For example, create an agent (LotusScript or Java) that gets all forms and for each form, create a document with for example a field "form" containing the form name and and a field "fields" containing all field names (beware of 32K limit).
Then create a view that displays all these documents and contains the value of the "fields" field in the first column so that each value of this field creates one line in this view.
Having such a view, you can simply make a #DbLookup from your XPage.
If your forms are changed, you only need to re-run the agent to re-build your index. The #DbLookup should be pretty fast.
Place the form list in a static field of a Java class. It will stay there for a long time (maybe until http boot). In my experience applicationScope values dissappear in 15 minutes.

lotus notes, search data that equal to textbox

I don't understand why my code is not allowed.
#If(#DbLookup("":"nocache";#DbName;"GPA";1)="GPnum";#Failure(#Command([FileSave])&#Command([CloseWindow]));#Success)`
Please help me. Thank you.
#If(#DbLookup("":"nocache";#DbName;"GPA";1)="GPnum"
your code should have 1 more parameter.
from help
#DbLookup( class : cache ; server : database ; view ; key ; fieldName ; keywords )
So you have "GPA" as view and then you need to specify Key and field/column you wish to return. Also for DbLookup I would recommend you to use [FAILSILENT] as keywords, in this case you will not need to check result for #IsError
However probably you just need to use #DbColumn instead of #DbLookup.
as I understood you need to verify if some value exists in database/view, try this code:
#If(#DbColumn("":"NoCache";#DbName;"GPA";1)="GPnum"; #Failure(#Command([FileSave]) : #Command([CloseWindow])); #Success)
or
#If(#DbLookup("":"NoCache";#DbName;"GPA"; "GPnum"; 1; [FAILSILENT])<>""; #Failure(#Command([FileSave]) : #Command([CloseWindow])); #Success)
Edit: I add a code for button action that save the current doc (see author comment below)
The editable field in which the user enters the value we check is called GPnum. A view "GPA" is sorted by its first col an display GPnum value.
t:=#DbLookup("":"nocache";#DbName;"GPA"; GPnum ; 1 ; [FailSilent] );
#If(#IsError(t) ; #Prompt([Ok]; "DB has a problem:";#Text(t)) ;
t = "" ; #Do(#Command([FileSave]);#Command([CloseWindow])) ;
#Prompt([Ok] ; "unable to save" ; "The key already exists") )
original response
t:=#DbLookup("":"nocache";#DbName;"GPA"; #ThisValue ; 1 );
#If(#IsError(t) ; #Failure("DB has a problem:"+#Text(t)) ; t = "" ; #Success ; #Failure("The key already exists") )
If you use #failure/#success you MUST be in an editable field in a form (validation).
As I understand you check that your value does not ALREADY exists.
so:
first add #thisValue as the key you search in the DBLOOKUP,
as told above DBLOOKUP could return an error thus check #isError(t)
second failure just BLOCK the validation of the form, I never tried (an it doesn't make sense) to make it save the form
Hope it helps

Binding an edit box within a custom control to a form field programatically

I have a notes form with a series of fields such as city_1, city_2, city_3 etc.
I have an XPage and on that XPage I have a repeat.
The repeat is based on an array with ten values 1 - 10
var repArray = new Array() ;
for (var i=1;i<=10;i++) {
repArray.push(i) ;
}
return(repArray) ;
Within the repeat I have a custom control which is used to surface the fields city_1 through city_10
The repeat has a custom property docdatasource which is passed in
It also has a string custom property called cityFieldName which is computed using the repeat
collection name so that in the first repeat row it is city_1 and in the second it is city_2 etc..
The editable text field on the custom control is bound using the EL formula
compositeData.docdatasource[compositeData.cityFieldName]
This works fine but each time I add new fields I have to remember to create a new custom property and then a reference to it on the parent page.
I would like to be able to simply compute the data binding such as
compositeData.docdatasource['city_' + indexvar]
where indexvar is a variable representing the current row number.
Is this possible ? I have read that you cannot use '+' in Expression Language.
First: you wouldn't need an array for a counter. Just 10 would do (the number) - repeats 10 times too. But you could build an array of arrays:
var repArray = [];
for (var i=1;i<=10;i++) {
repArray.push(["city","street","zip","country","planet"]) ;
}
return repArray;
then you should be able to use
#{datasource.indexvar[0]}
to bind city,
#{datasource.indexvar[1]}
to bind street. etc.
Carries a little the danger of messing with the sequence of the array, if that's a concern you would need to dig deeper in using an Object here.
compute to javascript and use something like
var viewnam = "#{" + (compositeData.searchVar )+ "}"
return viewnam
make sure this is computed on page load in the custom control
I was never able to do the addition within EL but I have been very successful with simply computing the field names outside the custom control and then passing those values into the custom control.
I can send you some working code if you wish from a presentation I gave.

Pagination in ListViewByQuery web part

I have written a web part that use ListViewByQuery to display the items based on query provided. Everything work perfect except pagination.
When I specify rowLimit it is displaying me only first set of record and pagination control is not visible so I could not able to move to next set of records.
The problem is that when you click on the paged button 1-2 it will postback adding some values in query string.
I accidentally remove the view=. query string from the URL and hit enter to get the results.
So what I did is as follows
if (!string.IsNullOrEmpty(Request.QueryString["View"]))
{
string queryString = string.Empty;
foreach (string key in Request.QueryString.Keys)
{
if (key.ToLower() != "view")
queryString += key + "=" + Request.QueryString[key] + "&";
}
SPUtility.Redirect(Request.Url.GetLeftPart(UriPartial.Path), SPRedirectFlags.Default, HttpContext.Current,queryString);
return;
}
Great answer Muhammad - after removing the view key and value, the link works fine.
However the line SPUtility.Redirect(.. didn't work for me.
Instead, as I put your code inside CreateChildControls() I used:
this.Context.Response.Redirect(this.Context.Request.Url.GetLeftPart(UriPartial.Path) + "?" + queryString);

Resources