Dynamically importing a module upon submitting a form in JavaScript - javascript

A have an 'Add to basket' button which submits a form via Ajax with all products' details. At the moment the module responsible for that operation is loaded straight away when the website is loaded. I would like it to be loaded only when the button is clicked, though. This is what I have so far:
$('form:not(.contact-form__items)').on('submit', event => {
import('./modules/adding-products-to-basket.js')
.then(module => {
module.AddingProductsToBasket.addProductToBasket(event);
});
});
Module's content:
export const AddingProductsToBasket = {
addProductToBasket (event) {
const _this = AddingProductsToBasket;
event.preventDefault();
$.ajax({
url: 'basket',
method: 'POST',
data: $(event.currentTarget).serialize(),
dataType: 'text',
success: function(response) {
_this.openAddedToBasketLightbox();
}
},
});
}
};
I'm not getting any errors in the console but the problem is that
event.preventDefault() inside addProductToBasket doesn't do it's job, so user is taken to the basket page instead of staying on the page where the 'Add to basket' button is.

Thank you both for your help. It's working now.
Loading the module when the form shows:
if ($('form:not(.contact-form__items)').length) {
import('./modules/adding-products-to-basket.js')
.then(module => {
$('form:not(.contact-form__items)').on('submit', event => {
module.AddingProductsToBasket.addProductToBasket(event);
});
});
}
Loading the module not when the form loads but when it is submitted:
(event.preventDefault() in AddingProductsToBasket() can be removed)
$('form:not(.contact-form__items)').on('submit', event => {
event.preventDefault();
import('./modules/adding-products-to-basket.js')
.then((module) => {
module.AddingProductsToBasket.addProductToBasket(event);
});
});

Related

When I post something with Pusher, and reload the page, all entries disappear. How to fix? Python Flask

Here's where I'm triggering the Pusher event.
#app.route('/post-question', methods=['POST'])
def add_question():
data_received = json.loads(request.data)
data = {
'id':'post-{}'.format(uuid.uuid4().hex),
'title':data_received['title'],
'question':data_received['content'],
'status': 'active',
'event_name': 'created'
}
pusher.trigger("CHANNEL", 'question-created', data)
return jsonify(data)
Here's the Pusher channel binding:
<script>
function appendToList(data) {
const html = `
<div id="${data.id}">
<header>
<h1>${data.title}</h1>
</header>
<div>
<p>${data.question}</p>
</div>
</div> `
let list = document.querySelector('#post-list')
list.innerHTML += html
}
$(document).ready(() => {
$(document).on('click', "#submit", function(event) {
$.post({
url: '/post-question',
type: 'POST',
contentType: 'application/json;charset=UTF-8',
dataType: 'JSON',
data: JSON.stringify({'title': $("#question-title").val(), 'content': $("#question-content").val()}),
success : function(response) {
console.log(response);
},
error : function(xhr) {
console.log(xhr);
}
}).done(function(response) {
$("#question-form").reset()
})
})
})
Pusher.logToConsole = true;
const pusher = new Pusher('*', {
cluster: '*',
encrypted: true
});
const channel = pusher.subscribe('CHANNEL')
channel.bind('question-created', data => {
appendToList(data);
})
</script>
It correctly triggers the event, and appears correctly in another window in real time, but for some reason, when I reload the page, all the posts disappear; and the post disappears on the current window as well.
I think it might be a problem with the way I am rendering the posts, but I don't know. Anybody know how to fix this?
Thanks in advance!
First comment is correct. Pusher takes care of real-time communication and new events. For showing old/existing posts every time page (re)loads, you need to query and render them in your app. You can choose to do that server-side or client-side.

How to reload page after using fetch

