GithubHelp home page GithubHelp logo

cheatsheet-vuejs's Introduction

lysla's Vue.js cheatsheet

Simple indexed manual with notes.

vue cli 3

npm i -g @vue/cli

create

vue create my-vue-app
> Follow instruction to build your app

run

npm run serve

add a plugin

> Plugin name must be vue-cli-plugin-someplugin
vue add someplugin

main structure

General Vue instance or component structure

{
	data() {
		return {
			myData: 'some data',
			//...
		}
	},
	computed: {
		myComputedData() {

		},
		//...
	}
	methods: {
		myMethod() {

		},
		//...
	},
	watch: {
		dataToWatch: function() {
			// do something when data changes
		}
	}
	//...
}

common initial instance

In main js file (main.js)

import Vue from 'vue';
import App from './..path../App.vue';

new Vue({
	el: '#app',
	render: h => h(App)
});

In main html file

<html>
	<!-- ... -->
	<div id="app"></div>
	<!-- ... -->

	<script src="..path../compiled.js"></script>
</html>

built-in directives

v-if and v-show

Renders an element only if the condition is true

<div v-if="condition == true"></div>
<!-- also -->
<div v-if="condition == true"></div>
<div v-else></div>

Show an element (that is rendered anyway) only if the condition is true

<div v-show="condition == true"></div>

v-for

Loop throu a cycle and renders an element each time

<div v-for="n in array">{{ n }}</div>

Current index is available

<div v-for="(n, i) in array">{{ n }} is the element number {{ i }}</div>

v-bind and v-on

Both directives are commonly short-cut, relatively to : and @

v-bind example

<div class="container any-class" :class="someData"></div>

<script>
	//...
	data() {
		return {
			someData: 'dynamic-class'
		}
	}
</script>

v-on example

<button @click="myMethod"></button>
<a href="#" @hover="myMethodHover"></a>
<script>
	//...
	methods: {
		myMethod() {
			// do something on click event
		},
		myMethodHover() {
			// do something on hover event
		}
	}
</script>

components

general

Importing components in main Vue instance

Vue instance (App.vue)

<comp-name></comp-name>
...
<script>
	import CompName from './..path../CompName.vue';

	export default {
		...
		components: {
			'comp-name': CompName //or compName: CompName
		}
	}
</script>

Vue component (CompName.vue)

<template>
	<div>
		...
	</div>
</template>
<script>
	export default {
		//...
	}
</script>

dynamic components

<component :is="someVariableData">
	<!-- can hold default content -->
	default content
</component>

Prevent destroying components when switching between them

<keep-alive>
	<component :is="someVariableData"></component>
</keep-alive>

props

Passing data from component to child component

Parent component

<child-component :name="someData"></child-component>
<script>	
	data() {
		return {
			someData: 'some data'
		}
	}
	//...
</script>

Child component

<template>
	{{ someData }}
</template>
<script>
	//...
	props: ['someData']
	//or
	props: {
		someData: {
			type: SomeType //String, Array...
			required: false,
			default: 'some default data'
		}
	}
</script>

slots

Reserving html space in child components Parent

<child-component>
	<div></div>
	<div slot="partialSlot"></div>
</child-componenet>

Child component

<template>
	<div>
		<!-- this slot will render all html inside the component tag in the parent which does not have a slot attribute (slot name) -->
		<slot></slot>

		<!-- will render only html which has the corresponding name -->
		<slot name="partialSlot"></slot>

		<!-- slots can have a default value when they don't find any html to render -->
		<slot name="missingSlot">
			some default html
		</slot>
	</div>
</template>

events

Listening to custom events and how to emit them

Component in the listener Vue file

<my-component @myCustomEvent="someMethod($event)"></my-component>

<script>
	//...
	methods: {
		someMethod(someArgs) {

		}
	}	
</script>

Component which emits the custom event

<button @click="myMethod(someArgs)"></button>

<script>
	//...
	myMethod() {
		this.$emit('myCustomEvent', someArgs);
	}
</script>

filters

