Immutable JavaScript / ES6 to do list

Here is my interpretation of how to create a simple JavaScript ToDo list based on immutability and states. You may also enjoy the JavaScript for beginners - learn by doing course.

So far there are only add and delete actions created:
<input id="myInput" type="text" /><button id="Add">Add new Todo </button>
<div id="app"></div>

<script>
// state object
var state = {
name: 'todo list 1',
todos: [{ id: 1, data: 'first todo <button class="delete" data-id="1">X</button>' }]
};

//we pass the todo as object({with id, and the todo_info})
function applyAction(todo, action) {
switch (action) {
case 'add':
return [...state.todos, todo];
break
case 'remove':
//here remove it from index using todo.id
return state.todos
.filter(dbTodo => dbTodo.id !== todo.id);
break
case 'update':
// return [
// ...state.todos
// .filter(dbTodo => dbTodo.id !== todo.id), // first we remove the soon to be updated todo
// todo // then we add the updated version to the end of the array
// ];
return state.todos.map(
dbTodo =>
// whe check when we have match on id, we use todo, otherwise we leave the original dbTodo
dbTodo.id === todo.id ? todo : dbTodo
);
break
}
}


let renderTodos = todos => {
return `
<ul>${state.todos.map(todo => `
<li>${todo.data}</li>
`)} `;
}


// The state-based UI rendering
var render = state => {
var html = `
<h1>
${state.name}</h1>
${ state.todos.length < 1 ? 'Please add a todo' : ''} ${renderTodos(state.todos)} `; app.innerHTML = html; }; let setState = obj => {
// update the state with passed object
Object.keys(obj).forEach(key => {
state[key] = obj[key];
});
//update the render
render(state);
}

// Add todo event listener
document.querySelector('#Add').addEventListener('click', () => {
// get what's inside the input
const inputData = document.querySelector('#myInput');
if (inputData.value == '') return;
// just mapping into new array only the ids, then doing max on them
let lastId = (state.todos.length > 0) ? Math.max(...state.todos.map(todo => todo.id)) : 0;
current_todo = { id: ++lastId, data: `${inputData.value} <button class="delete" data-id="${lastId}">X</button>` }
setState({ //save the modified state and show the result
todos: applyAction(current_todo, 'add') // apply the add modification to the state
});
// clear the value inside the input
inputData.value = '';
});

// Remove todo event listener
document.querySelector('#app').addEventListener('click', (e) => {
if (e.target.classList.contains('delete')) {
const id = +e.target.getAttribute('data-id'); // convert the string data-id to number
const currentTodo = { id };
setState({ // save the modified state and show the result
todos: applyAction(currentTodo, 'remove') // apply the add modification to the state
});
}
});

// Render the initial UI
var app = document.querySelector('#app'); render(state);
</script>

Congratulations ! 

Resources:

JavaScript for beginners - learn by doing
Author Photo

About Nevyan Neykov

I do web design and development for more than 15 years. Have been working in various companies dealing mainly with PHP and JavaScript. Independently as well as in teams, I am involved in design and development of user friendly websites. Exploring the new aspects of JavaScript language such as ES6, as well as the Angular framework and how to apply them in practice. Nowadays I find dealing with Docker / Kubernetes and Linux system administration compelling. @youtube: https://www.youtube.com/channel/UC69XQPDbEpfAtO5S2-ZyNoA at udemy: https://www.udemy.com/user/nevyan-neykov/ Have a nice day !

View Full Profile →