Was wondering why my code below isnt working. Basically I am fetch data from my url to delete something. on delete, it should refresh. however it doesnt seem to let me do that. But what it does is delete the post if i manually refresh the page.
Works when I use Ajax method though which I don't know why.
Fetch method
const deleteBTN = document.querySelectorAll('.deleteBtn');
const update = document.querySelectorAll('.postedNote');
console.log(deleteBTN);
for (let btn of deleteBTN) {
btn.addEventListener('click', (e) => {
console.log("Delete from front end");
console.log(btn[btn])
let id = e.target.dataset.btn;
fetch('http://localhost:3000/api/notes' + '/' + id, {
method: "DELETE",
}).then(() => {
Location: reload()
})
})
}
Ajax method
$(".deleteBtn").click((e) => {
$.ajax({
type: "DELETE",
url: `http://localhost:3000/api/notes/${e.target.dataset.btn}`,
success: function () {
console.log("delete success");
},
}).done(
setTimeout(() => {
window.location.reload();
}, 500)
);
});
We can reload by using window.location.reload as already doing on ajax success.
Kindly find below as code snippet
const deleteBTN = document.querySelectorAll('.deleteBtn');
const update = document.querySelectorAll('.postedNote');
console.log(deleteBTN);
for (let btn of deleteBTN) {
btn.addEventListener('click', (e) => {
console.log("Delete from front end");
console.log(btn[btn])
let id = e.target.dataset.btn;
fetch('http://localhost:3000/api/notes' + '/' + id, {
method: "DELETE",
}).then(() => {
window.location.reload();
})
})
}
Also, a few considerations below
The use of Ajax is defeated here as we are reloading the page.
Either
we should perform some DOM manipulation to delete the deleted post
from the page
Or,
in case we are using React, we can bind posts to state and then
delete the deleted post on API success call, so that component is
re-rendered and we do not need to refresh the page.
I think you should'nt try to reload the page when removing one of the elements,
instead I would have checked the response status and manually update the DOM to make the deleted element disappear if response says it was removed successfully.

how can I execute the call to function doing ajax request using jQuery $("#").click()

I have a function that gets the form values and send them Flask backend to retrieve info from SQLite database. I'm using jQuery $.ajax() with POST to allow for better error handling.
Because the ajax is async I'm passing a callback to logTable(callback) as suggested here. I need the logTable() to run after I input the form data and click the submit button. I'm using $("#some-id").click() to achieve this.
const logsTable = (callback) => {
const startDate = $("#start-date").val();
const endDate = $("#end-date").val();
const container = $("#programs").val();
const server = window.location.host;
const url = `http://${server}/api/log-info`;
let logs = "";
let dataToSend = {
start_date: startDate,
end_date: endDate,
program: container,
};
$.ajax({
type: "POST",
url: url,
data: dataToSend,
success: (data) => {
callback(data);
},
error: (jqXHR, textStatus, errorThrown) => {
alert(errorThrown);
},
});
};
$("#submit-button").click(() => {
return logsTable((data) => {
$("#logs-div").html(data);
alert("Success");
});
});
I receive the alert with Success, the data briefly appears on the page and disappears. If run the code below directly it, it runs on page reload and posts an empty list to a page because no data was sent to the backend.
logsTable((data) => {
$("#logs-div").html(data);
alert("Success");
});
I need to somehow the function call above to a Submit button. How can I do that?

How to run JavaScript code on Success of Form submit?