๐ŸŽˆ filters can be used as a handy alternative to computed proprieties

Usage

Filtering data before displaying it

<p>{{ myData | myfilter }}</p>
<!-- or multiple filters -->
<p>{{ myData | myfilter | anotherfilter }}</p>

Global filter example

In main js file (main.js)

Vue.filter('myfilter', function(value) {
	// value is the value to filter somehow
	return value;
});

Local filter example

In the component

<script>
	export default {
		//...
		filters: {
			myfilter(value) {
				// do something with value
				return value;				
			}
		}
	}
</script>

mixins

Snippet of structured code to re-use in multiple application parts

Mixins live in separated files

๐ŸŽˆ data values aren't shared, they just get copy-pasted

๐ŸŽˆ mixins don't override nor destroy existing proprieties

In myMixin.js

export const myMixin = {
	data() {
		return {
			//...
		}
	},
	methods: {
		//...
	},
	computed: {
		//...
	},
	//...
}

In Vue instance or component where i need the mixin

<script>
	import { myMixin } from './..path../myMixin';

	export default {
		mixins: [myMixin],
		//...
	}
</script>

forms

v-model

input text

Automatically update the data everytime the input value changes

<form>
	<input type="text" id="name" v-model="myData.name">
</form>

<script>
	//...
	data() {
		return {
			myData: {
				name: 'Name',
				email: '[email protected]'
			}
		}
	}
</script>

Change when to update the value, rather then the default 'change' event, to the 'out of focus' event

<input type="text" id="name" v-model.lazy="myData.name">

checkbox and radio

Automatically store values with the same model into an array

<input type="checkbox" id="cb1" v-model="arrayData">
<input type="checkbox" id="cb2" v-model="arrayData">

<script>
	//...
	data() {
		return {
			arrayData: []
		}
	}
</script>

Radio with the same model are automatically bound to the same radio group.

<input type="radio" id="rb1" value="1" v-model="radioValue">
<input type="radio" id="rb2" value="2" v-model="radioValue">

<script>
	//...
	data() {
		return {
			radioValue: 1 // default or empty value
		}
	}
</script>

select

Use for cycle to render available options, and a data variable to store the selected value

<select id="mySelect" v-model="selectValue">
	<option v-for="n in myArray">{{ n }}</option>
</select>

<script>
	//...
	data() {
		return {
			myArray: ['1', '2', '3'],
			selectValue: '1' // default or empty value
		}
	}
</script>

custom directives

Usage

With value passed, which can be hardcoded or any data value or object

<p v-somename="'someString'"></p>
<!-- or -->
<p v-somename="someData"></p>

With value and arg passed

<p v-somename:somearg="someData"></p>

With value, arg and modifiers passed

<p v-somename:somearg.somemod.othermod="someData"></p>

Global directive example

In main js file (main.js)

Vue.directive('somename', {
	bind(el, binding, vnode) {
		// el is the html element
		// binding.value is the value passed
		// binding.arg contains the arg passed
		// binding.modifiers[] containers all modifiers passed, accessible by their name as array key
	}
});

Local directive example

In the component

<script>
	export default {
		//...
		directives: {
			'somename': {
				bind(el, binding, vnode) {
					// do something
				}
			}
		}
	}
</script>

hooks

components life cycle

beforeCreate()

created()

beforeUpdate()

beforeMount()

mounted()

updated()

beforeDestroy()

destroyed()

For <keep-alive> dynamic components only

activated()

deactivated()

directives

bind(el, binding, vnode)

inserted(el, binding, vnode)

update(el, binding, vnode, oldVnode)

componentUpdated(el, binding, vnode, oldVnode)

unbind(el, binding, vnode)

transitions

before-enter()

enter()

after-enter()

after-enter-cancelled()

before-leave()

leave()

after-leave()

after-leave-cancelled()

routing

In main.js

beforeEach(to, from, next)

In routes.js

beforeEnter(to, from, next)

In component

beforeRouteEnter(to, from, next)

In component only

beforeRouteLeave(to, from, next)

transitions

