Prevent form submission but reflecting it in URL - javascript

Working with vanilla JS is there a "way" where i could essentially event.preventDefault while reflecting the URL on the form. I want to give people the choice to copy and paste the link and share to their friends.
My javascript code is doing something like
searchKeywordForm.addEventListener('submit', async (event) => {
event.preventDefault();
//Clear all courseItems and start from scratch
courseItems = [];
courseContainerElement.innerHTML = "";
let searchInput = document.getElementById("keywords");
await fetchDataByKeywords(searchInput.value);
})
In so doing it's not reflected in the url that i can do file:///C:/Users/bobby/Desktop/twitdemy/index.html?keywords=cas
I have already did some checks for queryString so essentially it works.
Right now since there is event.preventDefault the url is basically static at file:///C:/Users/bobby/Desktop/twitdemy/index.html

You can use history.pushState() to modify the current url without reloading page
const searchKeywordForm = document.forms.keyform
searchKeywordForm.addEventListener('submit', (e) => {
e.preventDefault();
const searchInput = document.getElementById("keywords"),
newUrl = `${searchKeywordForm.action}?key=${searchInput.value}`;
history.pushState(null, null, newUrl)
// log current location to see changes
console.log(location.href)
})
<form id="keyform" action="/formsubmiturl">
<input id="keywords" value="foo" />
<button>Submit</button>
</form>

Related

Why isn't my localStorage.setItem() and localStorage.getItem() storing a value?

I want to store a user input value using localStorage then use that value in my countdown timer.
Here is the HTML where the user inputs their data:
<form action='/' method= 'GET' id='settings'>
<label> Work Time </label>
<input class='settingInput' type='number' id='workInput'>
<label id='short-break'> Short Break </label>
<input class='settingInput' id='shortBreak'>
<label id='long-break'> Long Break </label>
<input class='settingInput' id='longBreak'>
<button id = 'set-values'>Submit</button>
</form>
this is the javascript to store and retrieve the data:
var workInputValue = document.getElementById('workInput').value;
var workTimeSerialized = JSON.stringify(document.getElementById('workInput').value);
var workTimeFinal = JSON.parse(localStorage.getItem('workTimeKey'));
submitButton.addEventListener('click', (e) => {
localStorage.setItem('workTimeKey', workTimeSerialized);
console.log('submit pressed');
e.preventDefault();
})
Here is the codepen for the whole project: https://codepen.io/Games247/pen/XWJqebG
This is my first time using setItem and getItem so I may be overlooking something obvious.
Currently it looks like a pair of brackets is stored in the localStorage where workTimeKey should be.
Your linked code on codepen has a problem, in fact the code posted here corrects said problem.
var workTimeSerialized = JSON.stringify(document.getElementById('workInput'));
The above is your codepen, the problem is you are trying to serialize the HTML element to JSON rather than it's value hence the '{}' you see in your session storage.
You need to ensure it's the value of the input element and not the element itself you serialize. Like i mentioned, your code posted here resolves the issue ;
var workTimeSerialized = JSON.stringify(document.getElementById('workInput').value);
Note: Whenever you see '[]' or '{}' in session storage rather than your intended value, you are either passing an object directly or an element in your case.
Edit:
'you are most likely not either'
Your input values should be read in the submit click handler otherwise, you get the value of the input before sumbit and not after
So your code:
var workInputValue = document.getElementById('workInput').value;
var workTimeSerialized = JSON.stringify(document.getElementById('workInput').value);
var workTimeFinal = JSON.parse(localStorage.getItem('workTimeKey'));
submitButton.addEventListener('click', (e) => {
localStorage.setItem('workTimeKey', workTimeSerialized);
console.log('submit pressed');
e.preventDefault();
})
becomes:
submitButton.addEventListener('click', (e) => {
var workInputValue = document.getElementById('workInput').value;
var workTimeSerialized = JSON.stringify(document.getElementById('workInput').value);
var workTimeFinal = JSON.parse(localStorage.getItem('workTimeKey'));
localStorage.setItem('workTimeKey', workTimeSerialized);
console.log('submit pressed');
e.preventDefault();
})

