I am trying to find a way how to store form data in local storage to show them even if user refresh page. For whole form it is no problem, but I have object with image files as part of form and I am not able to find the way how to store it.
My data object is for ex. like this:
{file_9wyh8: File, file_cwjg0: File}
My output after get data from localstorage is without files:
{file_9wyh8: {…}, file_cwjg0: {…}}
I need to store data object bcz, there are files ordered as user see them on page. Due to this it is not possible to use directly filereader.
And this is my code:
// The unload event is sent to the window element when the user navigates away from the page for ex. page refresh
$(window).on('unload', function() {
// Save values of form fields to local storage
$(':file, :checkbox, select, textarea, input').each(function() {
// Due to JS added input instead of select, need to get value from input + add to storage just checked items
if ( !$(this).hasClass('add-item__select') && !$(this).is(':checkbox') && !$(this).is(':file') ) {
// Save value of field to local storage
localStorage.setItem($(this).attr('name'), $(this).val());
} else if ( $(this).is(':checked') && !$(this).is(':file') ) {
// Save just name of checkbox which is checked
localStorage.setItem($(this).attr('name'), $(this).val());
} else if ( $(this).is(':file') ) {
dataToString = JSON.stringify(data);
localStorage.setItem('file', dataToString);
}
})
});
// Get values form local storage if page is refreshed
$(window).on('load', function() {
// Save values of form fields to local storage
$(':file, :checkbox, select, textarea, input').each(function() {
// If input has this class then do not save value
if ( !$(this).hasClass('add-item__select') && ( !$(this).is(':checkbox' ) && !$(this).is(':file') ) ) {
// Get value of field
fieldValue = localStorage.getItem($(this).attr('name'));
// Show value of field if fieldValue is not empty
if (fieldValue !== 'null') $(this).val(fieldValue);
$(this).addClass('black-text');
// Done action just for checkbox
} else if ( $(this).is(':checkbox') && !$(this).is(':file') ) {
// Get value of field
fieldValue = localStorage.getItem($(this).attr('name'));
// If chekcbox name is same as saved in local storage then set as checked
if ( fieldValue === $(this).val() ) $(this).prop('checked', true);
// Remove checkbox value in localstorage each time - bcz of change checked checkboxes
localStorage.removeItem(fieldValue);
} else if ( $(this).is(':file') ) {
// Get whole object data from localstorage
var dataStringFromLocalStorage = localStorage.getItem('file');
var dataFromLocalStorage = JSON.parse(dataStringFromLocalStorage);
console.log(dataFromLocalStorage);
$.each(dataFromLocalStorage, function(index, value) {
/*
// create temp url to img object for creating thumbnail and append img with temp src to thumbnail__wraper div
$('.thumbnail__wrapper').append('<div class="thumbnail" id="file_'+ mark +'"><img class="imageThumb" src="' + url + '" title="' + upload.name + '"/><br/><a class="remove">Zmazať</a></div>');
$('.add-item__add-photo-btn-area').find('p').hide();
// set up first image as main image - marked by label
var firstImg = $('.thumbnail__wrapper').children().first();
$('<p class="main-img">Hlavná fotka</p>').appendTo(firstImg);
// Change photo number status
$('#photo-num').text('Fotky ' + count + '/50');
*/
})
}
})
I tried also alternatives found in this question, but it did not help me.
How can I serialize an input File object to JSON?
Related
I started to do dropdown list instead select bcz it is not possible to stylize but I did not think to future and now I found that if I want to save data from form to db I need to get ids via $_POST instead of names.
For ex. I have dropdown list with status of product:
New
Old
Handmade
If I want to save chosen sattus for chosen product it is better for me to get ID of status option. Bcz my table is like this:
item_id | option_value
1 | 1
If I send name as "old" via $_POST, I need to get its ID from another table before insert it.
I created dropdown list like this:
/* SELECT REPLACED BY DIV JS */
var select = $('.add-item__select').hide(); // Hide original select options
// Replace each select by div
select.each(function() {
var selectVal = $(this).find('.add-item__select-main').text(),
name = $(this).attr('name');
newDropdownDiv = $('<input class="add-item__input-select" name="' + name + '" placeholder="' + selectVal + '" readonly required><i class="arrow down"></i></input>')
.insertAfter($(this))
.css({paddingLeft: '0.3em', cursor: 'pointer'});
});
Each SELECT has addaed INPUT after it.
If I want to show shosen vale from dropdown list I need to show it in this way:
$('.add-item__input-select').val("text copied from list");
After this if I add ID of option to input in this way:
$('.add-item__input-select').attr("value", optionID);
Then If I want to serialize all fields values from form and this is point,
$('.add-item__form').serializeArray()
I get two results for status:
name: "status", value: "text copied from list"
and
name: "status", value: optionID
But I need just optionID.
I have everything optimized for this structure, so I would like to ask you if there is some easy way how to fix it or I need to modify structure.
I am thinking to remove INPUT and just change SELECT opacity to 0 instead of display none and use SELECT for form data serialize. But then I will need to replace all INPUTs by some DIV which will hold text of chosen option and also change everything else connected with it. For ex, if user clicked on INPUT the label was showed above it.
Thanks for advices
I found one solution but I have problem that it is working just if user will not refresh page. In DOM is everything the same after refresh but serializeArray() get just input text value and not value="ID" after page refresh.
I just remove these values which I do not want from FormData.
// Send formData to upload.php
$('.add-item__form').on('submit', function() {
event.preventDefault();
event.stopPropagation();
if ( checkFieldsIfNotEmpty() == true ) {
var formDataFields = $('.add-item__form').serializeArray(), // Get all data from form except of photos
count = Object.keys(data).length; // count fields of object
// Fill formData object by data from form
$.each(formDataFields, function(index, value) {
if ( value.name === 'category' && !$.isNumeric(value.value) || value.name === 'subcategory' && !$.isNumeric(value.value) ) {
// do nothing
} else if ( (value.name.indexOf('filter') >= 0) && !$.isNumeric(value.value) ) {
// do nothing
}
else {
formData.append(value.name, value.value); // add name and value to POST data
}
});
// foreach - fill formData with photos from form
$.each(data, function(index, value) {
formData.append('files[]', value);
});
uploadData(formData); // send data via ajax to upload.php
}
});
Can you advice me what can be problem?
In a wordpress website I want that when someone fills a product form (select attributes etc) and clicks buy now, if is not logged in then he is redirected to login form. On succesfull login I want to get the submitted form contents from localstorage, fill the form and then submit the form automatically.
Is that possible?
I found that I can store the submitted form like this (but how I can refill the form automatically?):
$(document).ready(function() {
$('form').submit(function(e) {
e.preventDefault();
var formFields = $(this).serialize();
localStorage.setItem('myForm', formFields);
//data = localStorage.getItem('myForm'); //retrieve it later
});
});
You should be able to retrieve data from localStorage, get your form fields using DOM selectors and fill their values using the data from localStorage.
In vanilla JS, you can probably do the following:
document.addEventListener('load', () => {
// check if user is logged in according to your usecase
if(isLoggedIn()) {
try {
const formData = JSON.parse(localStorage.getItem('myForm'));
// get input fields. If you have some unique id associated to them, you can use document.querySelector(`#${inputId}`);
const inputFields = document.querySelectorAll('input');
for(let i = 0; i<inputFields.length; i++) {
const inputId = inputFields[i].getAttribute('data-id');
// fallback to empty string in case it is not found in localStorage object
inputFields[i].value = formData[inputId] || '';
}
} catch(e) {
// handle error
}
// Now you have the form input fields pre-filled, add custom logic from here ..
}
})
/*
--- Sample DOM ----
<input data-id="name" />
<input data-id="city" />
---- Form fields saved in localStorage ---
{ name : 'Naruto', city: 'Leaf Village' }
*/
How can you make the browser remember what the user typed in the form, which has not yet been submitted and make the page refreshing not affect the data entered?
I have a form in which the user enters a number. Initially the form has 0 by default. I am storing the data in localStorage, so the browser can remember the data. However, when the page is refreshed, the user-entered data disappears and 0 is displayed by default. (still the localStorage data exists for it)
I tried to use jQuery's
$(".formClassName").val(localStorage.getItem(key));
but it does not work. Can anyone give me a piece of advice on this?Thank you in advance.
Edited: My form looks like this:
<form>
<!--There are multiple forms, and the only difference among them is the "name" attribute -->
Enter a number <input type="text" value="0" class"dataEntered" name="****">
<!--The button below saves the data entered in the above form -->
<input type="button" class="savedata" value="Save Value" name="****">
</form>
And I am adding the data to localStorage like below:
//JavaScript
<script>
//Using on because the website retrieves the above form dynamically
$(document).on("click", ".saveData", function(e){
//retrieve the number entered in the form
var userNum = $(this).siblings(".dataEntered").val();
//retrieve the value in name attribute
var thisFormName = $(this).attr("name");
//store the data
localStorage.setItem(thisFormName, userNum);
//Now that the save button has been pressed (not submitted to the
//server yet), and the data is stored in localStorage, I want to
//the page to show the number in userNum even after you refresh the page
//but this does not work.
$(".dataEntered").val(localStorage.setItem(thisFormName));
});
</script>
use cookie:
function addCookie(sName,sValue,day) {
var expireDate = new Date();
expireDate.setDate(expireDate.getDate()+day);
document.cookie = escape(sName) + '=' + escape(sValue) +';expires=' + expireDate.toGMTString();
}
function getCookies() {
var showAllCookie = '';
if(!document.cookie == ''){
var arrCookie = document.cookie.split('; ');
var arrLength = arrCookie.length;
var targetcookie ={};
for(var i=0; i<arrLength; i++) {
targetcookie[unescape(arrCookie[i].split('=')[0])]= unescape(arrCookie[i].split('=')[1]);
}
return targetcookie;
}
addCookie('type','1',1024);
var cookiesample = getCookies();
$(".formClassName").val(cookiesample.type);
cookiesample.type could be remembered unless the cookie is deleted.
Checkout this codepen I have it shows a functional solution to the problem. Also you need to make sure jQuery script checks if the DOM is ready, you can do that by using $(function() { }) a short hand for .ready().
$(function() {
var input = $("[type=text]");
var thisFormName = input.attr("name");
if (localStorage.getItem(thisFormName)) {
var value = parseInt(localStorage.getItem(thisFormName));
input.val(value);
}
$(document).on("click", ".savedata", function(e) {
var userNum = input.val();
localStorage.setItem(thisFormName, userNum);
input.val(localStorage.getItem(thisFormName));
});
});
i know we can manally log any input value by its selector
console.log('inputName='+$('#inputId').val()+'....)
But is there -simpler- a way to log all input values? if it's posible to do it when any input changes
You can use serialize to serialize the form elements to a string for logging. It follows the same rules for including or not including elements as normal form submission. The only caveat is that the content of input type="file" fields isn't serialized, for perhaps obvious reasons.
To fire it when any of the inputs changes:
$("form :input").change(function() {
console.log($(this).closest('form').serialize());
});
Live demo using the form shown in the documentation
You may get in form of query string using $("form").serialize().
This would log the form every time anything changes:
$("form :input").change(function(){
console.log($("form").serialize());
});
Edit:
Removed my focusout suggestion, as I realized that change is actually only fired when the element looses focus.
I made this little component:
$("form :input").change(function() {
var fields = $(this).closest('form').serialize();
serialize_to_console( fields );
});
/*
SERIALIZE TO CONSOLE
Transforms string to array and show each param in console if not empty */
var serialize_to_console = function( serialized ) {
var splited_serialized = serialized.split('&');
$.each( splited_serialized, function(index, key) {
var input = key.substr(0, key.indexOf('='));
var value = key.substr( key.indexOf('=') + 1 );
if( value !== '' )
console.log( '[' + input + '] = \'' + value + '\'' );
});
}
Enjoy!
Please look at the following code. When the form gets submitted, is it actually submitting the values I have entered i.e. val(50) or at the point it serialzies does it just get data from the form on the actual html page?
// stop all forms from submitting and submit the real (hidden) form#order
$('form:not(#order)').submit(function(event) {
alert($(this).attr('id'));
//event.preventDefault();
if($(this).attr('id')==='quick2a'){
alert('quick2a being submitted');
//submitQuick2a();
$('form#order input[name=custom_channels]').val(50);
var name = 'het-';
name += $('form#order input[name=platform]').val('astsk');
name += '-ga-';
name += $('form#order input[name=license]').val('floating');
$('form#order input[name=productname]').val(name);
$.post('/store/cart/add/ajax/', $('form#order').serialize(), function() {
document.location.href = '/store/checkout';
});
}else{
//
}
I want those values to be set in the form regardless of what is set by the user, am I doing this correctly?
Thanks all
Why not just construct the data directly instead of stuffing it into a form and then grabbing the values via serialize?
$('form').submit(function(event) {
if($(this).attr('id')==='quick2a') {
var data = {
'custom_channels': 50,
'platform' : 'astsk',
'license' : 'floating',
'productname' : 'het-astsk-ga-floating'
};
$.post('/store/cart/add/ajax/', data, function() {
document.location.href = '/store/checkout';
});
}else{
//
}
return false;
});
It gets the values from the HTML page... but by calling .val(...) you're setting the values on the HTML page, so your code will work as you want it to.