Im writing a function to export data pulled from C# to a csv file in JavaScript. The data is trying to be passed into an active webpage with live data. The goal is to export said data from C# string to the clients window hence the transfer to JavaScript (if my understanding is right). Then the JavaScript function in the page will download to the users window.
My issue is why am I have the invalid export data, please provide an array of objects output when I think I provide it one?
C# Code:
protected string test()
{
MyRequest request = new MyRequest();
request.Id = "TEST";
// Cant post this class but this is what I do
var tmp = new ExistingClassOfMine();
// pulls the data from the existing class through GetResponse();
// Then convert to json string
string data = JsonConvert.SerializeObject(tmp.GetResponse(request));
// Data found from breakpoint: {"Slot1":[{"Name":"TJ", "ID":"123"},{"Name":"Joe","ID:456"}], "TotalCount":2}
return data;
}
JavaScript:
function exportToExcel() {
console.log("Exporting to Excel");
isExporting = true;
const fileName = 'NameList';
const exportType = 'csv';
var data = <%=this.test()%>;
var readData = data["Slot1"];
var myArray = [];
// Followed a stack article to create this
for (var i in readData) {
myArray.push(readData[i]);
}
// Logging stuff for debugging
console.log("Data from C#");
console.log(data);
console.log(typeof (data));
console.log("Data we want to export");
console.log(readData);
console.log("Parsed Data?");
console.log(myArray);
// fails here with the error Invalid export data, please provide an array of objects
// which I thought I did with my for loop up a few lines
window.exportFromJSON({myArray, fileName, exportType});
isExporting = false;
}
function onRequestStart(sender, args) {
if (isExporting) {
args.set_enableAjax(false);
}
}
Log output:
Look, your triying to change the name of the key which is sent to exportFromJSON. The right way to name the key is data no myArray.
Change:
myArray
to
data
or assign myArray to data key
window.exportFromJSON({data:myArray, fileName, exportType});
I'm writing a chrome extension, and I can't store an array. I read that I should use JSON stringify/parse to achieve this, but I have an error using it.
chrome.storage.local.get(null, function(userKeyIds){
if(userKeyIds===null){
userKeyIds = [];
}
var userKeyIdsArray = JSON.parse(userKeyIds);
// Here I have an Uncaught SyntaxError: Unexpected token o
userKeyIdsArray.push({keyPairId: keyPairId,HasBeenUploadedYet: false});
chrome.storage.local.set(JSON.stringify(userKeyIdsArray),function(){
if(chrome.runtime.lastError){
console.log("An error occured : "+chrome.runtime.lastError);
}
else{
chrome.storage.local.get(null, function(userKeyIds){
console.log(userKeyIds)});
}
});
});
How could I store an array of objects like {keyPairId: keyPairId,HasBeenUploadedYet: false} ?
I think you've mistaken localStorage for the new Chrome Storage API.
- You needed JSON strings in case of the localStorage
- You can store objects/arrays directly with the new Storage API
// by passing an object you can define default values e.g.: []
chrome.storage.local.get({userKeyIds: []}, function (result) {
// the input argument is ALWAYS an object containing the queried keys
// so we select the key we need
var userKeyIds = result.userKeyIds;
userKeyIds.push({keyPairId: keyPairId, HasBeenUploadedYet: false});
// set the new array value to the same key
chrome.storage.local.set({userKeyIds: userKeyIds}, function () {
// you can use strings instead of objects
// if you don't want to define default values
chrome.storage.local.get('userKeyIds', function (result) {
console.log(result.userKeyIds)
});
});
});
I am new to session storage and I am trying to take two stored values and substract them then play it back in innerhtml. I don't know how to do that.
(index):897 Uncaught TypeError: Cannot read property 'getElementById' of undefined
let propertyPrice = document.getElementById("propertyPrice");
if (sessionStorage.getItem("propertyPriceStored")) {
propertyPrice.value = sessionStorage.getItem("propertyPriceStored");
}
propertyPrice.addEventListener("change", function() {
sessionStorage.setItem("propertyPriceStored", propertyPrice.value);
});
let deposit = document.getElementById("deposit");
if (sessionStorage.getItem("depositStored")) {
deposit.value = sessionStorage.getItem("depositStored");
}
deposit.addEventListener("change", function() {
sessionStorage.setItem("depositStored", deposit.value);
});
let loanAmount = propertyPrice - deposit;
loanAmount.document.getElementById("loanAmountResult").innerHTML;
I have managed to get the console log to show numbers on reloading of the page but i can get it to happen then and there on the page.
let deposit = document.getElementById("deposit");
// See if we have an autosave value
// (this will only happen if the page is accidentally refreshed)
if (sessionStorage.getItem("depositStored")) {
// Restore the contents of the text field
deposit.value = sessionStorage.getItem("depositStored");
}
// Listen for changes in the text field
deposit.addEventListener("change", function() {
// And save the results into the session storage object
sessionStorage.setItem("depositStored", deposit.value);
});
let loanAmount = propertyPrice.value - deposit.value;
console.log(loanAmount)
loanAmount.addEventListener("change", function() {
document.getElementById("loanAmountResult").innerHTML;
});
The goal is the user can save up to 7 field vals in obj userA, logout, log back in and the saved vals are there, retrievable. Specific to each user.
I am trying to create an object i.e. userA and update it, as the
user saves each field value (i.e. BaseMap: basemapSaved), save
the updated state in local storage, then retrieve saved state using
local storage. So, when the user logs out, then logs back in, their
saved data is still there specific to their username.
Below is my most recent attempt (full js): Any pointers? Am I going about this all wrong?
UPDATED ATTEMPT BELOW WITH BOUNTY.
I am simply trying to save an object of data and a field within it (i.e. userA.BaseMap.basemapSaved;) with local storage, on click.
I later want to parse that saved object in local storage, get that field, and update my API object i.e. object.data.field (userA.BaseMap.basemapSaved;) with the value saved and gathered. I can do this pro grammatically pretty easy, but the idea is to save the state per user, so they can log out, then log back in and have their selection saved.
// Here I am trying to initialize the variables
var currentUser;
var basemapSaved;
var userA[key] = {};
// This function I am getting the logged in username, I want to set this as the object key in userA i.e. userA[key]
function checkUser() {
var node = document.querySelectorAll("span.username")[0];
currentUser = node.textContent;
var key = currentUser;
console.log("current user is:" + key);
}
// This is just a handler to wait to my basemap gallery loads before trying to save
var basemapMod = document.getElementsByClassName("basemap")[0];
basemapMod.addEventListener('click', ()=>{
setTimeout(
function() {
BaseMapSaver();
}, 2000);
});
function BaseMapSaver() {
savebtnBM.addEventListener('click', ()=>{
checkUser();
// This is where I get the data from my API to save, gathers fine
basemapSaved = app.widget.Manager.Gallery.activeBasemap.Item.id;
// Below I am trying to set it, at first without the object key but would like to use the key
var saveMap = localStorage.setItem('userA', JSON.stringify(userA));
console.log(userA);
});
}
// Home button
var defaultViewHbtn = document.getElementById("home");
defaultViewHbtn.addEventListener('click', ()=>{
checkUser();
// Here I try to parse the value from local storage object
const userAParseValue = JSON.parse(localStorage.getItem('userA'));
// Errors with Uncaught TypeError: Cannot read property 'BaseMap' of undefined
userBaseMap = userAParseValue.userA.BaseMap.basemapSaved;
console.log(userBaseMap);
app.widget.Manager.Gallery.activeBasemap.Item.id = {
portalItem: {
id: userA.BaseMap.basemapSaved // this is where I want to load saved value from local storage object
}
};
});
It Should work check addEventListener function:-
Hbtn.addEventListener('click', ()=>{
checkUser();
const userAParseValue = JSON.parse(localStorage.getItem('userA'));
userBaseMap = userAParseValue.userA.BaseMap.basemapSaved;
console.log(userBaseMap);
myApp.widgets.bigData.Gallery.map = {
Item: {
id: userA.BaseMap.basemapSaved
}
};
});
You can use localStorage and the approach you're trying to make work, but you'll end up with localStorage having a separate object for each user. If that's OK then you use localStorage after load to check if a user is logged in and then load the users' data. Then update the data to the localStorage when the values change. You may check inline comments for details:
HTML if there is a user logged in:
<h3>User <span class="username"><?php echo $user; ?></span> is logged in</h3>
<form method="post">
<input type="hidden" name="action" value="logout"/>
<button type="submit">Logout</button>
</form>
<hr/>
<div>
<h2>User counter: <span id="counter"></span></h2>
<div>
<button id="inc-counter">Increase</button>
<button id="dec-counter">Decrease</button>
</div>
</div>
Javascript to handle localStorage:
// Get user stored on page HTML
const user = document.querySelector("span.username");
// Something to update/alter using user data and/or user input
const counter = document.querySelector("#counter");
const incCounter = document.querySelector("#inc-counter");
const decCounter = document.querySelector("#dec-counter");
if(user) { // If there is a user logged in
// Get the username
const username = user.textContent;
// Get the localStorage the belongs to that user (using username for key)
let storageUser = JSON.parse(localStorage.getItem(username) || 'null');
// Use default user object if the user has no previous settings stored
let currentUser = storageUser || {
BaseMap: {
counter: 0
}
};
// Display the user data
function displayCounter() {
const BaseMap = 'BaseMap' in currentUser ? currentUser.BaseMap : {};
let userCounter = 'counter' in BaseMap ? BaseMap.counter : 0;
counter.textContent = userCounter;
}
// Alter the user data and save it to localStorage user settings object
function alterCounter(addToCounter) {
// Check if BaseMap object exists or default
const BaseMap = 'BaseMap' in currentUser ? currentUser.BaseMap : {};
// Check if data exists or default
let userCounter = 'counter' in BaseMap ? BaseMap.counter : 0;
// Alter user data according to user input
userCounter += addToCounter;
// Change user settings object
currentUser['BaseMap']['counter'] = userCounter;
// Save user settings object
localStorage.setItem(username, JSON.stringify(currentUser));
// Display altered user data
displayCounter();
}
// Initialize by display retrieved/default data
displayCounter();
// Add event listeners to user inputs
incCounter.addEventListener('click', () => alterCounter(1));
decCounter.addEventListener('click', () => alterCounter(-1));
}
You can check an online example that I've made at the link below:
https://zikro.gr/dbg/so/60010743/ (Users userA, userB both with password 1234 can be used for demonstration)
That will work and retrieve/save user data to the localStorage using username for each user. Keep in mind that this method will only save the user settings for a specific browser location. If you want to have user settings when the user logs in from anywhere, then you should go with the traditional workaround which is based on server session, but it's not so flexible when it comes to user settings because you'll have to update each data/setting using server requests each time the user makes a change which it's possible but it requires server + client implementation.
A combination of both server side settings storage + server session + client localStorage would be the best approach to this situation.
here is my answer
<html>
<body>
<span class="border username">121</span>
<div class="border basemap">Base Map</div>
<div class="border saveBtn">Save</div>
<div id="home" class="border">Home</div>
<style>
.border{
border: solid gray 1px;
border-radius: 2px;
text-align: center;
background: #eee;
margin: 5px;
width: 100px;
}
</style>
<script type="text/javascript">
// Here I am trying to initialize the variables
var key = 1;
var currentUser;
var basemapSaved;
var userA = {
BaseMap: {
id: 1234
}
};
var app = {
widget: {
Manager: {
Gallery: {
activeBasemap: {
Item: {
id: {
portalItem: {
id: 1234 // this is where I want to load saved value from local storage object
}
}
}
}
}
}
}
};
// This function I am getting the logged in username, I want to set this as the object key in userA i.e. userA[key]
function checkUser() {
var node = document.querySelectorAll("span.username")[0];
currentUser = node.textContent;
var key = currentUser;
console.log("current user is:" + key);
}
// This is just a handler to wait to my basemap gallery loads before trying to save
var basemapMod = document.getElementsByClassName("basemap")[0];
basemapMod.addEventListener('click', ()=>{
console.log("basemapMod click");
setTimeout(
function() {
BaseMapSaver();
}, 2000);
});
function BaseMapSaver() {
var savebtnBM = document.getElementsByClassName("saveBtn")[0];
savebtnBM.addEventListener('click', ()=>{
console.log("savebtnBM click");
checkUser();
// This is where I get the data from my API to save, gathers fine
basemapSaved = app.widget.Manager.Gallery.activeBasemap.Item.id.portalItem.id;
/** saving users, instead of userA */
const userAParseValue = JSON.parse(localStorage.getItem('users'));
userA.BaseMap.basemapSaved = basemapSaved;
const finalUsers = {...userAParseValue, userA}
// Below I am trying to set it, at first without the object key but would like to use the key
var saveMap = localStorage.setItem('users', JSON.stringify(finalUsers));
console.log(userA);
});
}
// Home button
var defaultViewHbtn = document.getElementById("home");
defaultViewHbtn.addEventListener('click', ()=>{
console.log("defaultViewHbtn click");
checkUser();
// Here I try to parse the value from local storage object
const userAParseValue = JSON.parse(localStorage.getItem('users'));
// Errors with Uncaught TypeError: Cannot read property 'BaseMap' of undefined
userBaseMap = userAParseValue.userA.BaseMap.basemapSaved;
console.log(userBaseMap);
app.widget.Manager.Gallery.activeBasemap.Item.id = {
portalItem: {
id: userA.BaseMap.basemapSaved // this is where I want to load saved value from local storage object
}
};
});
</script>
</body>
</html>
I changed a few structures which were not coherent. Saving and loading them was causing discrepancies. I also suggest storing all users in a single object and accessing the data from userMap because multiple users can use same browser.
Based on the two requirements that you have defined in your original question, this should do what you ask.
The goal is the user can save up to 7 field vals in obj userA, logout, log back in and the saved vals are there, retrievable. Specific to each user.
I am trying to create an object i.e. userA and update it, as the user saves each field value (i.e. BaseMap: basemapSaved), save the updated state in local storage, then retrieve saved state using local storage. So, when the user logs out, then logs back in, their saved data is still there specific to their username.
// retrieve user from localstorage. defaults to {}
// This looks to retrieve the user from local storage by username.
// Returns a `userObj` an object with two properties.
// `username` - the name of the user
// `user` - the stored object that was retrieved from local storage.
// defaults to {} if nothing in user storage
// Not a good strategy btw, a lot of us share the same names :)
function getUser(username) {
let user = localStorage.getItem(username) || {};
try {
user = JSON.parse(user);
} catch (e) {
user = {};
}
return { username, user }
}
// Store user object in localstorage
// Store a user in local storage, keyed by their username
function setUser(username, user) {
localStorage.setItem(username, JSON.stringify(user));
}
// set a key/ value on user object in localstorage
// Don't allow anymore than 7 properties to be stored on the user object
function setUserProperty(userObj, key, value) {
let { username, user } = userObj;
if (Object.keys(user).length > 7) {
throw new Error('user properties exceeds 7')
}
user[key] = value;
setUser(username, user);
}
// modified to return a user from local storage or {}
function checkUser() {
var node = document.querySelectorAll("span.username")[0];
const currentUser = node.textContent;
return getUser(currentUser);
}
// This is just a handler to wait to my basemap gallery loads before trying to save
var basemapMod = document.getElementsByClassName("basemap")[0];
basemapMod.addEventListener('click', () => {
setTimeout(
function() {
BaseMapSaver();
}, 2000);
});
// Fyi Capitals indicate constructors - not functions!
function BaseMapSaver() {
savebtnBM.addEventListener('click', () => {
const userObj = checkUser(); // get the user from localstorage
const basemapSaved = app.widget.Manager.Gallery.activeBasemap.Item.id;
setUserProperty(userObj, 'basemap', basemapSaved) // store the basemap on the user object in local storage with the key 'basemap'
console.log(JSON.stringify(userObj));
});
}
var defaultViewHbtn = document.getElementById("home");
defaultViewHbtn.addEventListener('click', () => {
// get user from localstorage
const { user } = checkUser();
const userBaseMap = user.basemap
// if we have a store basemap
if (userBaseMap) {
app.widget.Manager.Gallery.activeBasemap.Item.id = {
portalItem: {
id: userBaseMap // load it
}
};
}
});
There are many ways to handle this depending upon your use case. You have specifically mentioned LocalStorage hence everyone is suggesting the same but cookies will fit your bill as well as long as you handle the expiry time properly for them.
Local Storage
Make an Object of fields you will like to store for that user
let obj = {'keyname' : value, 'keyname' : value};
//store it - mapping it with user
localStorage.setItem('userID', JSON.stringify(obj));
//retrieve and use on login success
let ret_obj= localStorage.getItem('userID');
Cookies
You can set an arbitrary expiration time and then you again have choice of choosing just one variable or store it as a JSON itself.
document.cookie = "userName=Robert; expires=Fri, 31 Dec 9999 23:59:59 GMT";
*Cookies will hold limited amount of data, as in not huge data (Which I don't think is the use case here because I checked your jsfiddle example, you are basically trying to store some data)
If you want to store JSON data in cookies check this out Click Here
*Why am I suggesting cookies? Many enterprises already do something similar for example even post logging out when you visit a website
they will display your name and ask you to sign-in, it is just a
personalisation addition.
I'm quite new to using storage settings in HTML/JavaScript. I'm building a hybrid app which is a not taking app on mobile using Phonegap. I want the user to type in a note name, then the note itself, and be able to save both by placing them into a jquery mobile list and putting them back on the home screen. My problem is that I can only save one note at a time. If I try to save another one, it just overwrites the previous one. How would I go about fixing it? Also, when I try refresh the browser the note disappears. Is this normal?
Please and thank you.
Here is the saving function I used:
function storeData() {
var i;
for (i=0; i<999; i++) {
var fname = document.getElementById('fname').value;
var wtf = document.getElementById('wtf').value;
localStorage.setItem('fname', fname);
localStorage.setItem('wtf', wtf);
}
var newEl = "<li><a href='#' id='savedNote'onclick='loadData'></a></li>"
document.getElementById("savedNote").innerHTML = localStorage.getItem("fname");
//try to create a new list element in main menu for this item being stored in
// and add an onclick load function for that
};
function loadData() {
var x;
for (x=0; x<999; x++) {
document.getElementById("fname").innerHTML = localStorage.getItem('fname', fnamei);
document.getElementById("wtf").innerHTML = localStorage.getItem('wtf', wtfi);
}
};
I'm not sure why you're using a loop for your functions. The storeData function looks 999 times for the value of #fname and #wtf, and save this 999x times in localStorage.fname and localStorage.wtf
This makes absolut no sense. Same Problem with your loadData function.
A nice way to save more then one string to the localStorage, is to create a javascript object, stringify it and then save it to the localStorage.
You only need to load the data from the localStorage, if you (re)load the page. But you need to save it to the localStorage, every time something changed, to be sure that the data in the localStorage is always up to date.
For display and manipulation on the page, you use the javascript object. in my example "myData". If you change something, you update your javascript object and then save it to the localStorage.
a side note. to be sure that the user don't overwrite something with a
identical name, you should use unique ids. like i did with the timestamp.
var postID = new Date().getTime();
Here a little example to show you a possible way. It's hard to code something functionally without your html code.
// Creating a object for all Data
var myData = {};
// Fill the Object with data if there is something at the LocalStorage
if (localStorage.myData){
loadDataFromLocalStorage();
}
function createNewPost(){
// Create a ID for the Post
var postID = new Date().getTime();
// Create a Object inside the main object, for the new Post
myData[postID] = {};
// Fill the Object with the data
myData[postID].fname = document.getElementById('fname').value;
myData[postID].wtf = document.getElementById('wtf').value;
// Save it to the LocalStorage
saveDataToLocalStorage();
// Display the Listitem. with the right postID
}
function loadPost (postID){
var singlePost = myData[postID];
// Display it
}
// A Helper Function that turns the myData Object into a String and save it to the Localstorage
function saveDataToLocalStorage(){
localStorage.myData = JSON.stringify(myData);
}
// A Helper Function that turns the string from the LocalStorage into a javascript object
function loadDataFromLocalStorage(){
myData = JSON.parse(localStorage.myData);
}
// Creating a object for all Data
var myData = {};
// Fill the Object with data if there is something at the LocalStorage
if (localStorage.myData){
loadDataFromLocalStorage();
}
function createNewPost(){
// Create a ID for the Post
var postID = new Date().getTime();
// Create a Object inside the main object, for the new Post
myData[postID] = {};
// Fill the Object with the data
myData[postID].fname = document.getElementById('fname').value;
myData[postID].wtf = document.getElementById('wtf').value;
// Save it to the LocalStorage
saveDataToLocalStorage();
// Display the Listitem. with the right postID
}
function loadPost (postID){
var singlePost = myData[postID];
// Display it
}
// A Helper Function that turns the myData Object into a String and save it to the Localstorage
function saveDataToLocalStorage(){
localStorage.myData = JSON.stringify(myData);
}
// A Helper Function that turns the string from the LocalStorage into a javascript object
function loadDataFromLocalStorage(){
myData = JSON.parse(localStorage.myData);
}
Store an array.
var arrayX = [];
arrayX.push(valueY);
localStorage.setItem('localSaveArray', arrayX);