I have an Asp.Net MVC web application. I want to run some code on the successful response of the API method which is called on form submit.
I have the below Code.
#using (Html.BeginForm("APIMethod", "Configuration", FormMethod.Post, new { #class = "form-horizontal", id = "formID" }))
{
}
$('#formID').submit(function (e) {
$.validator.unobtrusive.parse("form");
e.preventDefault();
if ($(this).valid()) {
FunctionToBeCalled(); //JS function
}
}
But FunctionToBeCalled() function gets called before the APIMethod(), but I want to run the FunctionToBeCalled() function after the response of APIMethod().
So I made the below changes by referring this link. But now the APIMethod is getting called twice.
$('#formID').submit(function (e) {
$.validator.unobtrusive.parse("form");
e.preventDefault();
if ($(this).valid()) {
//Some custom javasctipt valiadations
$.ajax({
url: $('#formID').attr('action'),
type: 'POST',
data: $('#formID').serialize(),
success: function () {
console.log('form submitted.');
FunctionToBeCalled(); //JS function
}
});
}
}
function FunctionToBeCalled(){alert('hello');}
So I am not able to solve the issue.
If you want to execute some work on success, fail, etc. situation of form submission, then you would need to use Ajax call in your view. As you use ASP.NET MVC, you can try the following approach.
View:
$('form').submit(function (event) {
event.preventDefault();
var formdata = $('#demoForm').serialize();
//If you are uploading files, then you need to use "FormData" instead of "serialize()" method.
//var formdata = new FormData($('#demoForm').get(0));
$.ajax({
type: "POST",
url: "/DemoController/Save",
cache: false,
dataType: "json",
data: formdata,
/* If you are uploading files, then processData and contentType must be set to
false in order for FormData to work (otherwise comment out both of them) */
processData: false, //For posting uploaded files
contentType: false, //For posting uploaded files
//
//Callback Functions (for more information http://api.jquery.com/jquery.ajax/)
beforeSend: function () {
//e.g. show "Loading" indicator
},
error: function (response) {
$("#error_message").html(data);
},
success: function (data, textStatus, XMLHttpRequest) {
$('#result').html(data); //e.g. display message in a div
},
complete: function () {
//e.g. hide "Loading" indicator
},
});
});
Controller:
public JsonResult Save(DemoViewModel model)
{
//...code omitted for brevity
return Json(new { success = true, data = model, message = "Data saved successfully."
}
Update: If SubmitButton calls a JavaScript method or uses AJAX call, the validation should be made in this method instead of button click as shown below. Otherwise, the request is still sent to the Controller without validation.
function save(event) {
//Validate the form before sending the request to the Controller
if (!$("#formID").valid()) {
return false;
}
...
}
Update your function as follows.
$('#formID').submit(function (e) {
e.preventDefault();
try{
$.validator.unobtrusive.parse("form");
if ($(this).valid()) {
$.ajax({
url: $('#formID').attr('action'),
type: 'POST',
data: $('#formID').serialize(),
success: function () {
console.log('form submitted.');
FunctionToBeCalled(); //JS function
}
});
}
}
catch(e){
console.log(e);
}
});
Check the browser console for fetching error. The above code will prevent of submitting the form.
I think line $.validator.unobtrusive.parse("form") were throwing error.
For that use you need to add the following jQuery libraries.
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>
I think you should remove razor form tag if you want to post your form using ajax call and add post api URL directly to ajax request instead of getting it from your razor form tag using id:
Here is the revised version of your code :
<form method="post" id="formID">
<!-- Your form fields here -->
<button id="submit">Submit</button>
</form>
Submit your form on button click like:
$('#submit').on('click', function (evt) {
evt.preventDefault();
$.ajax({
url: "/Configuration/APIMethod",
type: 'POST',
dataType : 'json',
data: $('#formID').serialize(),
success: function () {
console.log('form submitted.');
FunctionToBeCalled(); //JS function
}
});
});
function FunctionToBeCalled(){alert('hello');}
You need to use Ajax.BeginForm, this article should help [https://www.c-sharpcorner.com/article/asp-net-mvc-5-ajax-beginform-ajaxoptions-onsuccess-onfailure/ ]
The major thing here is that I didn't use a submit button, I used a link instead and handled the rest in the js file. This way, the form would nver be submitted if the js file is not on the page, and with this js file, it initiates a form submission by itself rather than th form submitting when the submit button is clicked
You can adapt this to your solution as see how it respond. I have somthing like this in production and it works fine.
(function() {
$(function() {
var _$pageSection = $('#ProccessProductId');
var _$formname = _$pageSection.find('form[name=productForm]');
_$formname.find('.buy-product').on('click', function(e) {
e.preventDefault();
if (!_$formname.valid()) {
return;
}
var formData = _$formname.serializeFormToObject();
//set busy animation
$.ajax({
url: 'https://..../', //_$formname.attr('action')
type: 'POST',
data: formData,
success: function(content) {
AnotherProcess(content.Id)
},
error: function(e) {
//notify user of error
}
}).always(function() {
// clear busy animation
});
});
function AnotherProcess(id) {
//Perform your operation
}
}
}
<div class="row" id="ProccessProductId">
#using (Html.BeginForm("APIMethod", "Configuration", FormMethod.Post, new { #class = "form-horizontal", name="productForm" id = "formID" })) {
<li class="buy-product">Save & Proceed</li>
}
</div>

How to render MVC 4 view on slickgrid double click via Javascript

I am using MVC4 along with slickgrid to display data to the user. I am trying to implement the ability to double click on a slickgrid row and have the page go to another view, but all I am able to get is the HTML returned to the client, but not rendered.
I am doing,
grid.onDblClick.subscribe(function (e, args) {
$.get(
"MapSetEdit/Edit/",
{ 'mapSetId': 1 }
);
});
and I have also tried:
grid.onDblClick.subscribe(function (e, args) {
$.ajax({
type: "GET",
url: "MapSetEdit/Edit/",
dataType: 'text',
data: {'mapSetId': 1}
})
.fail(function () {
console.log("Error retreiving map list.");
});
});
All this does is return the html to the browser but never renders it. How do I make a javascript request so that I am able to actually render the view. I think I am missing something obvious here as I am new to javascript and mvc.
You should render the returned HTML with jQuery. For example:
grid.onDblClick.subscribe(function (e, args) {
$.ajax({
type: "GET",
url: "MapSetEdit/Edit/",
dataType: 'text',
data: {'mapSetId': 1}
})
.succes(function(data){
var someemptydiv = $("#myEmptyDiv");
someemptydiv.html(data);
})
.fail(function () {
console.log("Error retreiving map list.");
});
});
I was able to do what I needed with:
grid.onDblClick.subscribe(function (e, args) {
window.location = '/MapSetEdit/Edit/?mapSetId=1'
});

Categories

Resources