<transition name="somename">
	<some-component-or-html-single-el>
	</some-component-or-html-single-el>
	<!-- or -->
	<some-comp-or-html v-if="" key="k1"></some-comp-or-html>
	<some-comp-or-html v-else key="k2"></some-comp-or-html>
	<!-- or -->
	<my-dynamic-component :is="someData"></my-dynamic-component>
	<!-- or -->
	<router-view></router-view>
</transition>

๐ŸŽˆ key propriety is needed in transitioning v-if elements

Trigger animation on the first rendering on page loaded

<transition appear>
	<!-- --->
</transition>

Change how animation works when used to switch between componenets

<transition mode="out-in"></transition>
<transition mode="in-out"></transition>

Custom classes names

<transition 
	enter-class="my-enter"
	enter-active-active="my-enter-active"
	leave-class="my-leave"
	leave-active-class="my-leave-active"
	move-class="my-move">
</transition>

Transition group

๐ŸŽˆ differently from single transition, this renders a default span which contain all the html, can be overwritten by setting the propriety tag="someothertag"

<ul> <!-- or any kind of element list -->
	<transition-group move-class="my-move">
		<!-- key propriety is mandatory -->
		<li key="k1"></li>
		<li key="k2"></li>
		<li key="k3"></li>
	</transition-group>
</ul>

Generated classes

When transition has the name propriety, this classes get automatically generated with that name

๐ŸŽˆ css animations work better with keyframes

css animation example

.somename-enter {

}
.somename-enter-active {
	animation: animation-in 300ms ease-in forwards;
}
.somename-leave {

}
.somename-leave-active {
	animation: animation-out 300ms ease-out forwards;
	/** hack for transition-group animation when an element is removed **/
	position: absolute;
}
/** specifically for transition-group **/
.somename-move {
	transition: all 300ms ease-in;
}
/*css keyframe animation example*/
@keyframes animation-in {
	from: {
		opacity: 0;
	}
	to: {
		opacity: 1;
	}
}
@keyframes animation-out {
	from: {
		opacity: 1;
	}
	to: {
		opacity: 0;
	}
}

Listening to animation hooks

<transition
	@before-enter="beforeEnterMethod"
	@enter="enterMethod">
	<!-- transitioning element --->
</transition>

<script>
	export default {
		//...
		methods: {
			beforeEnterMethod(el) {
				// el is the transitioning element
			},
			enter(el, done) {
				// done must be called when using custom hooks without css animations
				done();
			}
		}
	}
</script>

routing

Vue.js manage routing via vue-router which needs to be installed

In main js file (main.js)

import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './..path../App.vue';

/* routes.js file */
import { routes } from './..path../routes';

Vue.use(VueRouter);
const router = new VueRouter({
	routes,
	mode: 'hash' // or history
	// ๐ŸŽˆ history will only work if the server is configurated so it always return index.html even with 404 error
});

new Vue({
	el: '#app',
	router,
	render: h => h(App)
});

//...

Create routes.js file

import PageHome from './..path../PageHome.vue';
import PageFirst from './..path../PageFirst.vue';
import PageSecond from './..path../PageSecond.vue';

export const routes = [
	{
		path: '',
		component: PageHome
	},
	{
		path: '/page1',
		component: PageFirst,
		name: 'someRouteName' // not mandatory but useful
	},
	{
		path: '/page2',
		componenent: PageSecond
	}
]

App.vue main instance

<template>
	<div>
		<!-- ... --->
		<router-view>
			<!-- routed components will be rendered here --->
		</router-view>
	</div>
</template>

routing parameters

In routes.js

import PageHome from './..path../User.vue';

export const routes = [
	{
		path: '/user/:id',
		component: User,
		name: 'someRouteName'
	}
]

In User component (User.vue)

<template>
	<div>
		Url parameter: {{ id }}
	</div>
</template>

<script>
	export default {
		data() {
			return {
				id: this.$route.params.id
			}
		},
		// ๐ŸŽˆ if we have a way to reactivate this component without destroying and recreating it, we need to watch the route to be updated everytime it changes, otherwise this is not needed
		watch: {
			'$route'(to, from) {
				this.id = to.params.id;
			}
		}
	}