Remove query string on page reload

I have a hyperlink which i am redirecting to a page.
$('.lnkMerging').on("click", function () {
var id = $(this).attr('data-id');
window.location = '/Merging/Index/?workItemID=' + id;
});
My action in the controller page is
public ActionResult Index(int? workItemID)
{
MergingVM mergingVM = new MergingVM();
mergingVM.SourceList = GetSourceDropdownList();
mergingVM.WorkItem = (workItemID==null? 0: workItemID.Value) ;
mergingVM.MergeActionSelectList =
GetMergeProcessActionDropdownList();
PopulateDropDowns(mergingVM);
return View(mergingVM);
}
So what it does is when i click on the hyperlink it redirects me to the merging page.
After redirecting to Merge page, the drop down fills with id(selected in home page) and correspondingly triggers the button click.
My issue When i reload the merge page the value in the drop down doesn't get clear. I.e if i have redirected from home page to merge page , then the drop down has some value. but when i refreshes it the selected value should go. I understand that the query string still holds the value. But is there any alternative to send parameter to action without using windows.location.href in jquery.
If you are using hyperlink then also you can try it
$('.lnkMerging').on("click", function () {
var id = $(this).attr('data-id');
$(this).attr('href','/Merging/Index/?workItemID=' + id)
});
In order to clean the query string you should use redirect to another view.
public ActionResult Index(int? workItemID)
{
MergingVM mergingVM = new MergingVM();
mergingVM.SourceList = GetSourceDropdownList();
mergingVM.WorkItem = (workItemID == null ? 0 : workItemID.Value);
mergingVM.MergeActionSelectList =
GetMergeProcessActionDropdownList();
PopulateDropDowns(mergingVM);
//to send this model to the redirected one.
TempData["model"] = mergingVM;
return RedirectToAction("CleanIndex");
}
public ActionResult CleanIndex()
{
var model = (MergingVM)TempData["model"] ?? new MergingVM();
// Do something
return View("Index", model);
}
To find alternatives to an send parameter to a method you first need to understand the model Bindding action.
The model bidding searches a value in:
Form Data
Route Data
Query String
Files
Custom (cookies for example)
If your action must need to be HttpGet you lose the Form Data which would be a nice alternative for you.
If I understand correctly... the below worked for me.
If there's an ID appended to the URL, it gets logged to the console as the variable "param". The URL is then replaced (so that if you refresh the page, the ID is removed from the URL).
$(document).ready(function() {
var url = window.location.toString;
var hostname = window.location.hostname;
var pathname = window.location.pathname;
var param = window.location.search;
$('.lnkMerging').on("click", function () {
var id = $(this).attr('data-id');
window.location = '/new-page.php?' + id;
});
if ( pathname == "/new-page.php" && param ) {
console.log(param);
window.history.pushState("string", "Title", "http://yourURL.com/new-page.php");
//Do something with param...
}
});
This assumes that if there is no ID appended to the URL, the drop-down won't do anything. You also would need to update the URLs to the correct ones (I ran this on my local server).
I think you should use POST where you don't want to presist workItemID.
I mean all places where you have links you should use somethink like this:
<form action="/Merging/Index" method="POST">
<input type="hidden" name="workItemID" value="1" /> <-- your Id
<input type="submit" value="Link to workItemID 1!" /> <-- your link
</form>
This way you will get your View but without workItemID in URL. But you should change css to make your POST link look like <a> tags.
Here is with your table:
#if (#Model.DataSetList[i].StateID == 43)
{
<td>
<form action="/Merging/Index" method="POST">
<input type="hidden" name="workItemID" value="#Model.DataSetList[i].Workitem_ID" />
<input class="lnkMerging" type="submit" value="Merging" />
</form>
</td>
}
else
{
<td>
<text style="color:darkgrey" contenteditable="false">Merging</text>
</td>
}
You can save the parameter in local storage api of html5, and then use those parameters in Page load of index page.
$('.lnkMerging').on("click", function () {
var id = $(this).attr('data-id');
localStorage.setItem("workItemID",id);
window.location = '/Merging/Index/;
});
On page load of index you can retrieve it using getItem
localStorage.getItem("workItemID"); and use it as per your requirement.
On page load of Merge page, you have to explicitly set the selected option like below and then remove the value from local storage.
$(document).ready(function(){
if(localStorage.getItem("workItemID")!=null){
$("#mydropdownlist").val(localStorage.getItem("workItemID"));
localStorage.removeItem('workItemID');
}
});
Make sure in var id = $(this).attr('data-id'); id should get same value as you have in the options on the merge page.

