I'm accustomed to Windows Forms, but the standard MessageBox.Show() is not available in ASP.NET project. Can this be done in an ASP.NET WebForm project?
Say I have a couple of routines:
DatabaseRoutine();
GotoAnotherPageRoutine();
The DatabaseRoutine() makes a call to the database and has a TRY/CATCH block:
public void DatabaseRoutine()
{
try {
// code here that may fail
} catch (Exception error)
{
var scriptManager = Page.ClientScript;
var cstype = this.GetType();
var csname1 = "DatabaseRoutine";
if (!scriptManager.IsStartupScriptRegistered(cstype, csname1)) {
var script = String.Format("<script runat=\"server\">alert('{0}: {1}');</script>", csname1, message);
scriptManager.RegisterStartupScript(cstype, csname1, script, true);
}
}
}
The catch routine above would be extracted to an error handling method that could be called by other sections of the code that could have errors.
The issue currently is that the next routine GotoAnotherPageRoutine() is going to be called immediately after the ScriptManager calls the Javascript Alert, so it will not ever be displayed to the end-user.
What else is at our disposal to display a message to the end-user?
Adding the redirect URL to the Alert box is not recommended for a couple of reasons (the redirect is not always the same and the redirects are often nested in other decision-making tasks based on the database entries).
Maybe can you try with something like this
try {
DatabaseRoutine();
GotoAnotherPageRoutine();
} catch (Exception ex) { ShowModalError() ... }
public void DatabaseRoutine()
{
.. do some stuff without any try catch
}
or
try {
DatabaseRoutine();
GotoAnotherPageRoutine();
} catch (Exception ex) { ShowModalError() ... }
public void DatabaseRoutine()
{
try {
.. do some stuff
}
catch (Execpetion ex)
{
..log exception on db ..
throw ex // rethrow exception
}
}
for a better popup you can use ajaxcontroltoolkit and modalpopupextender control
So, can you setup and have text for the prompt from code behind (server side)?
Yes, you can. But you have to keep SEVERAL things in mind as to how this can (or will work).
First up, like humans breathing air? Well, the most important concept here is to keep in mind how a asp.net page "life cycle" works. Without just a BIT of considering of this issue, then most attempts at this will fail.
The next issue - and a HUGE one?
most web page code (client side) has now forced upon developers to NOT be allowed to write what we call blocking code. In other words, if you say popup a ajax popup, or a jQuery popup? They do NOT cause the code to HALT.
About the ONLY blocking option left in browsers of course is the JavaScript alert(), and of js prompt(); Both of these DO BLOCK (halt code), but after that? Then you have to wire up EXTRA code that runs WHEN the user hits ok, or cancel.
So, for REALLY quick and dirty? Say drop a asp.net button to delete somthing on a form.
With this :
<asp:Button ID="btnDialogTest"
OnClientClick="return askdelete();"
runat="server" Height="36px" Text="Prompt test" Width="100px" />
<script>
function askdelete() {
return confirm('delete this');
}
</script>
So, above will pop a dialog. And if the user hits cancel, then the button event code will not run. Above is REALLY short - and MUCH less then wireing up ajax toolkit dialog for a SUPER simple yes/no prompt.
And yes, I even use jQuery toast messages with text from the server. But lets stick to our goal here.
So, what about our server side prompt yes/no idea?
The most simple approach of course is thus to use option 1 or 2 above (alert() or prompt()). Since those two buttons DO BLOCK code, then we can do this for a prompt:
(but no server side supply of text).
If the user clicks ok, then our button code runs. If they click cancel, then the server side event code stub does NOT run.
However, the above would not get us server side supply of text.
So, how could we supply server side text, and then run code based on that choice?
Well, we could drop in this script function into the given page:
Well, say I have this server side button code:
Protected Sub btnServerCode_Click(sender As Object, e As EventArgs) Handles btnServerCode.Click
Dim sTitle As String = "This is a server side TITLE suppled prompt text"
Dim sOkButton As String = "btnOk"
Dim sCancelButton As String = "btnCancel"
Dim sBody As String = "this is SERVER text in the box"
Call MyDialog2("popdialog2", sTitle, sBody, sOkButton, sCancelButton)
End Sub
so, we dropped 3 buttons onto the form, we thus have this:
So, when I run the code, I get this:
So some suggests and tricks as to how the above works.
I dropped 3 buttons. The first button was the simple event - code behind that run above code.
I THEN dropped two more buttons. The "ok" one, and the "cancel" one.
So, we can't BLOCK the code or HALT the code in the server side code.
I mean, the user clicks a button - the web page travels up to server, THEN code behind runs, and THEN the page makes the trip down back to the browser, and THEN our dialog box displays. So this round trip process is important.
As for the dialog? Well in this case I used jQuery.UI.
You CAN do much the same if you want to use the ajaxtoolkit and their dialogs box. Both quite much can do the same thing. About the only difference is that the ajax ones tend to allow you to write LESS js. However, while I did use the ajaxtoolkit dialogs, I found the jQuery.ui ones better. And ONE BIG reason is that you can have the jQuery.ui dialog LOAD a whole new other pages for the content of the dialog. It is quite easy.
Note also how I included a text box, and a check box. When your button "ok" or "cancel" code runs, you have full use (code behind) of the values the user entered into that text box, and also full use of the value of the check box. Now one could just dump/drop/not have the check box and the text box - I just included them to so this is possible.
And just like the ajax toolkit, the idea here is you create a "div" with the popup content, and of course set style=none to hide.
So, the popup div specified in above - in the same web page looks like this:
<div id="popdialog2" runat="server" style="display:none">
<h2 id="popdialog2body" runat="server">My cool pop dialog</h2>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<br />
<asp:CheckBox ID="CheckBox1" runat="server" Text="A nice check box" />
</div>
Note how I put runat server tags - I wanted to be able to "replace" or "set" the "my cool pop dialog" text with anything else in the "h2" (larger heading) part.
Also, to save a LOT of work to wire up the events? Well as noted, I drop two plane jane asp buttons on the form. I then double click on the button, and thus write/wire up the code I want. For this sample, I had/have this:
Protected Sub btnOk_Click(sender As Object, e As EventArgs) Handles btnOk.Click
Debug.Print("ok button click")
End Sub
Protected Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
Debug.Print("cancel button click")
End Sub
And of course, often we might not want cancel. I could of course just do a js postback and pass up some values to be caught in the page-load event. But by dropping in buttons for what we want to occur for ok, or cancel, then we are quite much free (with greater ease) to wire up two events (one for ok, and the other for cancel).
Of course once I have those two buttons code working? Well, of course I don't need to display them - the dialog box "trick" I use here is to have the popped dialog box execute the "click" method of either button. So, in theory, then I should/would/could/will hide those two buttons with style=dispaly:none.
So, now our page has just this:
<asp:Button ID="btnServerCode" runat="server" Text="Server Prompt" />
<br />
<asp:Button ID="btnOk" runat="server" Text="Ok" Width="63px" ClientIDMode="Static"
style="display:none"/>
<asp:Button ID="btnCancel" runat="server" Text="Cancel" ClientIDMode="Static"
style="display:none" />
<br />
so that button "click" trick saves a LOT of js and having to wire up a event for the ok button, and the cancel button.
Note also that I did/do use clientIDMode=static. This just allows getElementById, or in this case the jQuery selector to with ease to pick up the specified control. If you don't, then you have to tweak the $ selector code in above.
The jScript routine I use is this:
function myaskcool(myDiv, sPrompt, sOk, sCancel) {
var mydiv = $(myDiv);
mydiv.dialog({
autoOpen: false, modal: true, title: sPrompt, width: '25%',
position: { my: 'top', at: 'top+150' },
buttons: {
'ok': function () {
vbtn = $(sOk);
vbtn.click();
},
'cancel': function () {
vbtn = $(sCancel);
vbtn.click();
}
}
});
// Open the dialog
mydiv.dialog('open');
}
So the above needs jQuery, and also needs jQuery.ui.
As noted, you could change the above to work with the toolkit dialogs. (you can pop a toolkit dialog with js - and I recommend you do this - Edit: what I mean here is to NOT use the options in toolkit to automatic pop the dialog based on a associated control - but just use a wee bit of js to pop that toolkit dialog).
A few more things:
The dialog is actually dismissed DUE TO THE POST BACK. If you going to run client side code as a result of the dialog, then BOTH the ok, and the cancel js has to dismiss the dialog. But, since we do a post back on either choice - then the dialog is dismissed for you.
In summary:
I do recommend jQuery.ui (and jQuery) for the dialogs.
You can consider the ajaxtool kit dialog (both jQuery.ui and toolkit do operate on a "div" that you place in the page.
I do suggest the button trick.
you can't HALT code to wait for a dialog. So of course our super long time coding habit of:
if msgbox("do you want to delete") = vb.ok then
bla bla bla
Now has to be broken up into two (or 3 if you want cancel code)
Thus:
code will pop the dialog
user ok = run some button stub code - button clicked by js
user cancel = run some button stub code - button clicked by js
So, we wind up in place of that loveable and simple msgbox command?
Well, you now have to write at least one more event stub for the ok.
But, by using the "click()" method trick above, then we at least don't have to wire up complex ajax calls, and we get a button click event (and nice code behind stub) to run for the above approach.
Also keep in mind that when we inject the js into the web page, it BETTER be in most cases the LAST code that runs in the code behind - so right before the sub exit.
So our LAST routine is this one:
Dim sTitle As String = "This is a server side TITLE suppled prompt text"
Dim sOkButton As String = "btnOk"
Dim sCancelButton As String = "btnCancel"
Dim sBody As String = "this is SERVER text in the box"
Call MyDialog2("popdialog2", sTitle, sBody, sOkButton, sCancelButton)
And call MyDialog2 is the code that "injects" the js to then call our script above in the page:
That code is thus this:
Sub MyDialog2(sDiv As String, sTitle As String, sBody As String, sOk As String, sCancel As String)
Me.popdialog2body.InnerText = sBody
Dim jScript = "myaskcool('##Div','#Title','##Ok','##Cancel');"
jScript = jScript.Replace("#Div", sDiv)
jScript = jScript.Replace("#Title", sTitle)
jScript = jScript.Replace("#Ok", sOk)
jScript = jScript.Replace("#Cancel", sCancel)
ScriptManager.RegisterStartupScript(Me.Page, Me.GetType(), "mycoolasker", jScript, True)
End Sub
Now of course, we could add to above routine the js "myaskcool" to above.
This would then mean we don't have to bother "adding" that myaskcool() js routine to each page.
As noted, above makes use of jQuery AND ALSO jQuery.UI for the dialog prompt.
And as noted, in that hidden div, you can add check box, text box or whatever. Since the ok or cancel does a post back (the click() trick), then all of the values inside that div are 100% able to be freely used by the code behind. So, check box, text box, combo box, or whaterver can be dropped into that dialog.
ONE BIG rule however:
You can't have those controls inside of that dialog do a postback. Well, ok you can, but such postbacks WILL dismiss the dialog. But, say in the case of a dropdown, radio button list, or whatever? Often if you set auto-postback "true", then it often rather nice to just popup that dialog - let the user select the combo box, and BECUASE the dropdown/combo has auto-post back, then you don't care about the ok, cancel buttons - but just want a user selection and the "all easy" important post-back + code behind stub for that control to run. So you can have post backs in the "div" controls - but just keep in mind if you do that - then the dialog will be dismissed.
For now, I have found a way to insert the System.Windows.Forms.MessageBox.
public void DebugLogHandler(String module, String method, String message) {
if (!String.IsNullOrEmpty(message)) {
var lc = message.ToLower();
if (-1 < lc.IndexOf("error")) {
var scriptManager = Page.ClientScript;
var cstype = this.GetType();
var csname1 = String.Format("{0}.{1}", module, method);
if (MessageBox.Show(message, csname1, MessageBoxButtons.OK) != DialogResult.OK) {
if (!scriptManager.IsStartupScriptRegistered(cstype, csname1)) {
var script = String.Format("<script runat=\"server\">alert('{0}: {1}');</script>", csname1, message);
scriptManager.RegisterStartupScript(cstype, csname1, script, true);
}
}
}
}
}
If anyone comes up with something better, please post up.
Here is the hack I did, and it works!
In the Business Objects solution of my project, I created a Message Handling delegate and put an instance of that delegate in my class:
namespace BusinessObjects.Utilities
{
public delegate void MessageHandler(String module, String method, String message);
public class ExtensionLogHelper
{
public static MessageHandler OnMessage;
public static void LogDetails(Guid extensionLogGuid, bool IsSuccess, string logDetails)
{
// ...
// ... other code that logs to the database here
// ...
if (OnMessage != null) {
if (!String.IsNullOrEmpty(logDetails)) {
var logGuid = String.Format("{0}", extensionLogGuid);
OnMessage(logGuid, "BusinessObjects.Utilities.AddExtensionLogDetails", logDetails);
}
}
}
}
}
The methods are static, so as long as the OnMessage handler is set, messages will pump across.
In the Master.Page code-behind, I added:
a static instance of my Master.Page,
a static System.Collections.Queue,
assigned the MessageHandler OnMessage to my static Instance,
created a method to add new items to the Queue, and
created a way to display those messages.
Here are the basic requirements:
namespace Web.Master
{
public partial class MainLayout : System.Web.UI.MasterPage
{
public static MainLayout Instance;
private static Queue<PopMessage> queue;
protected void Page_Load(object sender, EventArgs e)
{
if (Instance == null) {
Instance = (MainLayout)Page.Master;
// a bug here. It only seems to fire once, not if the page is refreshed
Page.LoadComplete += new EventHandler(Page_LoadComplete);
// this is where the Master.Page is linked to the Debug Logger:
BusinessObjects.Utilities.ExtensionLogHelper.OnMessage = Instance.DebugLogHandler;
if (queue == null) {
queue = new Queue<PopMessage>();
}
}
// manually call this until I can get the Page.LoadComplete to fire it.
ProcessQueue();
}
As soon as I can get my Page.LoadComplete to set and fire consistently, I'll remove that last line of the Page_Load event. For details about that issue, I have it as a current question here:
Why does Page.LoadComplete throw HttpUnhandledException?
This is the public event that is called by my static Master.Page Instance:
public void DebugLogHandler(String module, String method, String message) {
queue.Enqueue(new PopMessage() {
Heading = module, MoreInfo = method, Details = message
});
}
protected void Page_LoadComplete(object sender, EventArgs e) {
ProcessQueue();
}
// remove messages from the queue, count any errors, and display to User
private void ProcessQueue() {
var errors = 0;
PopMessage msg = null;
do {
if (queue.Dequeue(ref msg)) {
if (msg.IsError) {
errors++;
}
}
} while (msg != null);
if (0 < errors) {
var responseMsg = String.Format("<script language='javascript'>alert('There were {0} error(s). Go to [Settings] > [System] > [Logs] for details.')</script>", errors);
Response.Write(responseMsg);
}
}
This is the class I use to save messages in my Queue:
class PopMessage {
public PopMessage() { }
public String Heading { get; set; }
public String MoreInfo { get; set; }
public String Details { get; set; }
public bool IsError
{
get
{
if (!String.IsNullOrEmpty(Details)) {
var lc = Details.ToLower();
if (-1 < lc.IndexOf("error")) {
return true;
}
}
return false;
}
}
public override string ToString() {
var result = IsError ? "Error: " : String.Empty;
if (!String.IsNullOrEmpty(Heading)) {
result += Heading;
} else {
result += "No Heading";
}
return result;
}
}
}
}
I can call several routines, load DataGrids, edit items in the GridViewRows, send all log messages to the Master.Page, and they can be handled as the last method of the Page_Load event.
This may not be the best architecture, but it provides a solution to let the customer know that errors exist without having to redesign a 10-year-old website.
I have a form in my jsp wherein I enter a value. This is then inserted into a table on my database. However, I would like to ask the user first to confirm his submission. I used this:
function askConfirmation() {
var confirmSubmission = confirm("Do you wish to add this entry?");
if(confirmSubmission) {
return true;
} else {
return false;
}
}
Although this does the task of suspending submission, it's not quite what I had in mind. I tried using a modal but I don't know how to get the values I used from my EL and place it in the modal after the button click. How do I do this?
I am not quite sure how you have your form inputs setup, but you can pass an object representing all your form inputs as an argument into askConfirmation() function and then pass that to confirm(). This will display to the user all the information in the form. Eg.
function askConfirmation(formInput) {
var confirmSubmission = confirm(formInput);
if(confirmSubmission) {
return true;
} else {
return false;
}
}
So in this way, you can access members/fields in the object and format them accordingly. You can also use jquery dialog() function to achieve this if you don't like the lnf of the window. The bottomline is, just pass the object that represents your inputs value into whatever that is used in displaying to the user for further confirmation. Hope this helps!
As Felipe T mentioned your values are already rendered you just need to get them with javascript here's an example using bootstrap modal https://jsfiddle.net/tf021so9/6/
-
However, I prefer using a confirmation dialog plugin in such cases like this one :https://myclabs.github.io/jquery.confirm/
-
So I am trying to add a button to the Sales Order form in netsuite that validates certain fields based on what you entered in previous fields. I am having trouble testing and debugging this in google chrome in netsuite. First, here is my code: I am adding the button that calls this function within the client script record.
function vsoeValidate(){
var calc = nlapiGetFieldValue('custbody_cv_vsoe_calculation');
calc = nlapiGetFieldValue('custbody_cv_renewal_rev_amount') - (nlapiGetFieldValue('custbody_cv_vsoe_cola') * nlapiGetFieldValue(1-'custbody_cv_vsoe_partner_disc')) - (nlapiGetFieldValue('custbody_cv_vsoe_bts_fees') * (1-nlapiGetFieldValue('custbody_cv_vsoe_partner_disc'))) /
(nlapiGetFieldValue('custbody_cv_vsoe_software_amt') * (1- nlapiGetFieldValue('custbody_cv_vsoe_multiyear_disc')));
nlapiSetFieldValue('custbody_cv_vsoe_calculation', calc);
var display = nlapiGetFieldValue('custbody_cv_vsoe_calculation_disp');
var bucket = nlapiGetFieldValue('custbody_cv_vsoe_bucket');
if(bucket === 'X'){
return false;
}
if(calc > (nlapiGetFieldValue('custbody_cv_vsoe_bucket.custrecord_cv_vsoe_maintenance_rate') *1.15) || calc < ('custbody_cv_vsoe_bucket.custrecord_cv_vsoe_maintenance_rate'*0.85)){
display = '<div style="; background-color:red; color:white;font-weight:bold;text-align:center">Out of bounds</div>';
return true;
}
else{
display = '<div style="; background-color:green; color:white;font-weight:bold;text-align:center">In bounds</div>';
return true;
}
}
when I click the button I get the error TypeError undefined is not a function.
I am really not sure where to go from here, is it because the logic inside vsoeValidate is not right or am I using the wrong type of function? Any help would be great thank you!
Update: here is the screenshot of my script record!
Try passing the function name as string i.e.
form.addButton('custpage_validatevsoe', 'Validate VSOE', 'vsoeValidate');
You mentioned that you set vsoeValidate as a validateField function. Do you want this function to run when users click the button or when NetSuite's valdiateField event is fired (upon field change, before the value is stored)?
If you want this to run on NetSuite's validateField event, then the function must return true or false; it cannot return void. Right now in your logic, you have:
if (bucket = 'x') {
return;
}
if (bucket = 'x') is an assignment operation, not an equality check. This assignment operation will return 'x', which is a truthy value, so your code will enter that if-block. You then return void (undefined), so my guess is that NetSuite is trying to do something with the result returned by your function but cannot because it returned undefined.
The validateField function also gets passed a parameter that provides the ID of the field being validated.
You will also want to inject some console logging at various points so you can figure out where your script is failing instead of just trying to guess at reading syntax.
Can you provide us with a screenshot of your Script record setup?
Also since you are using a client side script, you don't need to use the pageInit event for adding a custom button.
There is a 'Buttons' subtab, under the 'Scripts' tab when you create the Script record in NetSuite. This subtab is next to the 'Libraries' subtab.
There are two columns here, 'Label' and 'Function'.
So in your case, you can just put 'Validate VSOE' in the Label field and vsoeValidate in the Function field.
Please note that if you do it this way, the button will only be shown when you are creating or editing a record.
I have very basic knowledge about JS/jQuery. I need to perform check on the value of certain text boxes. The example just recreates the problem I heave with the real application which is a lot bigger and the tables are dynamically created based on a data from a data base, so in run time I add the classes on which I base my jQuery logic.
Here is the jsfiddle example - http://jsfiddle.net/Xhnbm/
There are three different checks I need to do - for float, for string length and for float, however you may see that the validations is not performed I always get the integer exception and even if you remove the integer check the validation is not working either, so I guess the problem is not in the functions themselves but somewhere else.
Thanks for help.
P.S
It seem I can't submit the question without adding code. All the code is in the jsfiddle example but since I need to add some here too, I think that the problem is either in the way I declare may functions that perform the check or here :
$('#submitDocument').click(function () {
try {
if ($(".checkString16").val().length > 16) {
throw "The text can be up to 16 symbols";
} else if (!mathFunctions.isInt($(".checkULong").val())) {
throw "Insert integer";
} else if (!mathFunctions.isFloat($(".checkFloat").val())) {
throw "Insert float";
}
validationResult = true;
} catch (exc) {
alert(exc)
validationResult = false;
}
return validationResult;
});
in the way I try to execute the validation when the submit button is clicked. But being no Js programmer at all I don't want to point you to wrong directions.
$('#submitDocument').click(function () {
var validationResult = true;
if ($(".checkString16 input[type='text']:first").val().length > 16) {
validationResult=false;
} else if (!mathFunctions.isInt($(".checkULong input[type='text']:first").val())) {
validationResult=false;
} else if (!mathFunctions.isFloat($(".checkFloat input[type='text']:first").val())) {
validationResult=false;
}
return validationResult;
});
This should do the trick.
If the #submitDocument is a input type='submit' and you use it to submit the form, you should try this way:
$('#submitDocument').click(function (e) {
if ($(".checkString16 input[type='text']:first").val().length > 16) {
e.preventDefault();
} else if (!mathFunctions.isInt($(".checkULong input[type='text']:first").val())) {
e.preventDefault();
} else if (!mathFunctions.isFloat($(".checkFloat input[type='text']:first").val())) {
e.preventDefault();
}
});
The e.preventDefault() will prevent the submit button from doing it default handler, which is submitting the form.
You can always submit the form manually from the code, using $("#formId").submit();
PS. Make sure that you are also validating those values in code behind, because simple jquery validation is easy to come around.
I am trying to implement JavaScript in header of page of Oracle APEX application.
Fields in the form by default are going to be disabled if customer data exists but it can be trigger to edit mode by clicking on button 'Unlock'. By clicking button EnableItems() is run, but form is not resubmitted it is just js function that run.
function DisableItems()
{
$x_disableItem('P31_TITLE',true);
}
function EnableItems()
{
$x_disableItem('P31_TITLE',false);
}
If form is empty then all fields should be available to edit.
In Javascript >> Execute when Page Loads
I have
PageStart();
Now I need third piece of code so page would know if I want to load Enable or Disable mode. To do that I have
function PageStart(){
if ($x('P31_TEST2').value == "") {
EnableItems();
}
else {
DisableItems();
}
}
The difficulty is in second line of this code where I need to put some flag to assign value to a field or gather value from Apex field which would trigger either first or second function however I am not quite sure what would be the best practice to go around it. Any thoughts highly appreciated.
P31_START_ENABLED: hidden item, value protected = No. Provide the starting value.
For example, here the value is either 'Y' or 'N' to indicate enabled Y/N
function PageStart(){
if($v("P31_START_ENABLED")=='Y') {
EnableItems();
} else {
DisableItems();
};
};
function DisableItems()
{
$s("P31_START_ENABLED", 'N');
$x_disableItem('P31_TITLE',true);
};
function EnableItems()
{
$s("P31_START_ENABLED", 'Y');
$x_disableItem('P31_TITLE',false);
};