</script>

routing links

Simple examples

<router-link to="/page">My page link</router-link>
<router-link to="/">My home link</router-link>
<router-link :to="someDataLink">My dynamic link</router-link>

Active class and html style example

We want a li tag which will contain an a tag, and the active class will be added only with url exact match

<router-link to="/" tag="li" active-class="my-active-class" exact><a>Home</a></router-link>

Trigger navigation via javascript

//...
export default {
	//...
	methods: {
		navigateToPage() {
			this.$router.push('/page1');
			// or
			this.$router.push( { name: 'someRouteName' });
		}
	}
}

Dynamic link with parameters example, taking the current route id

<router-link :to="myLink">My Link</router-link>

<script>
	export default {
		data() {
			return {
				myLink: { 
					name: 'someRouteName', 
					params: { id: $route.params.id } 
				},
				// we can also pass query data
				myLinkWithQuery: {
					name: 'someRouteName', 
					query: { lang: 'eng' }
				},
				// and hash
				myLinkWithHash: {
					name: 'someRouteName',
					hash: '#someHash'
				}
			}
		}
	}
</script>

nested routes

We can have router views inside components already rendered inside a 'root' router view

In the parent we do likewise as non-nested routes

<template>
	<div>
		<router-view></router-view>
	</div>
</template>

In routes.js

// ... components imports

export const routes = [
	{
		path: '/user',
		component: User,
		children: [
			{
				path: 'new', // /user/new
				component: 'UserNew.vue'
			},
			{
				path: ':id', // user/123
				component: 'UserDetail.vue'
			},
			{
				path: ':id/edit', //user/123/edit
				component: 'UserEdit.vue'
			}
		]
	}
]

multiple router views

You can change rendering place of components relatively to the router view

In the component

<template>
	<div>
		<router-view></router-view>
		<router-view name="position-one"></router-view>
		<router-view name="position-two"></router-view>
	</div>
</template>

In routes.js

// ... components imports

export const routes = [
	{
		path: '/page',
		components: {
			default: MainComponent,
			positionOne: SwitchingComponent
		}
	},
	{
		path: '/pageSwitched',
		components: {
			default: MainComponent,
			positionTwo: SwitchingComponent
		}
	}
]

redirects

In routes.js

export const routes = [
	{
		path: '/nowhere',
		redirect: '/gosomewhereelse'
	},
	// also
	{
		path: '/home',
		name: 'routeHome'
	},
	{
		path: '/oldhome',
		redirect: { name: 'routeHome' }
	},
	// redirect all non-managed paths
	{
		path: '*',
		redirect: { name: 'routeHome' }
	}
]

guarding navigation hooks

Definition in component

<script>
	export default {
		//...
		beforeRouteEnter(to, from, next) {
			// call to proceed
			next();
			// can also redirect
			next('/somewhere');
		},
		beforeRouteLeave(to, from, next) {
			// call to proceed
			next();
		}
	}
</script>

Definition in routes.js (uncommon)

export const routes = [
	{
		path: '/somewhere',
		component: SomeComponent,
		beforeEnter: (to, from, next) => {
			// call to proceed
			next();
		}
	}
]

vuex

State management with Vuex, which needs to be installed

centralized data structure

In store.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export const store = new Vuex.Store({
	state: {
		centralizedAttr: 'someValue'
	},
	getters: {
		myGetFunction: state => {
			return state.centralizedAttr;
		},
		// ๐ŸŽˆ getters can also receive all getters as second arg
		myGetFunction: (state, getters) => {
			getters.myOtherGetFunction;
			//...
		}
	},
	mutations: {
		myUpdateFunction: (state, payload) => {
			// payload contains the (single) arg when passed
			// cannot contain async code
			state.centralizedAttr = 'newValue';
		}
	},
	actions: {
		myAction: (context, payload) => {
			// payload contains the (single) arg when passed
			// can contain async code
			context.commit('myUpdateFunction');
		},
		// ๐ŸŽˆ more commonly typed using only the commit method from the context parameter
		myAction: ({commit}, payload) => {
			commit('myUpdateFunction');
		}
	}
});

