Commit 7957c4f7 authored by Mike Street's avatar Mike Street
Browse files

Blog audit

parent 58d3bc98
---
title: Vue: Using localStorage with Vuex store
title: "Vue: Using localStorage with Vuex store"
date: 2017-10-13
updated: 2020-06-11
intro: Using the browser's localStorage we can create a Vue app which has its Vuex store cached. This allows the user to navigate away from the app and not lose their preferences.
permalink: "blog/vue-js-using-localstorage-with-the-vuex-store/"
tags:
- Web
- Javascript
......@@ -18,12 +19,14 @@ _This tutorial uses Vue v2.4.4 and Vuex v2.5.0 - although I'm sure it will work
`localStorage` is a cache in the browser which persists even after the browser is closed. It allows you to store data on a page and later access it - it's especially easy to do using JavaScript. More information about `localStorage` can be found on the [MDN Website](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), but the basics are as follows. The `key` is an identifiable string for you to access the saved data later.
<pre class="language-js">// Store the "value" under the ID of "key"
```js
// Store the "value" under the ID of "key"
localStorage.setItem('key', 'value');
// Load the data back and store as a variable
let val = localStorage.getItem('key');
// val will equal "value"</pre>
// val will equal "value"
```
**Note:**
......@@ -31,11 +34,13 @@ let val = localStorage.getItem('key');
For example:
<pre class="language-js"> // Convert the object into a JSON string and store
```js
// Convert the object into a JSON string and store
localStorage.setItem('key', JSON.stringify(object));
// Retrieve the data and convert from JSOn string to object/array
let obj = JSON.parse(localStorage.getItem('key'));</pre>
let obj = JSON.parse(localStorage.getItem('key'));
```
## Vuex
......@@ -49,7 +54,8 @@ On the latest Vue app I'm developing, I wanted the Vuex contents (or `state`) to
If you're reading this I would assume you've got your store already initialised. However you've built your app, the _store_ should have a variable assigned to it.
<pre class="language-js">// Initialise your store
```js
// Initialise your store
const store new Vuex.Store({
// You state might be more complex than this
state: {
......@@ -57,7 +63,8 @@ const store new Vuex.Store({
},
mutations: {},
getters: {}
});</pre>
});
```
### Storing data
......@@ -65,11 +72,13 @@ We now wish to cache the data whenever the store updated. Fortunately, Vuex offe
_After_ your store has been initialised, register the subscribe method on your `store` variable. This function accepts two parameters - the mutation which was fired and the state _after_ the mutation. We wish to store this state in our `localStorage`. As `localStorage` is specific to each domain name, we can use a variable name to reference the contents - such as `store`. Don't forget to convert your object to a string.
<pre class="language-js">// Subscribe to store updates
```js
// Subscribe to store updates
store.subscribe((mutation, state) => {
// Store the state object as a JSON string
localStorage.setItem('store', JSON.stringify(state));
});</pre>
});
```
### Retrieving data
......@@ -79,7 +88,8 @@ To do this, we are going to create a mutation within the store, which updates th
Create a new mutation called `initialiseStore`. Inside this mutation, check if the `localStorage` item exists
<pre class="language-js">const store new Vuex.Store({
```js
const store new Vuex.Store({
state: {
count: 1
},
......@@ -87,16 +97,18 @@ Create a new mutation called `initialiseStore`. Inside this mutation, check if t
initialiseStore(state) {
// Check if the ID exists
if(localStorage.getItem('store')) {
}
}
},
getters: {}
});</pre>
});
```
We now need to replace the current state if it does exist. To do this, we are going to use the `replaceState` Vuex method. Within here, we are going to merge both the current, blank, state and the stored data. The reason for this is so that if there are any new properties which were added since the last time the user visited, they don't get any dreaded `undefined` errors.
<pre class="language-js">const store new Vuex.Store({
```js
const store new Vuex.Store({
state: {
count: 1
},
......@@ -112,13 +124,15 @@ We now need to replace the current state if it does exist. To do this, we are go
}
},
getters: {}
});</pre>
});
```
The last stage is to call this mutation when the Vue app is created. We want this to happen at the _earliest_ point which, based on the [Vue lifecycle hooks](https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram) is during the `beforeCreate()` method.
Add this method to your Vue instance and trigger the mutation:
<pre class="language-js">new Vue({
```js
new Vue({
el: '#app',
store,
......@@ -126,7 +140,8 @@ Add this method to your Vue instance and trigger the mutation:
beforeCreate() {
this.$store.commit('initialiseStore');
}
});</pre>
});
```
Huzzah! You now have an app with a Vuex store cached in `localStorage`.
......@@ -150,25 +165,30 @@ If on load, the user had the same version number as that of my app, then the cac
The first step is to load our version number. Ours is stored in the `package.json` so, using ES6, this is as simple as:
<pre class="language-js">import {version} from './package.json';</pre>
```js
import {version} from './package.json';
```
However, you may wish to cache yours from a git tag or have it somewhere as a variable. Ideally, it needs to be accessed separately from the store so that the cache doesn't end up overwriting it.
Next, create an empty string in your store - for the version to be saved once verified.
<pre class="language-js">state: {
```js
state: {
// Cache version
version: '',
count: 1
},</pre>
},
```
We can now update our `initialiseStore` mutation to check the version with that of the one in the cache and take appropriate action based on the result
<pre class="language-js">initialiseStore(state) {
```js
initialiseStore(state) {
// Check if the store exists
if(localStorage.getItem('store')) {
let store = JSON.parse(localStorage.getItem('store'));
// Check the version stored against current. If different, don't
// load the cached version
if(store.version == version) {
......@@ -179,7 +199,8 @@ We can now update our `initialiseStore` mutation to check the version with that
state.version = version;
}
}
}</pre>
}
```
- - -
......@@ -189,11 +210,13 @@ We can now update our `initialiseStore` mutation to check the version with that
You may only wish to cache a few elements from your store, this can be achieved by creating a new object in your `subscribe` function and storing that. We are already merging the cache with the current store state on load, so that doesn't need to change.
<pre class="language-js">store.subscribe((mutation, state) => {
```js
store.subscribe((mutation, state) => {
let store = {
version: state.version,
count: 1
};
localStorage.setItem('store', JSON.stringify(store));
});</pre>
\ No newline at end of file
});
```
---
title: Filters in Vue.js&#58; What are they, how do you use them, and how do you make them? (video)
title: "Filters in Vue.js: What are they, how do you use them, and how do you make them? (video)"
date: 2017-11-08
updated: 2018-01-04
intro: There are many ways to manipulate a value to make it user-friendly using Vue.js. In this tutorial, I show you how you can use Vue filters to alter the appearance of a variable without affecting its data.
permalink: "blog/vue-js-filters-what-are-they-how-do-you-use-them-and-how-do-you-make-them-video/"
tags:
- Web
- VueJS
- Javascript
- Front-end Development
---
{% raw %}
<div class="info">I wrote a book about Vue.js! <a href="https://www.packtpub.com/application-development/vuejs-2x-example">Vue.js 2.x by Example</a> is available as from Packt and covers Vue, Vuex and VueRouter.</div>
......@@ -16,11 +20,14 @@ tags:
Using filters in Vue.js, you are able to manipulate the appearance of a variable without altering the actual value. This is done in the template by using the pipe (`|`) character. For example:
<pre class="language-js">{{ message | lowercase }}</pre>
```js
{{ message | lowercase }}
```
To create this filter, add a `filters` object to the Vue or component instance. Within this, create a new function which accepts one parameter and returns a value:
<pre class="language-js"> new Vue({
```js
new Vue({
el: '#app',
filters: {
......@@ -32,17 +39,19 @@ To create this filter, add a `filters` object to the Vue or component instance.
data: {
message: 'Hello World'
}
});</pre>
});
```
With the basics of filtering under your belt, we can progress onto slightly more advanced filtering - with a more practical example.
### VAT Calculator
### VAT Calculator
A realistic example would be a VAT calculator. Wanting to use the percentage as a decimal (e.g. 20% = 0.2) but display in a user-friendly way, we can use filters to accomplish this.
The initial app JavaScript will look like the following:
<pre class="language-js">new Vue({
```js
new Vue({
el: '#app',
data: {
......@@ -57,25 +66,29 @@ The initial app JavaScript will look like the following:
return price + vat;
}
}
});</pre>
});
```
Create the HTML to match the JS. This should have an input field bound to the `price` variable using `v-model`, the VAT rate output (`vat`) and the `amount` variable being output
<pre class="language-html">&lt;div id="app"&gt;
Price ext vat: &lt;input v-model="price"&gt;
&lt;h3&gt;Vat percent: {{ vat | percent }}&lt;/h3&gt;
&lt;h3&gt;Price with vat: {{ amount | currency }}&lt;/h3&gt;
&lt;/div&gt;</pre>
```html
<div id="app">
Price ext vat: <input v-model="price">
<h3>Vat percent: {{ vat | percent }}</h3>
<h3>Price with vat: {{ amount | currency }}</h3>
</div>
```
On both the `vat` and `amount` variables, add filters for `percent` and `currency` respectively.
The `percent` filter will convert a decimal to a percent - by multiplying the amount by 100 and then adding a **%** sign.
The `percent` filter will convert a decimal to a percent - by multiplying the amount by 100 and then adding a **%** sign.
The `currency` filter will use [toLocaleString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString) to convert the number to a human-readable price.
Within the app JavaScript, create two the two new filters and their functionality:
<pre class="language-js">new Vue({
```js
new Vue({
el: '#app',
filters: {
......@@ -103,7 +116,8 @@ Within the app JavaScript, create two the two new filters and their functionalit
return price + vat;
}
}
});</pre>
});
```
The VAT and amount now read a lot better, without the original values be altered.
......@@ -111,23 +125,28 @@ The VAT and amount now read a lot better, without the original values be altered
A couple of differences/issues that have been pointed out/I've noticed with the video. Unfortunately, you can't re-upload Youtube videos and keep the same URL, so I will have to list them here:
### Initialising
### Initialising
When initialising a Vue filter, you can either do it as described in the video, via an object on the Vue instance or component or, alternatively, you can use `vue-filter` - much as you would `vue-component`. An example of the percent one above would be:
<pre class="language-js">Vue.filter('percent', function(val) {
```js
Vue.filter('percent', function(val) {
return val * 100 + '%';
});</pre>
});
```
### Variables & arguments
In the video, I state that filters only accept one argument - this is incorrect and they can, in fact, accept many. A use case would be if you didn't want to hardcode the `GBP` in the currency filter, you could pass this is as an argument like so:
<pre class="language-html">&lt;h3&gt;Price with vat: {{ amount | currency('GBP') }}&lt;/h3&gt;</pre>
```html
<h3>Price with vat: {{ amount | currency('GBP') }}</h3>
```
With the javascript being updated as you would expect:
<pre class="language-js">new Vue({
```js
new Vue({
el: '#app',
filters: {
......@@ -144,6 +163,10 @@ With the javascript being updated as you would expect:
},
...
});</pre>
});
```
_Using ES6, we do not need to specify `currency: currency` in the `toLocaleString` function._
{% endraw %}
_Using ES6, we do not need to specify `currency: currency` in the `toLocaleString` function._
\ No newline at end of file
---
title: Creating an 11ty collection from a JSON API
intro: Using 11ty Global data files, you can make collections from JSON APIs, allowing you to make whole websites from one endpoint
date: 2021-07-12
date: 2021-06-28
permalink: "blog/creating-an-11ty-collection-from-json-api/"
tags:
- JSON
......
---
title: Create an 11ty collection from any RSS feed
intro: Using 11ty global data files, we create an 11ty collection from an RSS feed. As an example, we show the latest YouTube videos on our website
date: 2021-07-26
date: 2021-07-12
permalink: "blog/create-11ty-collection-from-rss/"
tags:
- 11ty
......
---
title: Making an 11ty collection from a remote XML file
intro: RSS is XML with a specification, however not all RSS feeds follow the spec. In this post, we process the feed as an XML document meaning we can access the extra attributes and values
date: 2021-07-29
date: 2021-07-26
permalink: "blog/making-an-11ty-collection-from-a-remote-xml-file/"
tags:
- RSS
......
......@@ -2,6 +2,7 @@
title: Server tools - htop and apache server status
date: 2021-06-15
intro: As a starting point with the server tool debugging, this blog post explores htop and setting up a server status page with Apache
draft: true
permalink: "blog/server-tools-htop-and-apache-server-status/"
tags:
- DevOps
......
......@@ -2,6 +2,7 @@
title: Server tools - an introduction
intro: I'm investigating a Linux server which has performance issues and walking through the processes and steps I am doing to find a solution
date: 2021-06-14
draft: true
tags:
- Server Tools
---
......
```js
const cloudinary = require('cloudinary').v2
cloud_image = cloudinary.uploader.upload(
image,
{
secure: true,
public_id: image_path
},
function() {
}
);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment