get URL before submit form post - javascript

I wanted to submit a form post based on user input, but the url only works for previous button. How do I take it so the addr.url becomes the current URL instead of the previous click. I want to get the url before I submit the post request.
<form id="launch" ngNoForm action="{{addr?.url}}" target="user.name" method="POST">
<input type="hidden" name="process" value="1"/>
<input type="hidden" name="key" value="user.cookie"/>
<button (click)="onSubmit(userInfo)">
<img src="../../../image/clickme.png">
</button>
</form>
onSubmit(userInfo) {
console.log('post submission' + userInfo);
this.paymentService.launch(userInfo).subscribe(data => {
this.addr = data;
if (this.addr && this.addr !== undefined && this.addr.url && this.addr.url !== undefined) {
console.log ('url: ' + this.addr.url);
$('#launch').submit();
}
});
}

Here is an example of posting data to a server "the Angular way":
The form tag:
<form novalidate
(ngSubmit)="save(signupForm)">
The submit button:
<button type="submit">
Save
</button>
The save method in the component:
save(signupForm: NgForm) {
console.log(signupForm.form.value);
// Call an http service to post the form values.
this.dataService.post(signupForm.form.value).subscribe();
}
The dataService:
post(signupValues): Observable<Product> {
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
return this.http.post(this.url, signupValues, { headers: headers });
}
NOTE: This code was written without assistance from a text editor and may contain syntax errors.

