cannot choose options confirm with bootbox - bootbox

i have a button that i use to delete records
every time bootbox shows the confirm its closes automatically
here in the example the "cancel" button does not word
where is the mistake?
function ConfermaCancella()
{
// e.preventDefault();
bootbox.confirm("Sure to delete?", function (result) {
if (result) {
return true;
} else {
return false;
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="http://bootboxjs.com/bootbox.js"></script>
<input type="button" onclick = "return ConfermaCancella();" ID="ImageButton3" value="Delete" />

As noted in the documentation:
All Bootstrap modals, unlike native alerts, confirms, or prompts,
generate non-blocking events. Because of this limitation, code that
should not be evaluated until a user has dismissed your dialog should
be placed (or called) within the callback function of the dialog.
So, if you want something to happen only if the user confirms the action, you need to move your code into a callback, like so:
function ConfermaCancella(){
bootbox.confirm('Confirm delete?', function(result){
/* 'result' is a truthy value */
if(result){
/* Do your delete action, probably using AJAX actions */
}
});
return false;
}

Related

How can I safely manipulate DOM in a StencilJS component?

I'm trying to safely remove a DOM node from a component made whit StencilJS.
I've put the removing code in a public method - It's what I need.
But, depending on which moment this method is called, I have a problem. If it is called too early, it don't have the DOM node reference yet - it's undefined.
The code below shows the component code (using StencilJS) and the HTML page.
Calling alert.dismiss() in page script is problematic. Calling the same method clicking the button works fine.
There is a safe way to do this remove()? Do StencilJS provide some resource, something I should test or I should wait?
import {
Component,
Element,
h,
Method
} from '#stencil/core';
#Component({
tag: 'my-alert',
scoped: true
})
export class Alert {
// Reference to dismiss button
dismissButton: HTMLButtonElement;
/**
* StencilJS lifecycle methods
*/
componentDidLoad() {
// Dismiss button click handler
this.dismissButton.addEventListener('click', () => this.dismiss());
}
// If this method is called from "click" event (handler above), everything is ok.
// If it is called from a script executed on the page, this.dismissButton may be undefined.
#Method()
async dismiss() {
// Remove button from DOM
// ** But this.dismissButton is undefined before `render` **
this.dismissButton.remove();
}
render() {
return (
<div>
<slot/>
<button ref={el => this.dismissButton = el as HTMLButtonElement} >
Dismiss
</button>
</div>
);
}
}
<!DOCTYPE html>
<html lang="pt-br">
<head>
<title>App</title>
</head>
<body>
<my-alert>Can be dismissed.</my-alert>
<script type="module">
import { defineCustomElements } from './node_modules/my-alert/alert.js';
defineCustomElements();
(async () => {
await customElements.whenDefined('my-alert');
let alert = document.querySelector('my-alert');
// ** Throw an error, because `this.dismissButton`
// is undefined at this moment.
await alert.dismiss();
})();
</script>
</body>
</html>
There are multiple ways to delete DOM nodes in Stencil.
The simplest is to just call remove() on the element, like any other element:
document.querySelector('my-alert').remove();
Another would be to have a parent container that manages the my-alert message(s). This is especially useful for things like notifications.
#Component({...})
class MyAlertManager {
#Prop({ mutable: true }) alerts = ['alert 1'];
removeAlert(alert: string) {
const index = this.alerts.indexOf(alert);
this.alerts = [
...this.alerts.slice(0, index),
...this.alerts.slice(index + 1, 0),
];
}
render() {
return (
<Host>
{this.alerts.map(alert => <my-alert text={alert} />)}
</Host>
);
}
}
There are other options and which one to choose will depend on the exact use case.
Update
In your specific case I would just render the dismiss button conditionally:
export class Alert {
#State() shouldRenderDismissButton = true;
#Method()
async dismiss() {
this.shouldRenderDismissButton = false;
}
render() {
return (
<div>
<slot/>
{this.shouldRenderDismissButton && <button onClick={() => this.dismiss()}>
Dismiss
</button>
</div>
);
}
}
Generally I would not recommend manually manipulating the DOM in Stencil components directly since that could lead to problems with the next renders since the virtual DOM is out of sync with the real DOM.
And if you really need to wait for the component to render you can use a Promise:
class Alert {
loadPromiseResolve;
loadPromise = new Promise(resolve => this.loadPromiseResolve = resolve);
#Method()
async dismiss() {
// Wait for load
await this.loadPromise;
// Remove button from DOM
this.dismissButton.remove();
}
componentDidLoad() {
this.loadPromiseResolve();
}
}
I previously asked a question about waiting for the next render which would make this a bit cleaner but I don't think it's easily possible at the moment. I might create a feature request for this in the future.

mixpanel track form submission with validation

I have a form which I want to use mixpanel to track some properties when I submit. How can I stop the form submit through mixpanel if the validation return false ?
Here's my code in general.
My simple form
<form id="form" action="..." method="post" role="form">
// my elements here
<input type="submit" value="Submit" />
</form>
My script
<script>
function(){
mixpanel.track_forms("form", "MyEventName", getProperties());
$("form").submit(SubmitForm);
function getProperties(){
// get properties here
}
function SubmitForm() {
if (SomethingNotRight()) { return false; }
return true;
}
}
My problem:
I expect that in my SubmitForm function, after validation by SomethingNotRight function, it will stop the submit. However, even when SubmitForm returns false, the form keep submitting to the server, which I found out is because of the mixpanel.track_form.
The reason I use mixpanel.track_form is to avoid the race condition between form submit and mixpanel submit as debugging mixpanel track form
I can definitely understand the issue here, and the reason is that track_forms is just designed for the default use case of a form submitting right away. If you have a process in between (in this case a validation), you should basically do your own implementation. The idea of track_forms is to identify the form being submitted, log the event, wait for a while so that the event can be saved, and then proceed. In that sense, you can do:
(function(){})(
var theForm = $("#form"),
readyToProceed = false;
//listen for the submition
theForm.submit(function(e){
if(!readyToProceed){
e.preventDefault();
processSubmit();
}
});
function processSubmit(){
//validation process
if (SomethingNotRight()) { return false; }
//we are all good, lets proceed
mixpanel.track("Form submitted");
readyToProceed = true;
window.setTimeout(function(){ theForm.submit() }, 300);
}
);

input type=reset and knockout

Knockout doesn't update observables when a form reset button is clicked.
http://jsfiddle.net/nQXeM/
HTML:
<form>
<input type="text" data-bind="value: test" />
<input type="reset" value="reset" />
</form>
<p data-bind="text: test"></p>
JS:
function ViewModel() {
this.test = ko.observable("");
}
ko.applyBindings(new ViewModel());
Clearly the change event of the input box isn't being fired, as seen with this jQuery test:
http://jsfiddle.net/LK8sM/4/
How would we go about forcing all observables bound to form inputs to update without having to manually specify them if the reset button isn't firing of change events?
It would be easy enough to use jQuery to find all inputs inside the form and trigger change events, but lets assume we've a knockout only controlled form.
I copied and modified the default Knockout submit binding in order to create a similar binding for the form reset event:
ko.bindingHandlers['reset'] = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
if (typeof valueAccessor() !== 'function')
throw new Error('The value for a reset binding must be a function');
ko.utils.registerEventHandler(element, 'reset', function (event) {
var handlerReturnValue;
var value = valueAccessor();
try {
handlerReturnValue = value.call(bindingContext['$data'], element);
} finally {
if (handlerReturnValue !== true) {
if (event.preventDefault)
event.preventDefault();
else
event.returnValue = false;
}
}
});
}
};
You'd bind this like:
<form data-bind="reset: onFormReset">
and onFormReset would be on your view model:
function ViewModel() {
this.onFormReset = function () {
//Your custom logic to notify or reset your specific fields.
return true;
}
}
In your reset handler, if you return true, then JavaScript will continue to call its reset function on the form. If you are setting observables that are bound to value, though, you don't really need to have JavaScript continue to reset the form. Therefore, you could technically not return anything, or return false in that scenario.
Someone else could extend this further to notify all the bound observables in the form automatically, but this worked for my purposes.
As you mentioned, the change event isn't fired when a form is reset. If you're only using KnockOut, I don't think you really have may options unless you create custom bindings that can register for the reset event and detect changes - that would still involve manual JS, but at least it would be centralized.
A more general approach, although it does require jQuery, is to create a function to handle the form's reset event, and detect changes on the form inputs at that time.
Here's an example of an event handler that might work. Please be aware, this is not production-ready code. I would look at it with a good jQuery eye before using :)
$('form').on('reset', function (evt) {
evt.preventDefault();
$(this).find('input, select, textarea').each(function () {
if ($(this).is('input[type="radio"], input[type="checkbox"]')) {
if ($(this).is(':checked') !== $(this)[0].defaultChecked) {
$(this).val($(this)[0].defaultChecked);
$(this).trigger('click');
$(this).trigger('change');
}
} else {
if ($(this).val() !== $(this)[0].defaultValue) {
$(this).val($(this)[0].defaultValue);
$(this).change();
}
}
});
});
Here's a fiddle that demonstrates the idea: http://jsfiddle.net/Fm8rM/2/

Call a function after a form is submitted using jquery

I'm trying to call a function after any form with the class shown below is submitted. However, this doesn't seem to be working for me (the form submits, but the submit button remains active and the loading image is not shown).
$(document).ready(function() {
$('.uniForm').submit(function() {
$('#loadingImage').show();
$(':submit',this).attr('disabled','disabled');
return true;
});
});
Here's some HTML:
<form class="uniForm" id="formABC">
//...form.... here
</form>
<img src="loadimage.gif" style="display: none;" id="loadingImage">
does anyone see anything inherently wrong with this that would be preventing things from working correctly?
I have a feeling it's just not being called correctly. Can I call it myself via some HTML like this?
<button type="button" class="primaryAction" alt="Submit Form" onclick="$('#formABC').submit();">Submit Form</button>
Following your comment, it seems the binding of the handler function to the submit event might be taking place before the form element has been loaded into the DOM.
Ideally, you should bind event handlers only after the DOM has finished loading.
For example:
$(document).ready(function() {
$('.uniForm').submit(function() {
...
});
});
Put an id on the submit input/button and try this:
$('#mySubmitButton').click(function(e) {
e.preventDefault();
e.stopPropagation();
$(this).attr('disabled','disabled');
$('#loadingImage').show(function() {
$(this.form).submit();
});
});
There is a jQuery plugin named jQuery Form Plugin which helps to submit your form from ajax without refresh and then you can do the rest of actions on its success (which occurs exactly after successful form submission):
jQuery(document).ready(function () {
jQuery('#my_submit_button').click(function (e) {
jQuery(this.form).ajaxSubmit({
target: false,
success: function ()
{
your_other_stuff();
},
});
});
});
function your_other_stuff(){
// rest of things
}
Try something else:
$('.uniForm input[type=submit]').click(function(){
$('.uniForm').submit();
//doStuffafterSubmit
});

ajax.beginform onsucess updatetargetid hidden input

I am trying to call a jquery ui dialog by attaching the function to the onsuccess property of the ajaxoptions on a ajax.beginform..
<script type="text/javascript">
// Dialog
$(document).ready(function () {
$('#dialog').dialog({
autoOpen: false,
width: 600,
modal: true,
buttons: {
"Ok": function () {
$(this).dialog("close");
}
}
});
});
</script>
In a seperate script file I have this..
function EmailResult() {
$('#dialog').dialog('open');
}
Then I have a contact form that is not actually wired up yet, the controller just responds with one of two string responses.
<% using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "ContactResult", OnSuccess="EmailResult" }))
{ %>
If I take out the OnSuccess="EmailResult" from the Ajax.BeginForm or simply remove $('#dialog').dialog('open'); from my EmailResult function the error goes away so obvisouly this is an issue with the OnSuccess property and a Jquery UI Dialog.
My first question is am I doing something wrong that is causing this not to work and/or if this won't work then is there a better solution.
I am trying to create a dialog that comes up and says whether the message was sent. I do not want to use the alert dialog box.
I guess the error would help, in the IE 8 debugger it comes up with an undefined error in the MicrosoftAjax.js library
The finally block of this code is causing the problem and under the locals tab in IE 8 it says b is undefined.
this._onReadyStateChange = function () {
if (a._xmlHttpRequest.readyState === 4) {
try {
if (typeof a._xmlHttpRequest.status === "undefined") return
} catch (b) {
return
}
a._clearTimer();
a._responseAvailable = true;
try {
a._webRequest.completed(Sys.EventArgs.Empty)
} finally {
if (a._xmlHttpRequest != null) {
a._xmlHttpRequest.onreadystatechange = Function.emptyMethod;
a._xmlHttpRequest = null
}
}
}
};
What it was updating was
<%= Html.Hidden("ContactResult") %>
Which turns out was the whole problem, I changed the Hidden Input to a div and it works perfectly. Not sure why but... if anyone else runs into this there you go...
So I guess this is what I figured out.. I started a new mvc project with two inputs and started just using an alert box as it turns out it was not related to the jquery.ui dialog plugin. I got it to work correctly with the alert box coming up after it was run using the ajax.beginform.
So long story short.. You can't use a Hidden Input for the UpdateTargetID in the Ajax.BeginForm? I guess this is kind of a question and the answer but changing the UpdateTargetID to the ID of a "div" fixed it and it works appropriately. You can even set the Div visibility to hidden and it works.