I have a form that uses jqGrid
for a section of the form. This section displays user info that can be selected via the checkbox. On the review page there is an option to edit the form and I'm trying to retain the checkbox selections during this process.
I'm trying to use window.localStorage
for this however I'm not sure how to setItem properly. I'm calling getItem in the loadComplete and my coding may not be quite correct here either. What I have now, when a user goes to edit, selects the first item in the jqGrid instead of the actual saved item. I'm guessing because I haven't properly setItem. Can anyone offer guidance?
$.jgrid.gridUnload("#list");
myGrid = $("#list").jqGrid({
url: baseURL + '/scripts/get_user_list.php' + urlString,
datatype: "json",
mtype: 'POST',
width: 660,
height: '100%',
pager: '#pager',
rowNum: 10,
rowList: [20, 30, 40, 50, 60],
sortname: 'id',
sortorder: "asc",
viewrecords: true,
multiselect: true,
repeatitems: false,
imgpath: '/scripts/jquery-ui/images',
colNames: ['id', 'Building', 'Company ID', 'Description', 'Individual Name', 'SECCode'],
colModel: [
{name: 'id', index: 'id', jsonmap: 'id', hidden: true, width: 20},
{name: 'Building', index: 'Building', jsonmap: 'Building', hidden: true, width: 20},
{name: 'CompanyId', index: 'CompanyId', jsonmap: 'CompanyId', width: 110},
{name: 'Description', index: 'Description', jsonmap: 'Description', sortable: true, width: 300},
{name: 'IndName', index: 'IndName', jsonmap: 'IndName', width: 200},
{name: 'UsrNum', hidden: true, index: 'UsrNum', jsonmap: 'UsrNum'}
],
jsonReader: {
repeatitems: false,
root: 'rows',
id: '0',
cell: '',
subgrid: {
root: 'rows',
id: '0',
cell: '',
repeatitems: false
}
},
// subgrid support
subGrid: true,
subGridUrl: baseURL + '/scripts/get_user_list.php' + urlString,
subGridModel: [{
name: ['Date', 'ID'],
params: ['CompanyId'],
align: ['center', 'right'],
width: [150, 80]
}
],
ondblClickRow: function (id) {
$('#recId').val(id);
},
beforeRequest: function () {
blnGridLoading = true;
// console.log("beforeRequest(); setting blnGridLoading=true");
fnValidateAccount(); // Check that user has data available
},
loadComplete: function () {
$(':checkbox').each(function () {
var status = localStorage.getItem(this.id) === "false" ? false : true;
$(this).prop("checked", status);
});
blnGridLoading = false;
// console.log("loadcomplete(); setting
blnGridLoading = false;
// ");
for (swap in arySwap) {
if (typeof arySwap[swap]['CompanyId'] != 'undefined') {
$("#list").jqGrid('setSelection', arySwap[swap]['CompanyId']); // select companyId
}
}
fnValidateAccount(); // Check that user has data available
},
});
Here's the localStorage.getItem in loadComplate, isolated from the rest of the code:
$(':checkbox').each(function () {
var status = localStorage.getItem(this.id) === "false" ? false : true;
$(this).prop("checked", status);
});
Here's what I tried for setItem and where I'm not sure where to place this or if this is the correct way to go.
$(':checkbox').on('change', function () {
//set the check value of checkbox
localStorage.setItem(this.id, this.checked);
});
Your current placement of the getItem
is correct. You should put the setItem
block there too. Inside the loadComplete
which means once the jqGrid
is loaded, your getItem
would run, also the setItem
events would be bound to the checkboxes.
localStorage only supports storing key value pairs and the values can be String
only. Which means if you set a key customCheckbox
to true
and run a query for that key, the return value would be "true"
localStorage.setItem('test', true); // item set
localStorage.getItem('test') // returns "true"; string, not boolean.
However, there is a way to define one key and store an object to that. You should use JSON.stringify()
before storing and JSON.parse()
after retrieving.
let person = {name: 'John', age: 30, weight: 60} // a pure object.
localStorage.setItem('testPerson', JSON.stringify(person)); // object stringified;
localStorage.getItem('testPerson') // returns a stringified version of 'person' object;
// to use the stored stringified object like a regular object, you need to parse it.
person = JSON.parse(localStorage.getItem('testPerson'));
You have used different keys for each different checkboxes, thus your keys and values are wide open for the whole script or some other script on the same page. You might accidentally end up deleting or modifying the values of those keys, or maybe not. Also, other pages can modify those items, as they are on localStorage. So try to set as unique keys as possible.
Note: Open the browser inspector and check the storage
tab to check your localStorage status, there might be a panel at the left with sessionStorage
and localStorage
Now let's talk about your current logic. It looks like at the initial page load, when there is no keys sot to localStorage
, all your checkbox would be checked. Is that intended ?
Even if it is, let's break it down:
var status = localStorage.getItem(this.id) === "false" ? false : true;
localStorage.getItem('key')
would return null
if there is no such key set. so null === "false"
returns false
and your ternary logic sets the status
to true
Hence:
$(this).prop("checked", status); // sets all the checkboxes to checked at initial page load;
What you should do is:
object
, as null is a typeof object
status
to false
immediately. because when you set the value to true
or false
it'll be a string type, not object.'true'
and 'false'
and set accordingly.Here is the final logic:
let status = typeof localStorage.getItem($(this).attr('id')) === 'object' ? false : localStorage.getItem($(this).attr('id')) === 'true';
Finally some code, have a look at the snippet, Note that the browser will return an error, because an iframe trying to modify localStorage. but extract the code at your end to view the results.
$(document).ready(function() {
$(':checkbox').each(function() {
let status = typeof localStorage.getItem($(this).attr('id')) === 'object' ? false : localStorage.getItem($(this).attr('id')) === 'true';
$(this).prop('checked', status);
// console.log(status, typeof localStorage.getItem($(this).attr('id')))
});
// setItem.
$(':checkbox').on('change', function() {
//set the check value of checkbox
localStorage.setItem($(this).attr('id'), $(this).prop('checked'));
console.log('updated, ', $(this).attr('id'));
console.log(localStorage);
});
$('#clear').on('click', function() {
localStorage.clear();
});
});
h3 {
margin: 40px 0;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js'></script>
<div class="container">
<div class="row">
<div class="col-12">
<h3>Checkboxes status to LocalStorage</h3>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<label class="custom-control-label" for="customCheck1">One</label>
</div>
</div>
<div class="col-12">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck2">
<label class="custom-control-label" for="customCheck2">Two</label>
</div>
</div>
<div class="col-12">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck3">
<label class="custom-control-label" for="customCheck3">Three</label>
</div>
</div>
<div class="col-12">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck4">
<label class="custom-control-label" for="customCheck4">Four</label>
</div>
</div>
<div class="col-12">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck5">
<label class="custom-control-label" for="customCheck5">Five</label>
</div>
</div>
<div class="col-12">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck6">
<label class="custom-control-label" for="customCheck6">Six</label>
</div>
</div>
<div class="col-12">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck7">
<label class="custom-control-label" for="customCheck7">Seven</label>
</div>
</div>
<div class="col-12">
<div class="form-group"></div>
<button id="clear" type="button" class="btn btn-danger">Clear LocalStorage</button>
</div>
</div>
</div>