I would do it the way DeborahK suggested and inside the onSubmit() function, I would combine both http requests (the one getting the url and the actual submit) with RxJS. E.g. this.httpServe.getUrl().pipe(flatMap(result=>this.httpService.submitWithUrl(result, formValued).

Related

client-side javascript file set form tag attribute

I want to make a login, signup webpage with nodejs. So I use form tag to send url and method. In my case form tag has two different submit buttons.
below is HTML code
<form id="login">
<input type="text" placeholder="ID" id="id" name="id"> <br>
<input type="password" placeholder="password" id="passwd" name="passwd"> <br>
<input type="submit" value="login" id="login-btn">
<input type="submit" value="signup" id="signup-btn">
</form>
<script src="index.js"></script>
Since I want to make these two buttons work differently I write simple js file to set forms' action and method.
const response = document.getElementById('login');
const attribute = function(obj, action, method){
response.setAttribute('action', action);
response.setAttribute('method', method);
}
const login = document.getElementById('login-btn');
login.addEventListener('click', attribute(response, '/login', 'POST'));
const signup = document.getElementById('signup-btn');
signup.addEventListener('click', attribute(response, '/signup', 'GET'));
When I write like that both buttons work as signup button. So I only can access signup page.
However, when I write js file without declaring function
const response = document.getElementById('login');
const login = document.getElementById('login-btn');
login.addEventListener('click', () => {
response.setAttribute('action', "/login");
response.setAttribute('method', "POST");
});
const signup = document.getElementById('signup-btn');
signup.addEventListener('click', () => {
response.setAttribute('action', "/signup");
response.setAttribute('method', 'GET');
});
it works well.
Can you guys tell me what is different between two js codes? And why is this happening?
As per the MDN documentation for [addEventListener]1, the syntax is given by
target.addEventListener(type, listener [, options]);
listener
The object that receives a notification (an object that implements the Event interface) when an event of the specified type occurs. This must be an object implementing the EventListener interface, or a JavaScript function. See The event listener callback for details on the callback itself.
If you observe the 2nd argument in the following line of code, you will notice, that it's not a function, it's rather the return value of the function, which is, undefined by default (because you haven't specified any return values) :
login.addEventListener('click', attribute(response, '/login', 'POST'));
To validate what I am saying here, please do the following:
typeof attribute(response, '/login', 'POST');
> undefined
So, essentially, this following line:
login.addEventListener('click', attribute(response, '/login', 'POST'));
evaluates to
login.addEventListener('click', undefined);
whereas, in the following snippet, the 2nd argument is clearly an arrow function:
document.getElementById('login-btn');
login.addEventListener('click', () => {
response.setAttribute('action', "/login");
response.setAttribute('method', "POST");
});
.. and that is the source of the difference in behavior between two.
I hope I clarified your doubt. If I din't, please post a comment.
You're trying to use attribute as the callback, but you're calling the function which returns undefined and when the click event happens it just tries to call undefined. You need to wrap those attribute calls in another function to be able to run it that way. Something like...
const login = document.getElementById('login-btn');
login.addEventListener('click', () => {
attribute(response, '/login', 'POST')
});
const signup = document.getElementById('signup-btn');
signup.addEventListener('click', () => {
attribute(response, '/signup', 'GET')
});

eventListener on form is not firing

I've copied some code from a tutorial, which sends form content to an API. The API is set up on AWS and works if I send it some JSON using Postman. However the JavaScript isn't working. When I hit the submit button on the form the sendDataToLambda function is not executing. If I add onClick="sendDataToLambda()" to the submit button then the function fires (but then fails on the e.preventDefault() line, which is expected behavior).
I've checked the form ID is correct and that the listener is set up correctly and I can't find the fault.
I prefer not to use jQuery if at all possible.
<body>
<div class=container>
<h1>Notes</h1>
<form id="note-form" style="margin-top:50px;">
<input type="text" id="subject" placeholder="Enter subject here…" class="form-control" /><br/>
<textarea id="body" rows="3" placeholder="Enter body here…" class="form-control"></textarea><br/>
<button type="button" class="btn btn-lg">Submit</button>
</form>
</div>
<script type="text/javascript">
// Adds an event listener to our form. When the form is submitted, it will send data to our Lambda function, which in turn, will send us an email.
document.getElementById('note-form').addEventListener('submit', sendDataToLambda);
// Now for the good stuff. This is the function that will send our data to AWS.
function sendDataToLambda(e) {
console.log('Submit clicked')
e.preventDefault();
// Gets the values of each field in our form. This is the data we'll send to our Lambda function.
var formSubject = document.getElementById('subject').value;
var formBody = document.getElementById('body').value;
// This is the endpoint we created in our API Gateway. This is where we make our POST request, which calls our Lambda function.
var endpoint = 'https://################';
// Remember those form values we just grabbed? We're going to put them into an object here.
var body = {
subject: formSubject,
body: formBody
}
// Here, we instantiate our Request. This is a special object used by the Fetch API so it knows where to send data, what data to send, and how to send it.
var lambdaRequest = new Request(endpoint, {
method: 'POST',
// Quick note: 'no-cors' mode is for development on localhost only!
mode: 'no-cors',
body: JSON.stringify(body)
});
// Call the Fetch API to make our request
fetch(lambdaRequest)
// This is where you can handle errors. This is just an example, so we won't cover that.
.then(response => console.log(response))
.catch(err => console.log(err));
}
</script>
</body>
</html>
If you want the onSubmit event to fire, you need to make sure your form has a submit button (must have the type attribute set to submit).
<button type="submit" ... >Submit</button>
See the code below for the modifications to your code:
<body>
<div class=container>
<h1>Notes</h1>
<form id="note-form" style="margin-top:50px;">
<input type="text" id="subject" placeholder="Enter subject here…" class="form-control" /><br/>
<textarea id="body" rows="3" placeholder="Enter body here…" class="form-control"></textarea><br/>
<button type="submit" class="btn btn-lg">Submit</button>
</form>
</div>
<script type="text/javascript">
// Adds an event listener to our form. When the form is submitted, it will send data to our Lambda function, which in turn, will send us an email.
document.getElementById('note-form').addEventListener('submit', sendDataToLambda);
// Now for the good stuff. This is the function that will send our data to AWS.
function sendDataToLambda(e) {
console.log('Submit clicked')
e.preventDefault();
// Gets the values of each field in our form. This is the data we'll send to our Lambda function.
var formSubject = document.getElementById('subject').value;
var formBody = document.getElementById('body').value;
// This is the endpoint we created in our API Gateway. This is where we make our POST request, which calls our Lambda function.
var endpoint = 'https://################';
// Remember those form values we just grabbed? We're going to put them into an object here.
var body = {
subject: formSubject,
body: formBody
}
// Here, we instantiate our Request. This is a special object used by the Fetch API so it knows where to send data, what data to send, and how to send it.
var lambdaRequest = new Request(endpoint, {
method: 'POST',
// Quick note: 'no-cors' mode is for development on localhost only!
mode: 'no-cors',
body: JSON.stringify(body)
});
// Call the Fetch API to make our request
fetch(lambdaRequest)
// This is where you can handle errors. This is just an example, so we won't cover that.
.then(response => console.log(response))
.catch(err => console.log(err));
}
</script>
</body>
</html>

Ajax: Send a model to controller from list iterated by foreach loop

I need to be able to send a list of a model back to the controller from a view but only when the input has been checked.
Using AJAX I can get it working but the page refreshes and I don't catch the data but it does show up in the URL. Example: https://localhost:44308/PlayTest/PlayTest?personName=Test+User&DevOps-rate=3&Software+Development-rate=2&Solution+Architecture-rate=1&comments=&save=Save
But when I try and use Javascript and JQuery, I'm only able to catch the "person name" not the comments or rates in the post method.
HTML
<div class="tabcontent" id="testing">
<form name="skillform"
id="skillform"
asp-action="SaveRecord"
asp-controller="YourSkills"
data-ajax="true"
data-ajax-method="post">
<h3 class="tab-title">Testing</h3>
#foreach (var item in Model.Skills)
{
#if (item.SkillGroupID == 2)
{
<div class="star-rating">
<h5 class="skill-name" id="skill-title">#item.SkillName</h5>
<input type="radio" id="#item.SkillName#item.SkillGroupID-star3" name="#item.SkillName-rate" value="3" /><label for="#item.SkillName#item.SkillGroupID-star3" title="Advanced - 3 Stars">3 Stars</label>
<input type="radio" id="#item.SkillName#item.SkillGroupID-star2" name="#item.SkillName-rate" value="2" /><label for="#item.SkillName#item.SkillGroupID-star2" title="Intermediate - 2 Stars">2 Stars</label>
<input type="radio" id="#item.SkillName#item.SkillGroupID-star1" name="#item.SkillName-rate" value="1" /><label for="#item.SkillName#item.SkillGroupID-star1" title="Beginner - 1 Star">1 Stars</label>
</div>
<br />
<br />
}
}
<div class="comments">
<h6 class="comment-name">Comments</h6>
<textarea rows="4" cols="50" name="comments" id="comment-text-area" spellcheck="true"></textarea>
</div>
<div class="buttons">
<input type="reset" value="Clear">
<button type="button" class="edit" onclick="alert('This will allow the tab to be edited')">Edit</button> <!--add cancel button when opened-->
<input type="submit" name="save" value="Save" id="btnSave" skill-group="2"/>
</div>
</form>
</div>
Post Method
public JsonResult SaveRecord(string PersonName, List<SkillsModel> skill, string comment)
{
SkillsMatrixDB database = HttpContext.RequestServices.GetService(typeof(SkillsMatrix.Models.SkillsMatrixDB)) as SkillsMatrixDB;
List<PersonModel> people = database.GetAllPeople();
PersonModel recordingPerson = FindPerson(people, PersonName);
if (skill.Count() > 1)
{
for (int i = 0; i < skill.Count(); i++)
{
RecordsModel records = new RecordsModel();
records.PersonID = recordingPerson.PersonID;
records.SkillGroupID = skill[i].SkillGroupID;
records.SkillID = skill[i].SkillID;
records.SkillLevelID = Convert.ToInt32(HttpContext.Request.Form[skill[i].SkillName + skill[i].SkillGroupID + "-rate"]);
records.Comments = HttpContext.Request.Form["comments"].ToString();
records.DateSaved = DateTime.Now;
records.YearlyQuarter = DateTime.Now.Month / 3;
//database.SaveRecord(records);
}
}
else if (skill.Count() == 1)
{
RecordsModel records = new RecordsModel();
records.PersonID = recordingPerson.PersonID;
records.SkillGroupID = skill[0].SkillGroupID;
records.SkillID = skill[0].SkillID;
records.SkillLevelID = Convert.ToInt32(HttpContext.Request.Form[skill[0].SkillName + skill[0].SkillGroupID + "-rate"]);
records.Comments = HttpContext.Request.Form["comments"].ToString();
records.DateSaved = DateTime.Now;
records.YearlyQuarter = DateTime.Now.Month / 3;
//database.SaveRecord(records);
}
return Json(recordingPerson.Name);
}
JS
$(document).ready(function () {
$("#btnSave").click(function () {
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: "POST", //HTTP POST Method
url: "YourSkills/SaveRecord", //Controller/View
data: $('#skillform').serialize(),
success: function (data) {
console.log(data);
alert('You saved it!');
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(textStatus);
alert('Something went wrong. save failed!');
}
});
});
});
I feel like the way I've read to make the list in JS is wrong and to catch the data is not all that correct either. If someone could help that would be great. I'm so confused why doing it without JS works and picks up the right data but for some reason, I can't.
EDIT
I have tried what Emiel Zuurbier said but I am using Visual Studio 2019 and In the console, all I am getting is the following:
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 POST https://localhost:44308/PlayTest/YourSkills/SaveRecord application/json; charset=UTF-8 235
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 6.0162ms 404
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 POST https://localhost:44308/PlayTest/SaveRecord application/x-www-form-urlencoded 233
Failed to load resource: the server responded with a status of 404 () [https://localhost:44308/PlayTest/YourSkills/SaveRecord]
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'SkillsMatrix.Controllers.PlayTestController.SaveRecord (SkillsMatrix)'
error
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action = "SaveRecord", controller = "PlayTest"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.JsonResult SaveRecord(System.String, System.Collections.Generic.List`1[SkillsMatrix.Models.SkillsModel], System.String) on controller SkillsMatrix.Controllers.PlayTestController (SkillsMatrix).
Your page is being reloaded because you are submitting the form whenever you click the the #btnSave button. What you want to do is listen for the submit event on the form itself and cancel it with event.preventDefault(). This allows you to create your own submission behavior when submitting. And prevents the form from reloading the page.
$(document).ready(function() {
$('#skillform').on('submit', function(event) {
...
event.preventDefault();
});
});
Your HTML seems to miss the #skill-id element. If you mean to include data from your form into your controller then I suggest that you use hidden input fields instead of reading attributes from your elements.
<input type="hidden" name="skill-name" value="">
<input type="hidden" name="skill-id" value="">
<input type="hidden" name="skill-group" value="">
These fields will not be visible to the user but will contain data that the server is able to read.
Then instead of use .val() to get each individual field use $('form').serialize() to extract the name and value pairs out of the form and use them in your AJAX request. This way you are sending the same data as you would with a normal submit.
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: "POST",
url: "YourSkills/SaveRecord",
data: $('#skillform').serialize(); // <-- Get all values from the form.
success: function (data) { // <-- data is the response you receive from the controller.
console.log(data);
alert('You saved it!');
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Something went wrong. save failed!');
}
});
I recommend that you check the $.ajax docs to use the correct methods and notation to use the function properly.
page reloading may happens because the error occurred in js execution while you are creating skills object.as its not the right way
define skills object this way rest of the things look good.
let skills = {};
skills['SkillID'] = $("#skill-id").val();
skills['SkillGroupID'] = $(this).attr('skill-group');
skills['SkillName'] = $("#skill-title").val();

Form help(HTML/JS)

I'm (very) new to web development and am working on learning back-end currently.
I am trying to figure out how to use multiple inputs inside a form, but am struggling to get the actual input, instead of the element itself using this code to create the form:
<form id="newPostForm">
<input name="titleInput" placeholder="title"><br>
<input name="bodyInput" placeholder="body">
<button>Submit</button>
</form>
and this JS to try and output the user input to the console:
const newPost = document.getElementById("newPostForm")
const title = document.querySelector(".titleInput")
const body = document.querySelector(".bodyInput")
newPost.addEventListener("submit", (e) => {
e.preventDefault()
console.log(title, Body)
})
When I hit the submit button the console displays null null. This is probably a super simple question, but I'd appreciate any help.
After fixing the case issue with your body variable, you need to get the value of the inputs by accessing their value property. Then you want to move those variables into your submit handler, otherwise you're only getting the value once, when the page loads, and they're blank:
const newPost = document.getElementById("newPostForm");
newPost.addEventListener("submit", (e) => {
const title = document.querySelector(".titleInput").value;
const body = document.querySelector(".bodyInput").value;
e.preventDefault()
console.log(title, body)
})
<form id="newPostForm">
<input name="titleInput" class="titleInput" placeholder="title"><br>
<input name="bodyInput" class="bodyInput" placeholder="body">
<button>Submit</button>
</form>

multipart/form-data form with no field names

I have an HTML form that I was using to send information to the nodejs backend. I then tried to implement file uploads using the same form. To do that, I had to change the enctype of the form from the default value (application/x-www-form-urlencoded) to be enctype='multipart/form-data', and I had to use multer on the backend. I also had this button:
<input type="button" value="Submit" onclick="submitRequest(this);">
which I had to change to:
<input type="submit" value="Submit" onclick="submitRequest(this);">
This worked great in the sense that I now had files uploading to the server. However, this implementation depends on the field's names in the form. The problem is that most of the fields that I have don't have names.
I was wondering if there is a way to get both files and data to send without having to give names to each field in the form? I am wondering if it would be possible to inject my own data into the result that is generated after clicking Submit and before that result is sent to the backend? If not, is there any other way?
You can use FormData to set key and value multipart/form-data, fetch() or XMLHttpRequest() to POST data to server.
<form id="form">
<select>
<option value="1">1</option>
<option value="2">2</option>
</select>
<input type="file" />
<input type="submit" value="Submit" />
</form>
function submitRequest(event) {
event.preventDefault();
var i = 0;
var inputs = form.querySelector("input[type=file], select");
var fd = new FormData();
for (let el of inputs) {
if (el.tagName === "SELECT") {
fd.append("select", el.value)
}
if (el.type === "file") {
if (el.files.length) {
for (let file of el.files) {
fd.append("file" + (i++), file);
}
}
}
}
fetch("/path/to/server", {method:"POST", body:fd})
.then(function(response) {
return response.text()
})
.then(function(res) {
console.log(res)
})
.catch(function(err) {
console.log(err)
})
}
const form = document.getElementById("form");
form.onsubmit = submitRequest;

Categories