In main.js

import Vue from 'vue';
import App from './App.vue';
import { store } from '../path../store';

new Vue({
	el: '#app',
	store,
	render: h => h(App)
});

Accessing centralized structure from components

export default {		
	computed: {
		centralizedProp() {
			// accessing the value directly
			return this.$store.state.centralizedAttr;
			// or using getters
			return this.$store.getters.myGetFunction;		
		}						
	},
	methods: {
		centralizedMethod() {
			this.$store.commit('myUpdateFunction');
		},
		centralizedAction() {
			this.$store.dispatch('myAction');
		}
	}
}

We also can use map helpers to import all state, getters, mutations and actions

import { mapState } from 'vuex';
import { mapGetters } from 'vuex';
import { mapMutations } from 'vuex';
import { mapAction } from 'vuex';

export default {
	computed: {
		// ๐ŸŽˆ the three dots allow the extraction of all methods in the object (es6 syntax) so we can then use other computed proprieties of our own
		...mapState(['centralizedAttr']),
		...mapGetters(['myGetter', 'anotherGetter']),
		otherCompProp() {
			//do something
		}
	},
	methods: {
		...mapMutations(['myUpdateFunction', 'anotherMutation']),
		...mapActions(['myAction']),
		otherMethod() {
			//do something
		}
	}
}

Then we render values from the centralized structure like normal attributes

<!-- ... -->
<div>{{ myGetter }}</div>
<div>{{ myUpdateFunction }} {{ anotherMutation('someArg') }}</div>
<div>{{ myAction('someArg') }}</div>

๐ŸŽˆ We need to use an uncommon structure of computed proprieties if we need to bind a centralized value to a v-model input (two-way binding)

<template>
	<div>
		<input type="text" v-model="myCompPro">
	</div>
</template>

<script>
	export default {
		computed: {
			myCompProp: {
				get() {
					return this.$store.getters.myGetter;
				},
				set(value) {
					this.$store.dispatch('myAction', value);
				}
			}
		}
	}
</script>

modules

Splitting the main store.js centralized state file using modules, all structure is available from all the modules

๐ŸŽˆ You can also split elements in different js files and using normal es6 import without using modules

New splitted partial.js

const store = {
	mySharedStore: 'someValue'
};
const getters = {
	mySharedGetter: state => {
		return state.mySharedStore;
	}
};
const mutations = {
	mySharedMutation: (state, payload) => {
		// some mutation
		state.mySharedStore = payload;
	},
};
const actions = {
	mySharedAction: (context, payload) => {
		// some action
		context.commit('myShareMutation', payload);
	}
};

export default {
	state,
	getters,
	mutations,
	actions
};

In main store.js

//...
import MyModule from '../path/..partial';

export const store = new Vuex.Store({
	//... global state, getters, mutations, actions
	modules: {
		MyModule
	}
});

axios

HTTP interaction (REST) with axios, which need to be installed

import axios from 'axios';

// can have global configuration
axios.defaults.baseURL = 'http://apibaseurl/';
axios.defaults.headers.common['SomeConfig'] = 'some config value';
// ... and more

POST request

axios.post('http://apiurl/', dataObject, { extraOptions })
	.then(response => {
		// ...
		console.log(response);
	})
	.catch(error => {
		// ...
		console.log(error);
	});

GET request

axios.get('http://apiurl/', { extraOptions })
	.then(response => {
		// ...
		console.log(response);
	})
	.catch(error => {
		// ...
		console.log(error);
	});

interceptors

Global snippets to be executed before a said action (request, response)

import axios from 'axios';

axios.interceptors.request.use(config => {
	return config;
});
axios.interceptors.response.use(response => {
	return response;
});

custom multiple instances

Its possible to configure globally more then one axios instance so to have multiple global configurations

In a dedicated instance.js file

