Cannot get Custom Validator to fire - xpages

I am stumped. I have an input field in an xpage where I added a custom validator. I can not get the custom validator to fire no matter what I try. There is a also validateRequired which works as expected. The error message is sent to a "Display Error" control, clientside validation is disabled. The goal of the custom validator is to check if a valid date has been entered. After I get it working, I also plan to add other complicated validation such as checking valid day of the week.
The print statements work correctly, as in "inside true" shows in the console for a valid date, and "inside false" shows for an invalid date. If I add a test print statement after the if statement, it doesn't not execute as you would think. For either condition, the message does not display, and the page is submitted.
I have tried using both getValue() and getSubmittedValue. I have also tried returning a facesMessage and a string. I am also very open to better ways to do this.
<xp:inputText id="datepicker" styleClass="datepicker"
value="#{viewScope.arrivalDate}"
defaultValue="#{javascript:statusBean.arrivalDate}"
disableClientSideValidation="true">
<xp:this.validators>
<xp:validateRequired message="Please enter the arrival date">
</xp:validateRequired>
<xp:customValidator message="err" loaded="true">
<xp:this.validate><![CDATA[#{javascript:var datepicker = getComponent("datepicker").getSubmittedValue();
var testDate = #IsTime(#TextToTime(datepicker));
print("testDate=" + testDate);
if(testDate == 0){
print("inside false");
return false;
} else if(testDate == 1){
print("inside true");
return true;
}}]]>
</xp:this.validate>
</xp:customValidator>
</xp:this.validators>

I haven't tried with a custom validator, but here's the SSJS I put in the validator property for a sample demo at LUGs last year:
<xp:this.validator>
<![CDATA[#{javascript:var sv = this.getSubmittedValue();
print ("Checking submitted value for input1 '" + sv + "' is more than 5 characters");
print ("Value for input1 is " + this.getValue());
if (sv.length < 5) {
var msgStr = "You must enter your FULL name, which will be more than 5 characters!";
var msgObj = new javax.faces.application.FacesMessage(javax.faces.application.FacesMessage.SEVERITY_ERROR, msgStr, msgStr);
facesContext.addMessage(getClientId(this.getId()), msgObj);
this.setValid(false);
}}]]>
</xp:this.validator>
Note that it adds the facesMessage and also sets the component's valid property to false.

The customValidator must return a string with the error message in it - and not true or false.
So in your case, do this instead:
<xp:customValidator message="err" loaded="true">
<xp:this.validate><![CDATA[#{javascript:
var datepicker = getComponent("datepicker").getSubmittedValue();
var testDate = #IsTime(#TextToTime(datepicker));
print("testDate=" + testDate);
if(testDate == 0){
print("inside false");
return "Invalid date";
}
}]]></xp:this.validate>
</xp:customValidator>

Here's my version with using xSnippet - postValidationError.
<xp:customValidator>
<xp:this.validate><![CDATA[#{javascript:
if (#IsTime(#TextToTime(#Trim(value))) == 0){
postValidationError(this, "Please enter a valid Date/Time")
}
}]]></xp:this.validate>
</xp:customValidator>

Related

How to edit Tabulator dates in the cell?