How do I post data to the server without leaving the current page?

What I want is having a JavaScript function which sends a POST to an arbitrary site and stays the whole time on the site 'it was executed on'. It does not necessarily have to be done with a form!
I don't want to use jQuery, if possible.
How can I do this?
You can "prevent" the default behavior.
<form id="myform">
Name: <input id="name" type="text" value="onur" /><br />
Email: <input id="email" type="text" value="onur#email.com" /><br />
<br />
<button type="submit">type=submit</button>
<button type="button" onclick="form.submit()">form.submit()</button>
</form>
Before the </body> tag (or on DOM ready);
var form = document.getElementById('myform');
function onSubmit(event) {
if (event) { event.preventDefault(); }
console.log('submitting');
postFormData(form); // <-------- see below
}
// prevent when a submit button is clicked
form.addEventListener('submit', onSubmit, false);
// prevent submit() calls by overwriting the method
form.submit = onSubmit;
Fiddle here
EDIT:
The default behavior of form.submit() will redirect the page to the form.action URL. This is an approach on how you simulate the default behavior without redirecting to another page.
And since you want to "POST" the form, here is the method (AJAX stuff):
function postFormData(form) {
var xhr = new XMLHttpRequest(),
formData = urlEncodeFormData(form); // see below
// set XHR headers
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
// watch for state changes
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
// This is where you show a success message to the user
}
};
// open and send the post request
xhr.open('POST', 'https://myweb.com/action-target', true);
xhr.send(formData);
}
// You could use the FormData API if the browser supports it.
// Below is somewhat alternate and should be improved to support more form element types.
function urlEncodeFormData(form) {
var i, e, data = [];
for (i = 0; i < form.elements.length; i++) {
e = form.elements[i];
if (e.type !== 'button' && e.type !== 'submit') {
data.push(encodeURIComponent(e.id) + '=' + encodeURIComponent(e.value));
}
}
return data.join('&');
}
See:
MDN — Using XMLHttpRequest
MDN — FormData
Can I Use FormData?
Give your form an onsubmit handler that returns false. Do whatever processing you need to do in there (eg: ajax send data or what have you)
Code's untested, but here's the general idea.
function doFormThings() {
//processing form here
return false; //don't actually redirect, browser, I'm watching you
};
<form onsubmit="return doFormThings();">
Since you are dynamically creating the form, you can create it in an iframe and submit it inside of the iframe - that way you won't leave the current page and you'll actually use normal form submit. Here is a working example:
function generateFormAndSubmit()
{
// Create an input for the form
var input = document.createElement( 'input' );
input.type = 'hidden';
input.name = 'test'
input.value = '123';
// Create the form itself
var form = document.createElement( 'form' );
form.action = '/myaction';
// Append the created input to the form
form.appendChild( input );
// Create the iframe that will hold the form
var iframe = document.createElement( 'iframe' );
// Make it offscreen, so it's not visible for the user
iframe.style.cssText = 'width: 1px;height: 1px;position: absolute;top: -10px;left: -10px';
// Append the iframe to our document
document.body.appendChild( iframe );
// Append the form to the iframe
iframe.contentDocument.body.appendChild( form );
// Submit the form
form.submit();
}
You can call the submit of the form from another place, of course, like a button for an example - the iframe is yours, so you can manipulate (search for the form, modify it, submit it, etc.) it's contents at any point - no security restrictions will apply.
If you need a result of the submit, then it's a bit more complicated - first, the action of the form needs to point to the same domain. Then, if that is true, you just listen for when the iframe is loaded and read the result from it's content (either printed in the document JS or parse the DOM in some way).
You can simply have an iframe and change the form's target to post the data into it. E.g:
<form method='POST' target='hd-submit'>
<input name='firstName' placeholder='First Name' type='text' />
<input name='lastName' placeholder='Last Name' type='text' />
<input type='submit' value='Send' />
</form>
<iframe name='hd-submit' hidden></iframe>

