49813

Save chrome extension options to chrome.storage?

Question:

I'm making a chrome extension that has an <em>options.html</em> page.

On the options page I have 3 checkboxes. When one of the checkboxes is checked/unchecked the value of that checkbox is saved to- or removed from chrome.storage using <em>chrome.storage.sync.set()</em>. But I can't seem to retrieve the data once it is saved using <em>chrome.storage.sync.get()</em>.

Here's the code I have:

<strong>options.html:</strong>

<div class="checkboxes"> <input id="test1" name="test1" type="checkbox"> <input id="test2" name="test2" type="checkbox"> <input id="test3" name="test3" type="checkbox"> </div>

<strong>options.js:</strong>

$(document).ready(function() { var storage = chrome.storage.sync; //Retrieve existing settings $(':checkbox').each(function() { $(this).prop('checked', function() { var name = this.name; storage.get(name, function(test){ console.log(test[name]); }); }); }); $(".checkboxes").on("change", ":checkbox", saveSettings); //Save or delete settings function saveSettings() { var name = this.name; if($(this).is(':checked')) { storage.set({name:'checked'},function(){ console.log("saved"); }); } else { storage.remove(name, function(){ console.log("removed"); }); } } });

<strong>Above outputs:</strong>

console.log(test[name]); > undefined console.log("saved"); > saved console.log("removed"); > removed

Why do I get "undefined"?

I tired the same thing using <em>localStorage</em> which worked fine on only <em>option.js</em>. But when I tried to retrieve the stored data on <em>background.js</em> it didn't work. I figured their <em>localStorage</em> details are not accessible to each other.

I should also mention I'm not the best at javascript/jquery and I'm still learning, so please excuse my mistakes.

Answer1:

You've got two main issues:

<ol><li><a href="https://developer.chrome.com/extensions/storage.html#method-StorageArea-get" rel="nofollow">chrome.storage.sync.get</a> is asynchronous, while the function in <a href="http://api.jquery.com/prop/#prop-propertyName-functionindex--oldPropertyValue" rel="nofollow">jQuery.fn.prop(propertyName, function(index, oldPropertyValue) )</a> must synchronously return the desired value.</li> <li>storage.set({name:'checked'}, ...); will create a property called "name" with value "checked", <em>not</em> a property with the name as specified in the name variable with value "checked".</li> </ol>

To solve the first problem, swap the order of operations: First read the preference, <em>then</em> set the property:

//Retrieve existing settings $(':checkbox').each(function(index, element) { var name = this.name; storage.get(name, function(items) { element.checked = items[name]; // true OR false / undefined (=false) }); });

To solve the second issue, first create an object, assign the new property, and save the result. Note: Since a checkbox can only have two states, I recommend to not save the string "checked", but use a boolean (true / false):

function saveSettings() { var name = this.name; var items = {}; items[name] = this.checked; storage.set(items, function() { console.log("saved"); }); }

PS. When you're certain that you're dealing with checkboxes, use element.checked instead of $(element).is(':checked'). The former is shorter and faster. Using jQuery adds no value here. See also: <a href="https://stackoverflow.com/questions/4651923/when-to-use-vanilla-javascript-vs-jquery" rel="nofollow">When to use Vanilla JavaScript vs. jQuery?</a>

Recommend

  • Using tablesorter custom parser only for filtering with Checkboxes - working example needed
  • Generic `vendors` mixin
  • How to denormalize nested list in R?
  • React Native + Redux: What's the best and preferred navigation?
  • apply a javascript function to draggable copy
  • Uncaught TypeError: $(…).select2 is not a function
  • Android changing fragment order inside FragmentPagerAdapter
  • Button click event not firing in jQuery
  • Detect when Facebook like button is clicked
  • Chart.js Multiple dataset
  • Visual Studio 2010 debugger build correctly - compiler pdb and linker pdb not in synch?
  • Create DicomImage from scratch using Dcmtk
  • Needing to do .toArray() to get output of mongodb .find() on key name not value
  • Groovy: Unexpected token “:”
  • How to get Eclipse Oxygen to run on Java 9
  • How do I get HTML corresponding to current DOM tree?
  • chrome.tabs.executeScript only fires when the Developer Console is open
  • Make VS2015 use angular-cli ng at build time in a .NET project
  • JQuery Internet Explorer and ajaxstop
  • JSON response opens as a file, but I can't access it with JavaScript
  • MailKit: The IMAP server replied to the 'EXAMINE' command with a 'BAD' response
  • Display issues when we change from one jquery mobile page to another in firefox
  • Deselecting radio buttons while keeping the View Model in synch
  • req.body is undefined - nodejs
  • Modifying destination and filename of gulp-svg-sprite
  • JSON with duplicate key names losing information when parsed
  • Can a Chrome extension content script make an jQuery AJAX request for an html file that is itself a
  • Change an a tag attribute in JavaScript based on screen width
  • Importing jscolor library in angular 2
  • Upload files with Ajax and Jquery
  • Jquery - Jquery Wysiwyg return html as a string
  • XCode can't find symbols for a specific iOS library/framework project
  • Calling of Constructors in a Java
  • How to pass list parameters for each object using Spring MVC?
  • jqPlot EnhancedLegendRenderer plugin does not toggle series for Pie charts
  • Traverse Array and Display in markup
  • Transpose CSV data with awk (pivot transformation)
  • AngularJs get employee from factory
  • Proper way to use connect-multiparty with express.js?
  • Why can't I rebase on to an ancestor of source changesets if on a different branch?