What i want is to be able to choose the granularity for the messages displayed in my <rich:messages /> tag, meaning that the source of these messages could be the entire application, the current page or a single element. What are the options that RichFaces provides?
I am aware of the globalOnly attribute, which can be set to true or false, but i don't understand what is considered global and what is not.
So, i am looking for the whole list of message scopes .This list of scopes could be , for example : application, session, page, form. I would also appreciate a small example of each
You could read the reference doc.
A message is typically created like this:
FacesMessage message = new FacesMessage("Error!","An error has occurred.");
facesContext.addMessage(id, message);
If the id is null the message is global. So you can either use #for to show messages for a specific component, or #globalOnly to show global messages. If you use neither you will show all messages.
Related
I have a page where I wanted to use the "enableModifiedFlag" property, to let users know that their edit was not saved if they want to leave a page before saving.
I also have a search box in that page, and when I set the field to the static value "true", the message was popping because the search box was considered part of the page, and the field was modified. This all makes sense.
Since the "enableModifiedFlag" property can be computed, I decieded to set it to true only if the document was in edit mode, as the search box is not available at that time. The behaviour I got was that the message was not appearing anymore. I then tested with returning true as the value of the property, and it didn't change anything: the message was just gone. I then used the static values and set it to true, and the message was then appearing.
My conclusion is that there is a bug that prevents any computed value to be considered for that property.
So I had to find a workaround to prevent the message from popping up when users used the serach box. Here is the solution I came up with.
On the client side, we have access to the XSP object. One of its method is XSP._setDirty(). you can either set it to true or false, and it will affect if the page diplays the popup message or not. So in my search button, I added this code on the onclick event, on the client side:
XSP._setDirty(false,""); //so we don't get the "do you want to leave this page" message
showStandBy(); //show standby in case search is long or slow
return true;
That way, I tell my page not to show the message and the popup is not displayed.
It's still a shame you can't use the computed value for that property, but at least we have a workaround. Hope this will be useful to somebody!!!
GOT SOMETHING WORKING I THINK
This is what I have now, that controls teh flag:
<xp:this.enableModifiedFlag><![CDATA[${javascript:context.getUrlParameter("action")=="editDocument";}]]></xp:this.enableModifiedFlag>
I would rather use the document1.isEditable() function, but I wasn't successful with it so far, neither computed dynamically nor on page load.
At leaset I have something that seems to be working. Time to submit that code to the end users!
I hope someone can help me solve a very serious problem we face at the moment with a business critical application losing data when a user works in it.
This happens randomly - I have never reproduced this but the users are in the system a lot more than me.
A document is created with a load of fields on it, and there are 2 rich text fields. We're using Domino 8.5.3 - there are no extension lib controls in use. The document has workflow built in, and all validation is done by a SSJS function called from the data query save event. There is an insane amount of logging to the sessionscope.log and also this is (now) captured for each user in a notes document so I can review what they are doing.
Sometimes, a user gets to a workflow step where they have to fill in a Rich Text field and make a choice in a dropdown field, then they submit the document with a workflow button. When the workflow button is pressed (does a Full Update) some client side JS runs first
// Process any autogenerated submit listeners
if( XSP._processListeners ){ // Not sure if this is valid in all versions of XPages
XSP._processListeners( XSP.querySubmitListeners, document.forms[0].id );
}
(I added this to try and prevent the RTF fields losing their values after reading a blog but so far it's not working)
then the Server-side event runs and calls view.save() to trigger QS code (for validation) and PS code to run the workflow agent on the server.
95% of the time, this works fine.
5% of the time however, the page refreshes all the changes made, both to the RFT field (CKEditor) and the dropdown field are reloaded as they were previously, with no content. It's like the save hasn't happened, and the Full Update button has decided to work like a page refresh instead of a submit.
Under normal circumstances, the log shows that when a workflow button is pressed, the QuerySave code starts and returns True. Then the ID of the workflow button pressed is logged (so I can see which ones are being used when I am reviewing problems), then the PostSave code starts and finally returns true.
When there is a problem, The QuerySave event runs, returns true if the validation has passed, or false if it's failed, and then it stops. The ID of the workflow button is also logged. But the code should continue by calling the PostSave function if the QuerySave returns true - it doesn't even log that it's starting the PostSave function.
And to make matters worse, after the failure to call the PostSave code, the next thing that is logged is the beforePageLoad event running and this apparently reloads the page, which hasn't got the recent edits on it, and so the users loses all the information they have typed!
This has to be the most annoying problem I've ever encountered with XPages as I can find no reason why a successful QuerySave (or even a failure because mandatory fields weren't filled in) would cause the page to refresh like this and lose the content. Please please can someone help point me in the right direction??
It sounds as if in the 5% use cases, the document open for > 30mins and the XSP session is timing out - the submit causes the component tree to be re-created, and the now empty page returned back to the user. Try increasing the time out for the application to see if the issue goes away.
I would design the flow slightly different. In JSF/XPages validation belongs into validators, not into a QuerySave event. Also I'd rather use a submit for the buttons, so you don't need to trigger a view.save() in code. This does not interfere with JSF's sequence of things - but that's style not necessarily source of your problem.... idea about that:
As Jeremy I would as a first stop suspect a timeout, then the next stop is a fatal issue in your QuerySave event, that derails the runtime (for whatever reason). You can try something like this:
var qsResult = false;
// your code goes here, no return statements
// please and if you are happy
qsResult = true;
return qsResult;
The pessimistic approach would eventually tell you if something is wrong. Also: if there is an abort and your querySave just returns, then you might run in this trap
function noReturn() {return; } //nothing comes back!
noReturn() == true; --> false
noReturn() == false; --> false
noReturn() != false; --> true!!!!
What you need to check: what is your performance setting: serialize to disk, keep in memory or keep latest in memory? It could be you running foul of the way JavaScript libraries work.
A SSJS library is loaded whenever it is needed. Variables inside are initialized. A library is unloaded when memory conditions require it and all related variables are discarded. so if you rely on any variable in a JS Function that sits inside a SSJS library between calls you might or might not get the value back, which could describe your error condition. Stuff you want to keep should go into a scope (viewScope seems right here).
To make it a little more trickier:
When you use closures and first class functions these functions have access to the variables from the parent function, unless the library had been unloaded. Also functions (you could park them in a scope too) don't serialize (open flaw) so you need to be careful when putting them into a scope.
If your stuff is really complex you might be better off with a backing bean.
Did that help?
To create a managed bean (or more) check Per's article. Your validator would sit in a application bean:
<faces-config>
<managed-bean>
<managed-bean-name>workflowvalidator</managed-bean-name>
<managed-bean-class>com.company.WfValidator</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
</faces-config>
Inside you would use a map for the error messages
public Map<String,String> getErrorMessages() {
if (this.errorStrings == null) { // errorStrings implements the MAP interface
this.loadErrorDefinitions(); //Private method, loads from Domino
}
return this.errorStrings;
}
then you can use EL in the Error message string of your validators:
workflowvalidator.errorMessage("some-id");
this allows XPages to pick the right one directly in EL, which is faster than SSJS. You could then go and implement your own custom Java validator that talks to that bean (this would allow you bypass SSJS here). Other than the example I wouldn't put the notes code in it, but talk to your WfValidator class. To do that you need to get a handle to it in Java:
private WfValidator getValidatorBean() {
FacesContext fc = FacesContext.getCurrentInstance();
return (WfValidator) fc.getApplication()
.getVariableResolver()
.resolveVariable(fc, "workflowvalidator");
}
Using the resolver you get access to the loaded bean. Hope that helps!
My experience is that this problem is due to keeping page in memory. Sometimes for some reason the page gets wiped out of memory. I'm seeing this when there is a lot of partial refreshes with rather complex backend Java processing. This processing somehow seems to take the space from memory that is used by the XPage.
The problem might have been fixed in later releases but I'm seeing it at least in 8.5.2.
In your case I would figure out some other workaround for the CKEditor bug and use "Keep pages on disk" option. Or if you can upgrade to 9.0.1 it might fix both problems.
Some of my recent posts have to do with the fact that I am doing all of my validation in my Submit button.
The reason I am doing this is that I have a button that sets some read only edit boxes. Well you can configure a validation for a read only edit box but it does not execute at run time.
Since I could not figure this out and wanted to have a consistent look for validation I used my own validation on my Submit button.
Is there a way to validate read only fields?
One nice thing about putting all of the code in the Submit button is that all of the validation code is all in the same place but I can see where it also can cause portability issues when using custom controls.
Also another question is how to fire off validation if my Submit button is not marked as a Submit button.
As Dec says, the ReadOnly flag causes the content of the field to be rendered without the <input> tag. This makes validation impossible on the client side and since there is no data being submitted back to the JVM, validation coded on the field is ignored on the submit.
However, the data source QuerySaveDocument is triggered. Put your validation in there and/or put it in the fields that are rendered (readOnly=false) and be sure to set disableClientSideValidation="true" on all fields with validators on them.
Your QuerySaveDocument code looks something like this (assuming location is the field which is readOnly).
if (personDoc.getItemValueString("Location") == "") {
#ErrorMessage("The inherited location is blank and that is bad.");
return false;
}
return true;
With this, the field based validators will fire first and if they are all successful the QuerySaveDocument fires. This means if any field based validators fail, their messages will appear in your message area but the QuerySaveDocument message will not appear. QuerySaveDocument messages ONLY appear after all field based validators succeed.
When a read only field is rendered to the web browser it does not render using <input> tags but rather a simple <span> tag.
Validation can only be performed on proper input tags so the scenario you are experiencing is correct. There is no field for it to validate in read-only mode.
There is an option to 'display disabled in read only' which will render an <input disabled="true"> type tag for the field but I'm not sure off the top of my head is validation will work for those fields either because if a field is read-only then there really should be no need for any validation because your programmatically putting the value into the field and you should be validating it programmatically before you add the value.
I am working with Ajax Editing within a Telerik Grid extension. I would like to handle errors/exceptions on Insert/Update/Delete and display a user friendly message in the message box that is displayed back to the client, instead of the default message of "Error! The requested URL returned 500 - Internal Server Error" or the like.
Is there a way to tell the grid to display a custom text message?
Someone customized the alert here: http://www.telerik.com/community/forums/aspnet-mvc/grid/how-to-return-error-information-to-grid-in-ajax-editing-mode.aspx, but I'm still searching for a way to actually update the grid itself...
There's a little hope in the client-side grid's noRecordsTemplate property, but we still need a way to clear the grid of any records that may have already been there.
Edit:
Found it: To clear the grid, and set your message, do the following:
var grid = $('#Grid').data('tGrid');
grid.total = 0;
grid.dataBind(Array());
$('#Grid').find('.t-no-data td').text('My Custom Error Message');
Of course, you can figure out on your own how to combine the my example and the example from the link above.
I am learning JSF and came across this line:
<h:messages layout="table"></h:messages>
in a sample application ?
Am not sure what does this line do? I get no error when removing the line from the code, and am able to run it and get the same output ?
The h:messages tag renders all messages for the current JSF view which are not covered by a h:message (remark the missing 's' at the end) tag. Messages can be generated explicitly by your backing beans (FacesContext.addMessage) or implicitly by JSF.
E.g. if you have marked an input value as required and the user submits the form without filling in the required value, an error message will be added to the view. If a h:message tag is bound to the relevant component, the message will be rendered there, otherwise it will be rendered by the global h:messages tag in your view (if any).
The layout attribute specifies what the HTML code to be generated should look like. The table layout (used in your example) uses an HTML table to display messages, while the list layout uses a bulleted list (HTML ul tag).
If you do not specify a h:messages tag in your view and also no h:message tags, the user will not be informed about errors. Therefore, it is best practice to include a h:message tag for each input component of your view and a h:messages tag for your whole view to ensure that all messages are visible to the user.
You will find a compact JSF tag reference at JSF Toolbox.
The components <h:message> and <h:messages> are dedicated to display messages to users (generally error message).
For example, when you have a validation on a field that failed (for example the user didn't fill a required field, or inputed a string in a number-only field), then a FacesMessage is added to the FacesContext object. The <h:message> and <h:messages> are then used to display the message in the page.
The component <h:messages> will display all the messages contained in the FacesContext, while the <h:message> is dedicated to a specific clientId (a specific field). The latter is usefull when you want to place the message close to a field for example.
Note that you can add any kind of message that will displayed to the user:
FacesContext.getInstance().addMessage(null, new FacesMessage("The message to display"));
In this example, the first parameter is the ID field of the field that is concerned by this message (usefull when the message is a validation message for a specific field). null means that the message is a general information (i.e. not linked to any particular field).
You can see an example of this component here. Note that this example uses the rich:messages that is an extension (provided by RichFaces) of the "basic" <h:message/>, but the principle is the same.