Create URL upon JavaScript submit form

I currently have a form with some JavaScript functions and localstorage.
I'm trying to get that when a user types a value into a textbox, the search bar changes the URL from "mysite.com" to "mysite.com/%userinput%". Then that user can send that link to someone else and that person will then see what the original user saw.
This will change the URL after input.
As I understand from your question and comments, you don't want to load the URL, just change it, so try this fiddle: http://jsfiddle.net/GrP6U/2/show/
The code behind is:
JavaScript
var theForm = document.getElementById('theForm');
var theInput = document.getElementById('subj');
theForm.onsubmit = function(e) {
var myurl = "http://jsfiddle.net/GrP6U/2/show/?input=" + encodeURIComponent(theInput.value);
window.history.pushState('', "Title", myurl);
return false;
}
HTML
<form id="theForm">
<input id='subj'/>
<input type='submit'/>
</form>

Get the original url in this case with jquery

In the form below, I change the action attribute and submit the form. That works fine. What goes on is: if the current location is http://localhost/search/?mod=all and the search term is 14, the action will be changed to http://localhost/search/?mod=all&handle=14 and so will the url in the browser.
But the next time I try to search, since the url now is http://localhost/search/?mod=all&handle=14, I get http://localhost/search/?mod=all&handle=14&handle=15. It'll keep going on and on with each search term.
Any idea how I can retain the orginal url http://localhost/search/?mod=all through this all.
Here's the form:
<form method="GET" class="modForm" action="">
<input type="text" placeholder="Search" class="modSearchValue">
<input type="radio" name="text" value="text" class="text" title="Search">
</form>
Here's the jquery:
$('.modForm').submit(function(event) {
var $this = $(this);
var query = $this.find('.modSearchValue').val(); // Use val() instead of attr('value').
var locale = window.location;
if ($('.text').is(':checked')) {
query = '&text=' + query;
} else {
query = '&handle=' + query;
}
route = locale + query;
console.log(route);
if (query.length >= 1) {
// Use URI encoding
var newAction = (route);
console.log(newAction); // DEBUG
// Change action attribute
$this.attr('action', newAction);
//event.preventDefault();
} else {
console.log('Invalid search terms'); // DEBUG
// Do not submit the form
event.preventDefault();
}
});
There are few ways to do it. I would rather not mess with window.location and do something simpler:
<form method="GET" class="modForm" action="">
<input type="hidden" name="mod" value="all"> <!-- mod is a hidden variable -->
<input type="text" id="modSearchValue"> <!-- name not defined yet -->
<input type="checkbox" id="textOrHandle"> <!-- name not required -->
</form>
$(".modForm").submit(function() {
$("#modSearchValue").attr("name", $("#textOrHandle").is(":checked") ? "text" : "handle");
// let the form submit!
});
You have multiple ways to do it. Why can't you store original URL in a global variable (kept outside your functions like form submit etc.)
If you do not want that you can use window.location.hash which will return all the GET params you are sending. Using split you will be able to get exact parameter that you want. If you still need help, I will post the code.
Quickest solution: If, for this code, window.location should always be http://localhost/search/?mod=all, then you don't even need to say var locale = window.location. Just say var locale = "http://localhost/search/?mod=all" and you avoid the problem.
​var s = window.location.hostname; // gets the hostname
var d = window.location.protocol; // gets the protocol
var g = window.location.search; // gets all the params
var x = g.split("&"); // split each parameter
var url = d+"//"+s+x[0]; // makes url you want
alert(url);​​​​ // just for chill

Categories

Resources