Skip to content

Instantly share code, notes, and snippets.

@rupertlssmith
Last active January 31, 2022 15:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rupertlssmith/5c4e3be17830e40d64168f390f4aea24 to your computer and use it in GitHub Desktop.
Save rupertlssmith/5c4e3be17830e40d64168f390f4aea24 to your computer and use it in GitHub Desktop.
Local storage using Elm port.

To attach the local-storage.js to an Elm application, the code example in index.js is used. Note that there are 2 ways given in the example, one is using local code and the other is using the npm package.

The javascript implementation can be as shown in local-storge.js.

The ports needed on the Elm side must be provided by your application. An example implementation can be seen in LocalStoragePort.elm.

Lastly, in order to get back messages telling you when something has been found or not in local storage, or to get listings of available keys, you need to susbscribe to the ResponsePort. The code snippet in Main.elm shows how to set this up and what Responses you can get and need to deal with in your update function.

// If you are using the npm package.
const LocalStorage = require('@the-sett/elm-localstorage').ElmLocalStoragePorts;
// OR If you are copy/pasting this code locally.
const LocalStorage = require('local-storage.js').ElmLocalStoragePorts;
const app = Elm.Main.init({node: document.getElementById('main')});
// Subscribe to local storage.
const localStorage = new LocalStorage();
localStorage.subscribe(app);
var ElmLocalStoragePorts = function() {};
ElmLocalStoragePorts.prototype.subscribe =
function(app, getPortName, setPortName, clearPortName, responsePortName, listKeysPortName) {
if (!getPortName) getPortName = "getItem";
if (!setPortName) setPortName = "setItem";
if (!clearPortName) clearPortName = "clear";
if (!listKeysPortName) listKeysPortName = "listKeys";
if (!responsePortName) responsePortName = "response";
if (app.ports[responsePortName]) {
var responsePort = app.ports[responsePortName];
if (app.ports[getPortName]) {
app.ports[getPortName].subscribe(function(key) {
var val = null;
try {
val = JSON.parse(localStorage.getItem(key))
} catch (e) {}
responsePort.send({
key: key,
value: val
})
});
} else {
console.warn("The " + getPortName + " port is not connected.");
}
if (app.ports[setPortName]) {
app.ports[setPortName].subscribe(function(kv) {
var key = kv[0];
var json = kv[1];
if (json === null) {
localStorage.removeItem(key);
} else {
localStorage.setItem(key, JSON.stringify(json));
}
});
} else {
console.warn("The " + setPortName + " port is not connected.");
}
if (app.ports[clearPortName]) {
app.ports[clearPortName].subscribe(function(prefix) {
if (prefix) {
var cnt = localStorage.length;
for (var i = cnt - 1; i >= 0; --i) {
var key = localStorage.key(i);
if (key && key.startsWith(prefix)) {
localStorage.removeItem(key);
}
}
} else {
localStorage.clear();
}
});
} else {
console.warn("The " + clearPortName + " port is not connected.");
}
if (app.ports[listKeysPortName]) {
app.ports[listKeysPortName].subscribe(function(prefix) {
var cnt = localStorage.length;
var keys = [];
for (var i = 0; i < cnt; i++) {
var key = localStorage.key(i);
if (key && key.startsWith(prefix)) {
keys.push(key);
}
}
responsePort.send(keys);
});
} else {
console.warn("The " + listKeysPortName + " port is not connected.");
}
} else {
console.warn("The " + responsePortName + " port is not connected.");
}
};
module.exports.ElmLocalStoragePorts = ElmLocalStoragePorts;
port module Ports.LocalStoragePort exposing (clear, getItem, listKeys, response, setItem)
import LocalStorage exposing (ClearPort, GetItemPort, ListKeysPort, ResponsePort, SetItemPort)
port getItem : GetItemPort msg
port setItem : SetItemPort msg
port clear : ClearPort msg
port listKeys : ListKeysPort msg
port response : ResponsePort msg
type Msg
= LocalStorageOp Operation
subscriptions : Model -> Sub Msg
subscriptions model =
LocalStorage.responseHandler LocalStorageOp "some.prefix"
|> LocalStoragePort.response
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
LocalStorageOp res ->
case res of
Item key value -> ...
ItemNotFound key -> ...
KeyList keys -> ...
Error errMsg -> ...
@Tails
Copy link

Tails commented Jan 31, 2022

In line #7, I think the "some.prefix" should be model.localStorageConfig; the LocalStorage config object should be passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment