On my xpages I have an inputfield:
<xp:inputText id="inputPassExpiryDate"
value="#{customerBean.customer.dateValidPass}"
disabled="#{!customerBean.customer.editMode}"
validator="#{customerValidators.validPassDate}">
</xp:inputText>
I enable a datapicker plugin (https://github.com/eternicode/bootstrap-datepicker) for the inputfield with the following script:
<xp:scriptBlock>
xp:this.value><![CDATA[$(document).ready(function(){
reloadDP();
var dateFormat = "#{javascript: application['date_only']}";
x$('#{id:inputPassExpiryDate}').datepicker({
language: getUserLanguage(),
format:(dateFormat),
weekStart: 1,
todayBtn: true,
clearBtn: true,
daysOfWeekHighlighted: "0,6",
calendarWeeks: true,
autoclose: true,
todayHighlight: true
}).on('changeDate', doSomething);
}
)
function doSomething(){
var from = x$('#{id:inputPassExpiryDate}').val().split("-")
var DateInput = new Date(from[0], from[1] - 1, from[2])
var DateNow = new Date();
if (DateInput <= DateNow) {
x$('#{id:inputPassExpiryDate}').addClass("invalid");
x$('#{id:pnlExpiredReason}').removeClass("hidden");
}else{
x$('#{id:inputPassExpiryDate}').removeClass("invalid");
x$('#{id:pnlExpiredReason}').addClass("hidden");
}
}
I notice that a change in date is only set in the web client.
In element 'pnlExpiredReason' I have an textarea control which I would like to validate when submitting to the server ONLY when inputPassExpiryDate has a date that is older than the current date.
But I notice that the changed value for inputPassExpiryDate is not changed when I submit the xpage to the server and validation starts. It simply has the same value as it has before I changed value with the date picker.
So my question is how can I update the value for the inputfield (server-side) when I have changed the value via the date-picker (client-side) ?
getComponent("inputPassExpiryDate").getValue()
will return the value that the date-pciker had when the xpage was loaded, not after update via the date-picker.
Related
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;
}
Thanks to #DChhapgar for help me figure out how to add "draft email" activity in opportunity, however, when I was trying to run my code I created following #DChhapgar instruction, I got error as follows:
Error #13: Inserting 'Activity' record raised one or more errors. Please review. Error: 'From' may not be empty
My code is as below:
CR304000Content CR304000 = context.CR304000GetSchema();
context.CR304000Clear();
//Email Activity Screen
CR306015Content CR306015 = context.CR306015GetSchema();
context.CR306015Clear();
//Locate Opportunity for which Email Draft needs to be added
CR304000Content[] CR304000result = context.CR304000Submit(
new Command[]
{
new Value { Value = opportunity.ID, LinkedCommand = CR304000.OpportunitySummary.OpportunityID},
//Invoke New Email Actity Action
CR304000.Actions.NewMailActivity
});
//Specify data for Email Activity
if (!string.IsNullOrWhiteSpace(email.Subject))
{
CR306015Content[] CR306015result = context.CR306015Submit(
new Command[]
{
new Value { Value = "abcd#efg.com", LinkedCommand = CR306015.Message.FromMailAccountID},
new Value { Value = email.ToAddress, LinkedCommand = CR306015.Message.To},
new Value { Value = email.Subject, LinkedCommand = CR306015.Message.Subject },
new Value { Value = email.Message, LinkedCommand = CR306015.Message_.ActivityDetails},
CR306015.Actions.Save,
});
}
I saw there were totally three fields related to email "from" in web service specification: CR306015.Message.FromMailAccountID, CR306015.Message.FromEmailAccountID, CR306015.Message.FromMailFrom, however neither of them worked for me.
Am I missing something?
I'm guessing FromMailAccountID needs to be an integer. Look at what the values are for existing records.
I have customized the inotes,as I wanted to add a button in "mailread",I mean inside the toolbar when the user opens the mail.as shown in image.
The fuctionality behind the this button is I wanted to go to other window with specified or hard Coded database name to open in othe window.
The code in Custom_js_Lite
code:
function Custom_Scene_Actions_Lite(s_MenuID)
{
if (-1 == s_MenuID.indexOf("mailread"))
return false;
// Add the button
var add1 = [{title:"custom-button", find_id: "print",class:"test", id: "sync", before: false,
action:"openDatabase{}", help_text:"custom-button" }];
addActionsLite( s_MenuID, true, add1);
}
// Calling function onclick.
function openDatabase(){
var unids = API_GetSelectedDocs_Lite();
var server = location.host;
var temp = location.pathname.substr(1, location.pathname.length);
var pos = temp.toLowerCase().indexOf(".nsf");
var database = temp.substr(0, pos + 4);
window.open("http://localhost/example.nsf/home.xsp?server="+server+"&db="+database+"&mailDocId="+unids);
In above code window.open, Opens the given link with selected unids which is getting from "API_GetSelectedDocs_Lite();" but the database name is hard coded that is "example.nsf";
So Instead of hardcoding the database name,I am just wondering to save the database name once profile document of that curent user's mail database, So it would help me get the database name from profile document to open it according.
I am not sure,If I can retrieve the the profile document field in subforms, custom inotes.
I need some idea how to retrieve the profile document in mail database with custom_js_lite.
Or i would really like to know if there is any other way to acheive this.
I got the solution for this.
I have just retrieved the profile document named "iNotesProfile" and add the new field in it "db_name" from my xpage button the code to update it profile document is:
var currdb:NotesDatabase = session.getDatabase(session.getServerName(),"mail/abc.nsf");
var doc:NotesDocument = currdb.getProfileDocument("iNotesProfile", "");
doc.replaceItemValue("db_name",database.getFileName());
doc.save();
This script edits the "iNotesProfile" profile document of the current user and sets the current database name inside the "db_name" field. Now we have set the database base in document which can be used from the mail database.
Now the task is to get the database name on click of custom-button.In Custom_js_Lite the code is:
function Custom_Scene_Actions_Lite(s_MenuID)
{
if (-1 == s_MenuID.indexOf("mailread"))
return false;
// Add the button //
var add1 = [{title:"custom-button", find_id: "print",class:"test", id: "sync", before: false,
action:"openDatabase{}", help_text:"custom-button" }];
addActionsLite( s_MenuID, true, add1);
}
function openDatabase(){
var unids = API_GetSelectedDocs_Lite();
var server = location.host;
var temp = location.pathname.substr(1, location.pathname.length);
var pos = temp.toLowerCase().indexOf(".nsf");
var database = temp.substr(0, pos + 4);
var mailFilePath = API_GetMailfilePath_Lite();
var db_name = '#{{#GetProfileField("iNotesProfile";"db_name")};jsData}';
if(db_name == ""){
alert("Database is not configured! Contact Administrator.");
}else{
window.open("http://localhost/"+db_name+"/home.xsp?server="+server+"&db="+database+"&mailDocId="+unids);
}
So we are now able to find the database name which is stored in iNotesProfile document by #{{#GetProfileField("iNotesProfile";"db_name")};jsData} and can be use it to go to that database.
Using the latest version of Acumatica 5 with the latest and greatest updates, I’m running into a Web API issue that I have not been able to solve. I have code to execute the “Extend To Vendor” action on the Customer screen. It seems to run fine and does not error out but it fails to create the vendor. It seems to me that when performing the same actions through the website interface, the issue is that I’m not sending the correct command to choose the “Yes” button on the popup Warning box “Please confirm if you want to update current Vendor settings with the Vendor Class defaults. Original settings will be perserved otherwise.” I could be totally off though and any help would be greatly appreciated.
Here is my code:
String customerId = "SomeCustomerId";
String vendorClass = “SomeVendorClass”;
AcumaticaApiWS.AR303000Content AR303000 = context.AR303000GetSchema();
AcumaticaApiWS.AP303000Content AP303000 = context.AP303000GetSchema();
context.AR303000Clear();
AR303000.Actions.ExtendToVendor.Commit = true;
AcumaticaApiWS.AR303000Content[] AR303000result = context.AR303000Submit
(
new AcumaticaApiWS.Command[]
{
new AcumaticaApiWS.Value { Value = customerId, LinkedCommand = AR303000.CustomerSummary.CustomerID },
AR303000.Actions.ExtendToVendor
}
);
AcumaticaApiWS.AP303000Content[] AP303000result = context.AP303000Submit
(
new AcumaticaApiWS.Command[]
{
new AcumaticaApiWS.Value { Value = vendorClass, LinkedCommand = AP303000.GeneralInfoFinancialSettings.VendorClass },
new AcumaticaApiWS.Value { Value = "YES", LinkedCommand = AP303000.GeneralInfoFinancialSettings.ServiceCommands.DialogAnswer, Commit = true },
AP303000.Actions.Save
}
);
Thanks!
You're almost there. This is not an easy scenario since it involves multiple screens and dialogs, two things which are not trivial to use. The issues in your code sample are:
The dialog answer has to be set before the value. In your case, you're setting the vendor class first. This is counter-intuitive but the system has to know it before the dialog is displayed
The dialog answer is "Yes", and not "YES". You can see this by using the web browser inspector window and looking at the button title. The text is displayed in uppercase due to CSS styling.
You need to set the dialog answer on the primary view of the form (AP303000.VendorSummary.ServiceCommands.DialogAnswer), where the dialog is being displayed. There's no way to know this without looking at the source code, but I believe this is generally the case with dialog boxes.
The different Commit = true settings are not necessary (but don't hurt in this case).
This is the code I used, and in my case it extends a customer to a vendor and changes the vendor class at the same time:
String customerId = "ACTIVESTAF";
String vendorClass = "DATACENTER";
AcumaticaApiWS.AR303000Content AR303000 = context.AR303000GetSchema();
AcumaticaApiWS.AP303000Content AP303000 = context.AP303000GetSchema();
context.AR303000Clear();
AcumaticaApiWS.AR303000Content[] AR303000result = context.AR303000Submit
(
new AcumaticaApiWS.Command[]
{
new AcumaticaApiWS.Value { Value = customerId, LinkedCommand = AR303000.CustomerSummary.CustomerID },
AR303000.Actions.ExtendToVendor
}
);
AcumaticaApiWS.AP303000Content[] AP303000result = context.AP303000Submit
(
new AcumaticaApiWS.Command[]
{
new AcumaticaApiWS.Value { Value = "Yes", LinkedCommand = AP303000.VendorSummary.ServiceCommands.DialogAnswer },
new AcumaticaApiWS.Value { Value = vendorClass, LinkedCommand = AP303000.GeneralInfoFinancialSettings.VendorClass },
AP303000.Actions.Save
}
);
Could you please suggest me any Phonegap DateTime Picker plugin that is compatible with platforms Android,Ios and Windows Phones?
We have number of plugins avail for datepicker, As I tried this already, I would recommend you to follow below steps to make it work,
Step 1: Run the following command
cordova plugin add https://github.com/mrfoh/cordova-datepicker-plugin
Step 2: Handle the click
$('.nativedatepicker').focus(function(event) {
var currentField = $(this);
var myNewDate = Date.parse(currentField.val()) || new Date();
// Same handling for iPhone and Android
window.plugins.datePicker.show({
date : myNewDate,
mode : 'date', // date or time or blank for both
allowOldDates : true
}, function(returnDate) {
var newDate = new Date(returnDate);
currentField.val(newDate.toString("dd/MMM/yyyy"));
// This fixes the problem you mention at the bottom of this script with it not working a second/third time around, because it is in focus.
currentField.blur();
});
});
$('.nativetimepicker').focus(function(event) {
var currentField = $(this);
var time = currentField.val();
var myNewTime = new Date();
myNewTime.setHours(time.substr(0, 2));
myNewTime.setMinutes(time.substr(3, 2));
// Same handling for iPhone and Android
plugins.datePicker.show({
date : myNewTime,
mode : 'time', // date or time or blank for both
allowOldDates : true
}, function(returnDate) {
// returnDate is generated by .toLocaleString() in Java so it will be relative to the current time zone
var newDate = new Date(returnDate);
currentField.val(newDate.toString("HH:mm"));
currentField.blur();
});
});
Step 3: You may need to convert the result of date.parse() back to an object to get the picker to work a second or third time around. If so, try inserting this code after the myNewDate declaration:
if(typeof myNewDate === "number"){ myNewDate = new Date (myNewDate); }