Question here, may i know using this way to open existing document is totally wrong, or i miss out some part?
Cuz currently not be able to open existing document.
Let say i already have the "document" inside with NRIC 851013-13-5125
Below is the code to get DocumentID
var vw:notesView = database.getView("Request sort by nric used for docID");
var doc:NotesDocument = vw.getDocumentByKey(document1.getValue("NRIC"), true)
if (doc!=null){
return doc.getItemValue("docID")
}
Desmond,
beside a HUGE security hole - displaying data based on an NRIC only (which is almost public data, since you use it everywhere to sign up for membership, discount cards etc.
You should change a few things:
Bind you entry box to a scope variable, not a document, so instead of document1.getValue("NRIC") you use viewScope.NRIC
You don't need to go after an item, but use doc.universalid, or better have that as a column in the view, so you could use #DbLookup(....)
Even better: you could simply redirect the URL to open /yourdb.nsf/byNRIC/[S12345678X] having a view byNRIC that is sorted by NRIC and has in the form property the XPage to open
Having said that: PLEASE(!!!) implement proper security. Singapore's legislation is VERY specific on data protection. You might want to read up on it here: https://www.pdpc.gov.sg/legislation-and-guidelines/overview
Related
I have an xPage that is behaving very oddly. (if xPages get corrupt, I think this one might be) Tell me what you think:
I have editable fields with onChange events that take the value of the field (a company name) and looks into the database to see if the company already exists. If it does not, a field called "isNew" is set to "y". BUT the next time a Full Update is performed, from another field or button, my "isNew" field (or all of them) are erased! Why on earth would a full update erase a totally different field?
Do I need to just recreate this xPage?
============================================================================
Ok, here's the onChange event on the editable field that sets the flag:
var c = currentDocument.getItemValueString("company");
var id = #DbLookup("","AD",tc,11); // this view column gets the doc ID
if (id==null || id==""){
#SetField("isNew","y")
}
This field is being set properly - I use a computed field to display it. But the next full update (button, field, whatever) will erase the "isNew" field.
I think your problem is caused by the data sources you have on your page and how you save them.
Maybe you have data sources that gets binded from the url that should not be.
Are you using data sources within a repeat or view panel? If so, make sure you are only saving the correct data source
JSF (and thus XPages) works best when keeping MVC in mind. So you never manipulate a component, but keep that component bound to a model, like a data source or a scope. This way code doesn't get into each other's way.
A refresh of a page computes the whole tree, not just the updated field, so you need to design your calls carefully.
Work directly with your data source so do this instead of #SetField():
currentDocument.setValue("isNew", "y")
This seems like it should be easy to do but I cannot get it done.
I have an Xpage called Location. There are two general types, A and B. I have a series of views for A and B. They are the same except for the value of that one field.
In the views I want my "New Location" button to automatically populate the type to A or B, depending on whether the user is in one of the A views or B views.
Seems like I would set a scoped variable and then check for that on document creation, but it doesn't seem to work. What is the best practice to do this?
Jesse Gallagher's frostillicus framework on OpenNTF (XPages Scaffolding - http://openntf.org/main.nsf/project.xsp?r=project/XPages%20Scaffolding&SessionID=DN6QBBFGEB) includes flashScopes, which give the facility to pass information from one page to another and get cleared when the page is loaded.
You can use sessionScope variable to transfer data from one XPage to another.
A better approach might be to use URL parameter for your case.
Add for example &type=A to your URL like
http://server/database.nsf/Location.xsp?action=newDocument&type=A
Then you can read this parameter in your destination XPage with param.type like
var type = param.type;
The disadvantage of sessionScope is that it's the same for all browser tabs. So, you need to delete it right after usage in this case. Using an URL parameter instead you don't have to think about that.
My scenario:
The xpage ( document content ) has a complex structure. I have a 1st button which opens this xpage, having in the postNewDocument:
Contr.replaceItemValue("txt_codformularmain","01") // I use this field as a flag.
Now, there is another button which compose the same xpage ... but in this case, I do want the xpage to be different, in other words to have some additional / showed fields.
I could add another code at the postNewDocument, like this:
Contr.replaceItemValue("txt_codformularmain2","01")
Later on, in some views I will filter the listed documents by this 2 fields: some views will be listing the documents where txt_codformularmain=01, other views for txt_codformularmain2=01, and so on.
All the fields are on the same form element. ( I could create easily 2 different xpages, with 2 document contents, but in the form Properties at onOpen and onWebAccess settings, I can add only one xpage )
But, I think it isn't the best approach for this. Because in both cases, postNewDocument takes place, and both fields are having the value 01.
In classic lotus notes programming, I had used only one field ( flag ) and for every different button, inside the button's code I just changed the field value: 01, 02, and so on, before the newDocument had been composed.
Should I use another/ a better approach?
I might go for creating a new form with the fields needed there, and creating a new XPage binded to that form...
dominoDocument.isNewNote() will tell you if it's a new document or not. You can compute visibility based on that.
If it's based on a field value, then again set the visibility based on what the value should be for the panel to be visible - instead of getComponent().getValue() use dominoDocument.getItemValueString() assuming it's a Text field for best practice. In the onblur event of the control that's bound to the field you're checking against, trigger a partial refresh. You will need to amend the default partial refresh settings if there is validation on the page.
Once you're comfortable with that technique, start thinking about using a dataContext to hold whether or not an area should be visible, and referencing that dataContext variable in the rendered property. The benefits of this are not only performance, but youo can give a better variable name to the dataContext to make it clearer when supporting the application what the logic is behind it being visible. For someone supporting the Notes Client app, for example, it's unclear without hunting what state "01" or "02" means. Descriptors like "newDoc", "published", etc have an advantage there.
Another method of optimisation would be to use a Dynamic Content control.
But it sounds like your XPage is going to be complex enough without adding more complexity at this stage.
I want to know if I can click a button in my XPage and dynamically create a Domino View and then show it in a panel control on the same page. The reason I want to do this is because I have a categorized view and I don't want to lose category data by using full text search. So I am thinking of creating a new view dynamically and pass my search parameters, like end date or start date, into the view selection formula.
Is it possible? Any other alternative solution is also welcome.
yes you can, but you don't want to. A Domino view takes space in the database and quite some time for its first use. So you end up with a lot of views taking space and the need to adjust database space after removal. Your response times will suck big time.
Categories as shown in Notes views are no web interaction pattern, so you might want to solve a problem that actually shouldn't exist.
The preferred method for Domino application is navigation / drill down over search. But you could do a FTSearch where you add your category to the search parameters and render your results in a repeat control instead of a view control. There you have more control over the look and feel.
Whether or not it's the best solution, the answer to the immediate question about creating a view on the fly is yes: the Database class has a couple "createView" methods to allow you to create a new view, either entirely from scratch or based on a named other view. From there, you can use the "setSelectionFormula" and "createColumn" methods in the created View to build what you want. You can't do EVERYTHING with those methods, but it may be enough.
One problem you'd likely run into is ACL access: you'll need Designer rights to the database, which a normal user most likely wouldn't have. If you use the sessionAsSigner object to fetch a signer version of the DB (say, "var signerDB = sessionAsSigner.getDatabase(database.getServer(), database.getFilePath())"), you can work from there. Off the top of my head, I don't remember if you will also have to up the "Maximum Internet access" setting on the last tab of the ACL to Designer as well, but you may.
I am assuming that you are referring to the problem that exists when you choose the documents based on the category. This is something that I find highly annoying and I wish that it was possible to turn this on and off. It makes sense for embedded views, but not for much else.
What I did to solve this was to include the category value in the next column. In this way that text could still be seen, even if it was a flat view.
Alternatively, you could also look into using a repeater control and create your own way of presenting the information. This would be used instead of a (Dynamic)ViewPanel control. You could then present the information any way you wanted as long as it is returned in the viewrow set.
Happy Programming!
There is a lot of questions about binding data to forms. This is very simple. I have a form that uses several computed fields that pull data using an #DbLookup to populate the fields based on a pulldown menu the user selects. The problem is; none of the computed fields save any of the values into the form that it is bound to. The only data that saves on the form is the data that is manually selected (in the case of the pulldown menu) or manually entered. When I use an edit box and don't make it "Read Only" the data saves fine. Why is this so difficult?
Mark -
Couple approaches here I think... but let's walk though something.
Read Only on the edit box is preventing the save. It makes sense. XPages should not try to save something marked "read only".
As Steve says, you're better off here with a computed field. Set the values however and if their bound to the document then I think they will save fine.
Another approach is is to work with scoped variables. When you get your data points... you can put that into scoped variables like:
viewScope.put("myField", myValue)
then you're computed field could be bound to the viewScope variable "myValue".
however this will of course not save back to the document as it's not bound to the document. So what you do if you want that approach is in the document save event... you then use SSJS to assign the values to the doc then. something like:
document1.replaceItemValue("myfield", viewScope.get("myField");
Since xpages basically has the same document events as notes client. This may seem familiar to you.
Hope this helps.
Dave -
NotesIn9.com
Disclamer: I'm answering this from a plane after a trip to Las Vegas. So please factor that into the quality of my answer. :)
You will want to put the data you receive from the #DbLookup in an edit box field(s). A computed field is like a "Computed for display" field in traditional Notes development. You can choose whether to allow the user to change the values or not by the read-only property.
Also see this question if you want the values read-only which it sounds like you do: ReadOnly field in Xpage not submitted
As usual, Dave steered me to something that worked. Being in the larval stages of JavaScript experience, I'm sure there is a better way to do this. I'm just happy it works. Her is the code I put into the QuerySave event of my Xpage.
var cost1 = getComponent('ItemCost1').getValue();
var uom1 = getComponent('UOM1').getValue();
var Num1 = getComponent('ItemNum1').getValue();
var tot1 = getComponent('Total1').getValue();
docuent1.replaceItemValue("ItemCost_1", cost1),
document1.replaceItemValue("ItemUOM_1", uom1),
document1.replaceItemValue("ItemNum_1", Num1),
document1.replaceItemValue("CostTotal_1", tot1)
I have 30 iterations of this so it probably works kind of clunky but the operative word is WORKS. If anyone has a better way to get the same results, please post it so I can learn something. Thanks for everyone's help.