http://tabulator.info/examples/4.1
The Editable Data example above shows the use of a custom editor for the date field (example in the link is DOB). Similar examples exist in earlier tabulator versions as well as here and Github. The javascript date picker that results works perfectly for most users but not all (even if also on Chrome). So the alternate approach often attempted by the users is to try and enter the date directly into the cell. But unfortunately this is problematic --in the same way it is with the linked example. Changing the month and day isn't too bad -- but directly changing the year is very difficult. Does anyone have a potential solution? I've explored everything from blur/focus/different formats/"flatpicker"/etc - but I'm coming up empty.
The best approach to get full cross browser support would be to create a custom formatter that used a 3rd party datepicker library, for example the jQuery UI datepicker. The correct choice of date picker would depend on your needs and your existing frontend framework.
in the case of the jQuery datepicker the custom formatter could look something like this (this example uses the standard input editor, you will notice in the onRendered function it turns the standard input into the jQuery datepicker):
var dateEditor = function(cell, onRendered, success, cancel, editorParams){
var cellValue = cell.getValue(),
input = document.createElement("input");
input.setAttribute("type", "text");
input.style.padding = "4px";
input.style.width = "100%";
input.style.boxSizing = "border-box";
input.value = typeof cellValue !== "undefined" ? cellValue : "";
onRendered(function(){
input.style.height = "100%";
$(input).datepicker(); //turn input into datepicker
input.focus();
});
function onChange(e){
if(((cellValue === null || typeof cellValue === "undefined") && input.value !== "") || input.value != cellValue){
success(input.value);
}else{
cancel();
}
}
//submit new value on blur or change
input.addEventListener("change", onChange);
input.addEventListener("blur", onChange);
//submit new value on enter
input.addEventListener("keydown", function(e){
switch(e.keyCode){
case 13:
success(input.value);
break;
case 27:
cancel();
break;
}
});
return input;
}
You can then add this to a column in the column definition:
{title:"Date", field:"date", editor:dateEditor}
I couldn't get what Oli suggested to work. Then again, I might be missing something simple as I am much more of a novice. After a lot of trial+error, this is the hack kind of approach I ended up creating -- builds upon Oli's onRender suggestion but then uses datepicker's onSelect the rest of the way.
The good: The datepicker comes up regardless where in the cell the user clicks -- so the user is less tempted to try and enter manually. If the user happens to try and enter manually, they can do so.
The less-than-ideal: If the user does manually enter, the datepicker won't go away until he/she clicks elsewhere. But not a showstopper.
//Date Editor//
var dateEditor = function(cell, onRendered, success, cancel, editorParams){
var cellValue = cell.getValue(),
input = document.createElement("input");
input.setAttribute("type", "text");
input.style.padding = "4px";
input.style.width = "100%";
input.style.boxSizing = "border-box";
input.value = typeof cellValue !== "undefined" ? cellValue : "";
onRendered(function(){
$(input).datepicker({
onSelect: function(dateStr) {
var dateselected = $(this).datepicker('getDate');
var cleandate = (moment(dateselected, "YYYY-MM-DD").format("MM/DD/YYYY"));
$(input).datepicker( "destroy" );
cell.setValue(cleandate,true);
cancel();
},
});
input.style.height = "100%";
});
return input;
};
I use datepicker from bootstrap, this is my code
var dateEditor = function (cell, onRendered, success, cancel, editorParams) {
//create and style input
var editor = $("<input type='text'/>");
// datepicker
editor.datepicker({
language: 'ja',
format: 'yyyy-mm-dd',
autoclose: true,
}).on('changeDate', function() {
if(editorParams != 'row'){
editor.trigger('keyup');
}else{
editor.trigger('change');
}
});
editor.css({
"padding": "3px",
"width": "100%",
"height": "100%",
"box-sizing": "border-box",
});
editor.val(cell.getValue());
onRendered(function(){
editor.focus();
});
editor.on("blur", function (e) {
e.preventDefault();
if(editor.val() === '') {
success(cell.getValue());
}
else {
//submit new value on change
editor.on("change", function (e) {
success(editor.val());
});
}
});
return editor;
}

Validate In-Line Edits in Netsuite

I need to validate inline editing in NetSuite.
I already have a Client Script in place that works great when editing the record normally.
I tried adding a User Event script that on the before save function that validates the record, but it appears this is ignored with inline editing.
Has anybody ran into this before?
Any insight you can provide would be helpful. Thanks!
Edits:
The relevant code from the UE script:
function beforeSubmit(type){
if (type == "create" || type == "edit" || type == "xedit") {
var status = nlapiGetContext().getSetting("SCRIPT", "...");
var amount = Number(nlapiGetContext().getSetting("SCRIPT", "..."));
var nr = nlapiGetNewRecord();
var entitystatus = nr.getFieldValue("entitystatus");
var projectedtotal = Number(nr.getFieldValue("projectedtotal"));
if (entitystatus == status && projectedtotal >= amount) {
var statusText = nr.getFieldText("entitystatus");
var message = "ERROR...";
throw nlapiCreateError("...", message, true);
}
}
}
This applies to the opportunity record.
The field being validated is Projected Total with id projectedtotal.
My mistake, I misunderstood how xedit handled nlapiGetNewRecord(). Calling nlapiGetNewRecord when in xedit only returns the edited fields, not the entire record. Thus, the if statement was never true in xedit mode, because either the amount or the status would be null (it was very unlikely the user would edit both at the same time, and validation relies on both these fields' values).
I edited the code to lookup the field value if it is not present in the new record. Now everything works as expected!
Thanks everyone for the help!
For reference, the corrected code is below.
function beforeSubmit(type){
if (type == "create" || type == "edit" || type == "xedit") {
var status = nlapiGetContext().getSetting("SCRIPT", "...");
var amount = Number(nlapiGetContext().getSetting("SCRIPT", "..."));
var nr = nlapiGetNewRecord();
//Attempt to get values normally
var entitystatus = nr.getFieldValue("entitystatus");
var projectedtotal = Number(nr.getFieldValue("projectedtotal"));
var id = nr.getId();
//If values were null, it's likely they were not edited and
//thus not present in nr. Look them up.
if(!entitystatus){
entitystatus = nlapiLookupField("opportunity", id, "entitystatus");
}
if(!projectedtotal){
projectedtotal = Number(nlapiLookupField("opportunity", id, "projectedtotal"));
}
if (entitystatus == status && projectedtotal >= amount) {
var message = "ERROR...";
throw nlapiCreateError("101", message, true);
}
}
}
In your user event are you checking the value of the type parameter. For inline editing, the value of the type is 'xedit'.

Value rule for Lookup field in RibbonWorkbench

I want to add a display rule to a custom ribbon button based on the value of a lookup field whether the lookup field is null or not. How should i check it. The below code is not working. I assigned value as 0 , "" but still it was not working. Please give some solution.
Thanks.
<DisplayRule Id="mcg.mcg_transition.DisplayRule_lookup.DisplayRule">
<ValueRule Field="ifx_lookupid" Value="null" Default="true" InvertResult="false" />
</DisplayRule>
Use Enable Rule as it gives the facility to write some JavaScript function.
//Check if the field value is null or not? '
//in my case the field I am checking for null value is ifx_lookupid.
function DisplayRule_IfField_IsNull()
{
var regardingField = Xrm.Page.getAttribute("ifx_lookupid");
if (regardingField != undefined && regardingField != null) {
return true;
}
else {
return false;
}
}
}
Hope this will help.

