To hand over values from an XPage to a custom control, which approach should be used ?
a) Define properties in the custom control at design time. Fill in the properties at the XPage with computed values. Use the value via 'compositeData' in the custom control at runtime.
or
b) Put the value in a session scope variable at the XPage in BeforePageLoad event. Bind the session scope variable to the field in the custom control.
The session scope is primarily intended for ensuring that values persist as the user navigates between pages. I like to call it the "shopping cart" scope: if you built an e-commerce site in Domino, you wouldn't want the site to forget that a user had added a product to their cart just because they clicked back to the home page. So this scope is also useful for features like remembering search / sort / filter options as the user navigates the app so each time they navigate somewhere else and come back, it remembers their prior behavior without having to store this information permanently in the NSF.
For passing in-page information to a Custom Control from a container, however, compositeData is definitely the way to go. This is because that variable is populated with the passed parameters only for the duration of the processing of the relevant control. Once that control has been dealt with, all pointers to the passed parameters are cleaned up automatically, which provides incremental scalability improvement for each instance compared to storing the same information for the duration of each user's session.
There will be cases where there is overlap: a given Custom Control might reference information that is appropriate to store in the session scope. In this scenario I like to mix the two techniques... for example:
<xp:inputText value="#{sessionScope[compositeData.scopeKey]}" />
The above syntax allows a Custom Control to be passed by its container the identifier for where in the session scope the relevant information is stored. This provides some serious flexibility, because I can drop the same control into multiple contexts, with each telling the control which information it should retrieve / store in scope.
Related
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.
Is it possible to validate the Xpage's ACL depending on the Source document's field value.
We need to make the Authors & Readers ability at XPage level (as per requirement I am not supposed to use the ROLES, since, it is dependent on each individual Authors which is stored in backend document FIELD).
Kindly suggest the approach, as I am not even looking HideWhen for the Buttons(edit,save etc)
Example code in the ACLEntry[0] in Xpage:
if getComponent("inputText1").getValue() == sessionScope.user {
session.getEffectiveUserName();
} else {
return false;
}
Thanks.
I do not quite understand your code on that property...
To query the readers/authors level at XPage level I suggest to use the database.queryAccess method (http://www-10.lotus.com/ldd/ddwiki.nsf/dx/NotesDatabase_sample_JavaScript_code_for_XPages?opendocument&comments#queryAccess)
You try to compare the username only. This may fail if your access level is computed by a membership in a group where your username is not relevant.
XPages' ACL depends on the database ACL, so you have to setup the levels there - the XPages' ACL is in addition to the "real" ACL as far as I experienced.
I also experienced that readers fields affect the ability to use an XPage to open a document by default.
I hope my answer is not too confusing ;-)
I think the question is valid (to my current knowledge):
If I want to design a workflow application but the current approver should not edit the full document I want to give him only access to parts (ie. a comment field and the approval button).
The question above relateds somehow to access controlled sections in old LN development. I so far also didn't find a good solution
What you describe is a very common workflow scenario. There are several ways how you can implement that efficiently. Here is what I would do:
Have one (or more) custom controls that render the "payload" (the fields the requester fills in)
assemble them into one bigger control that is used to render the form
compute the mode to read/edit depending on who is opening the form and the mode (new, pending approval, approved, rejected etc.)
Optional: when submitted remove submitter from the author field
Have one "Approval Control" that show only when the current user is the (current) approver and status is "pending approval" That control has fields that are NOT bound to the document, but a scope variable
The approval button triggers SSJS that takes the scope variable values and updates the document (and triggers notifications, access change etc)
The approval component can be used for any approval form. You then can contemplate not to give the approver write access since you could handle that in code.
Lets say user A logs in and a sessionScope variable is set (This is just an example):
sessionScope.put("ABC", "ABC");
Now user B logs in and his sessionScope variable is set:
sessionScope.put("XYZ", "XYZ");
Is there a way where I can get all these sessionnScope variables/objects belonging to different users?
In theory, you could register a sessionListener that stores in the applicationScope a pointer to each sessionScope that is created... but, in my opinion, that's a very bad idea. You'd have to be extremely careful to avoid exposing users' session data to each other.
use the debugBar
http://www.openntf.org/internal/home.nsf/project.xsp?action=openDocument&name=XPage%20Debug%20Toolbar
Session scopes belong to a single user so you cant retrieve them out of the box. You could add logging to the xpage/business log so you can keep track of the things that are going on. Another approach is to login as the user where you want to now the scopes from and use the debugbar to investigate
SessionScope variables belong to a single instance of a browser/client. If you are Anonymous and log in as "user one" you have the same sessionScope as you did before. The same is true if you logout and log back in as "use two".
I have built an app which runs a method in the before page load of every page to assure the necessary sessionScope data is setup. One part of that data is the name of the user for whom the data is defined. That way, if the user name changes the we clear the data and reload it for the current user.
Using this approach you could define a MAP or JSON object with the username as the key which would keep the differences as people log in and out, but I am not sure that is a very sensible thing to do since changing identities is only realistic in development and testing. It is not a normal thing in production.
/Newbs
So lets say that I have two views, one that is the default and another that can be triggered with a button. Is it possible to switch views, then have the view that you switched to become the default view? So that if the form were opened again it would still be on the view you switched to?
If not, is there a way to have a part of a form read-only to a certain group in SharePoint and editable to another group?
Or even better, could I have an email sent out to with different views to different people?
Thanks!
No, it's not possible to set the default view with a button/code. You'd want use a different approach (something similar to the State Machine Pattern)
Create a "State" field, that represents the actual state of the form (usually the same as the views). So when the button is pressed, it sets the State-field to "View2" and switch the view to View2. In the form load rules (Data - Form Load) you create a new Rule that changes the view based on the value State-field.
Yes, setting different section of the form to read-only for specific groups is also possible, however it requires custom code. For each section create a new field (like "Section1Enabled"). Then create a new conditional formatting rule that disables Section1 if Section1Enabled is false. In your form's load event, you add code that that decides whether the current user is in the specific group or not and based on that, you set the value of Section1Enabled.
You can do with SharePoint's UserGroups.asmx or with the SharePoint Server Object Model (google should help you out with that).