const instance = axios.create({
	baseURL: 'http://instancebaseurl//'
});


instance.defaults.headers.common['SomeInstanceConf'] = 'some value';
//... other axios configurations

export default instance;

In the location you need to use axios but with the instance configuration

import axios from '../path../instance';

// ... normal axios actions

authentication

SPA receive a Json Web Token (JWT) provided from authentication server; the token then gets stored into local browser baggage and via Vuex context, then accessed to check current authentication state or to send requests for data under authentication

Token stored in Vuex global state management (store.js)

๐Ÿ’ฅ need fix on args (name: value - not just value)

import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios';

Vue.use(Vuex);

export default {
	state: {
		idToken: null,
		userId: null,
		userData: null
	},
	mutations: {
		// login
		authUser(state, userData) {
			state.idToken = userData.token;
			state.userId = userData.userId;
		},
		// logout
		clearAuth(state) {
			state.idToken = null;
			state.userId = null;
		}
	},
	actions: {
		login({commit, dispatch}, authData) {
			// axios http request
			axios.post('http://url/', {
				authData
			}).then(res => {
				commit('authUser', {
					res.data.idToken,
					res.data.userId
				});
				dispatch('accessUserData');
			}).catch(error => {});
		},
		accessUserData({commit, state}) {
			// example for axios http request having the token set
			axios.get('http://url/auth='+state.idToken)
				.then(res => {
					state.userData = res.data;
				})
				.catch(error => {});
		},
		logout({commit}) {
			commit('clearAuth');
			// vue router redirect to home
			router.replace('/');
		}		
	},
	getters: {
		isAuthenticated(state => {
			return state.idToken !== null;
		})
		getUserData(state => {
			return state.userData;
		});
	}
}

auto logout out of timer

Automatically logout after a server-set timer expires

//... imports and stuff in main store.js

export default {
	//...
	actions: {
		setLogoutTimer({commit, dispatch}, expiresIn) {
			setTimeout(() => {
				dispatch('logout')
			}, expiresIn)
		},
		login({commit, dispatch}, authData) {
			//... in axios promise
			.then(res => {
				// start the timer
				dispatch('setLogoutTimer', res.data.expiresIn);
			})
			.error(err => {});
		}
	}
}

auto login within timer

Keep authentication after page reload, saving data in localStorage (browser storage)

//... imports and stuff in main store.js

export default {
	//...
	actions: {		
		login({commit, dispatch}, authData) {
			//... in axios promise
			.then(res => {
				// we can calculate exact datetime of auth expiration
				const now = new Date();
				const expirationDate = new Date(now.getTime() + res.data.expiresIn);
				// save server token and expiration date in browser baggage
				localStorage.setItem('myToken', res.data.idToken);
				localStorage.setItem('expirationDate', expirationDate);
				localStorage.setItem('userId', res.data.userId);
			})
			.error(err => {});
		},
		tryAutoLogin({commit}) {
			const token = localStorage.getItem('myToken');
			if (token) {
				const expirationDate = localStorage.getItem('expirationDate');
				const now = new Date();
				if (now < expirationDate) {
					const userId = localStorage.getItem('userId');
					commit('authUser', {
						idToken: token,
						userId: userId
					});
				}
			}
		},
		logout({commit}) {
			commit('clearAuth');
			// clear local storage
			localStorage.clear();
			// or clear specific items
			localStorage.removeItem('myToken');
			localStorage.removeItem('expirationDate');
			localStorage.removeItem('userId');
			router.replace('/');
		}
	}
}

lazy loading (webpack)

Importing components with lazy load for a webpack configuration

//import MyComponent from './..path../MyComponent.vue';

const MyComponent = resolve => {
	require.ensure(['./..path../MyComponent.vue'], () => {
		resolve(require('./..path../MyComponent.vue'));
	}, 'bundleGroupName');
};

๐ŸŽˆ bundleGroupName is not mandatory and but useful to let webpack bundle multiple components together even if lazy loaded

cheatsheet-vuejs's People

Contributors

lysla avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.