Extjs messagebox prompt limit the text input entered by user

I am using http://dev.sencha.com/playpen/docs/output/Ext.MessageBox.html#prompt to display an extjs prompt where the user can enter some text and click Ok. Now if I want to restrict the user to enter text not more than 100 characters, what should I do?
I understand I need to write some kind of an eventhandler but what is the event? Is it possible to look at a code sample?
When you invoke MessageBox.prompt it will return instance of the singleton which can be used to get dom reference of textbox element, this element can be used to specify attribute maxlength which can be used to limit length of text that can be entered
var dlg = Ext.MessageBox.prompt('Name', 'Please enter your name:', function(btn, text){
if (btn == 'ok'){
// process text value and close...
}
});
var textboxEl = dlg.getDialog().body.child('input[class=ext-mb-input]', true);
textboxEl.setAttribute('maxlength', 1); // second parameter is character length allowed so change it according to your need
Reference:
Character Limit in HTML
Updated for Ext 4 (with many thanks to SilentSakky for the original answer):
var dlg = Ext.MessageBox.prompt('Name', 'Please enter your name:', function(btn, text){
if (btn == 'ok'){
// process text value and close...
}
});
var textboxEl = dlg.getEl().query('input')[0];
textboxEl.setAttribute('maxlength', 1);

View Panel cannot locate data var rowData - not found error

I have a View Panel in a tabbed panel that has the data > var property set to rowData. I have this view set to mimic the Single Category view by using a viewScope value.
When I open a XPage and click on the tab which the view panel exists, sometimes this error pops up (line 2 in the JavaScript Code is where the error is):
Unexpected runtime error
The runtime has encountered an unexpected error.
Error source
Page Name:/speakerReq.xsp
Control Id: viewColumn2
Exception
Error while executing JavaScript computed expression
Script interpreter error, line=2, col=23: [ReferenceError] 'rowData' not found
JavaScript code
1: var href = facesContext.getExternalContext().getRequest().getContextPath();
**2: var docUNID = rowData.getDocument().getUniversalID();**
3: var formName = rowData.getDocument().getItemValueString("Form");
4: var formType = rowData.getColumnValue("Form")
5:
6: if(formName == "clientProfile") {
7: href + "/clientProfile.xsp?documentId=" + docUNID + "&action=openDocument&rtr=yes";
8: }
9: else {
10: href + "/speakerProfile.xsp?documentId=" + docUNID + "&action=openDocument&rtr=yes";
11: }
The viewColumn2 that is referenced above is a column in the view which has this formula:
#ReplaceSubstring(Form; "clientProfile" : "clientFeed" : "speakerProfile" : "speakerFeed"; "Client Profile" : "Client Feedback" : "Speaker Profile" : "Speaker Feedback")
I am not sure how that would throw the error above --- clicking on that tab on most XPages works fine.
The documents that are being displayed in the view are nothing special. I compared two of them -- one that displays and one that throws the error and I could not find any differences that would cause this problem.
I cannot determine why sometimes the error appears and sometimes not.
Any help would be great!
try to use a different variable name curRowData --- and don't forget that stuff is case sensitive. Also your code is a big fat memory leak since rowData.getDocument initializes a NotesDocument that you don't recycle.
Try to use:
var result;
if (curRowData.isCategory()) {
return "";
}
var href = facesContext.getExternalContext().getRequest().getContextPath();
try {
var doc = curRowData.getDocument();
if (doc != null) {
var docUNID = doc.getUniversalID();
var formName = doc.getItemValueString("Form");
var formType = curRowData.getColumnValue("Form")
if(formName == "clientProfile") {
result = href + "/clientProfile.xsp?documentId=" + docUNID + "&action=openDocument&rtr=yes";
} else {
result = href + "/speakerProfile.xsp?documentId=" + docUNID + "&action=openDocument&rtr=yes";
}
}
} catch (e) {
// some error handling
}
if (doc != null) {
doc.recyle();
}
return result;
Of course you would be better off just to add all values you need to the view. Saves you the need to create a NotesDocument object
Perhaps this error occurs if the view is categorized and the code hits a category and not a document. You can use the folllowing code to make sure that the current row is not a category:
if (!rowdata.isCategory()) {
// insert your code here
}
This code of course assumes that rowData is available so this might not solve your issue.
Example code can be found in the Notes & Domino Application Development wiki:
http://www-10.lotus.com/ldd/ddwiki.nsf/dx/notesxspviewentry_sample_javascript_code_for_xpages#isCategory+isDocument+isTotal
Please add a description of the XML declaring the control.
I have myself gotten this error and it was because I computed the column in a wrong way; "Computed" vs JavaScript I think it was…

Resources