Youtube channel !

Be sure to visit my youtube channel

Thursday, December 19, 2019

To do list in Angular

Here is how to create a simple todo-list in Angular. We will be also using extensively RxJs BehaviorSubject as well as Observables. If you want more information on the techniques used, I advise you to practice with the full Angular for beginners course.




First install angular with: sudo npm i -g @angular/cli
Then create a new todo project: ng new todo
Inside the todo directory create 2 new components and service using the Angular CLI:
ng g c todos
ng g c form
ng g s services/todos

Next, modify the following files:
app.component.html
// to include the new component tags
<div class="container">
<h1>{{appTitle}}</h1>
<app-todos [limit]="3"></app-todos>
<app-form></app-form>
</div>
...
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { TodosComponent } from './todos/todos.component';

// import httpclientmodule to be able to perform http requests
import { HttpClientModule } from '@angular/common/http';

// import forms module to be able to use 2-way [(binding)]
import { FormsModule } from '@angular/forms';
import { FormComponent } from './form/form.component';

@NgModule({
declarations: [
AppComponent,
TodosComponent,
FormComponent
],
// and place it (FormsModule) inside modules to be visible by all derived services and componenets
imports: [
BrowserModule,
HttpClientModule,
FormsModule //  add into imports the formsmodule to be accessible from the components
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

...
form.component.html

<div>
<input type="text" placeholder="Add todo..."
<!-- bind the title input field of the form to the model this.title -->
[(ngModel)]="title"
<!-- allow with enter to be able to run addTodo() -->
(keydown.enter)="addTodo()" />
<button (click)="addTodo()">Add todo</button>
</div>

...
form.component.ts

import { Component } from '@angular/core';
// import both the interface Todo as well as the TodoService
import { Todo, TodosService } from '../services/todos.service';

@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss']
})

export class FormComponent implements OnInit {
// title will be bound to the title input of the form
title: string = '';

// use dependency injection to inject the TodosService
constructor(private todosService: TodosService) { }

addTodo() {
// construct todo object and add it using the service
const todo: Todo = {
id: Date.now(),
title: this.title,
complete: false,
}
this.todosService.addTodo(todo);
}
}
...


todos.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { TodosService, Todo } from '../services/todos.service';
import { Observable } from 'rxjs';

@Component({
selector: 'app-todos',
templateUrl: './todos.component.html',
styleUrls: ['./todos.component.scss']
})
export class TodosComponent implements OnInit {

constructor(private todosService: TodosService) { }
private fetchData$: Observable<boolean>;
private todos$: Observable<Todo[]>;

// receive the limit from the parent(appcomponent) via input
@Input() limit: number;

ngOnInit() {
// initialize the both observables
this.fetchData$ = this.todosService.getTodos(this.limit);
this.todos$ = this.todosService.todos$;
}

// call the service
onChange(id: number) {
this.todosService.onToggle(id);
}

// call the service
removeTodo(id: number) {
this.todosService.removeTodo(id);
}

}

...

todos.component.html

<!-- mainly to fetch the http json data & setup this.todos -->
<div *ngIf="(fetchData$ | async ); else errorFetch"></div>

<!-- get the observable data and spread it on the page -->
<ul *ngIf="(todos$ | async ) as todos; else loading">
<li *ngFor="let todo of todos; let i = index">
<span [class.done]="todo.complete">
<input type="checkbox" [checked]="todo.complete" (change)="onChange(todo.id)">
<!--  bind [checked] to the state complete of todo
 pass todo.id on(change) event,
and run onChange function from the .ts file
-->
{{i + 1}} {{todo.title}}
</span>
<small>{{todo.date | date}}</small>
<!-- use pipe date to format the data: you can see other pipes from API/datepipe on angular website -->
<button class="remove" (click)="removeTodo(todo.id)">×</button>
</li>
</ul>

<ng-template #loading> Loading, please wait ...</ng-template>
<ng-template #errorFetch> There is an error while loading the data, please try again ...</ng-template>

...

todos.service.ts

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject, of } from 'rxjs';
import { tap, map, catchError } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

// create interface with the structure of a simple todo item
export interface Todo {
id: number
title: string
complete: boolean
}

@Injectable({
providedIn: 'root'
})
export class TodosService {

constructor(private http: HttpClient) { }
public todos: Todo[] = [];
private subject = new BehaviorSubject<Todo[]>([]); // to be able to retain the last emitted version !
public todos$ = this.subject.asObservable();

getTodos(limit: number): Observable<boolean> {

return this.http.get<Todo[]>(`https://jsonplaceholder.typicode.com/todos?_limit=${limit}`)
//  just return observable of true or false
.pipe(
map((fetchedTodos: Todo[]) => {
// setup the local this.todos member
this.todos = fetchedTodos;
// propagade the todos to subscribers via subject
this.subject.next(this.todos);
return true;
}),
catchError(err => {
alert(err.message);
return of(false);
})
);
}

onToggle(id: number) {
// get the todo index by the provided ID
const idx = this.todos.findIndex(todo => todo.id === id);
this.todos[idx].complete = !this.todos[idx].complete;
}

removeTodo(id: number) {
this.todos = this.todos.filter(todo => { return todo.id !== id }
);

// propagade the updated data back to all observables
this.subject.next(this.todos);
}

addTodo(todo: Todo) {
this.todos = [...this.todos, todo];
this.subject.next(this.todos);
}
}

Now you can run: ng serve
and browse: http://127.0.0.1:4200

Congratulations and enjoy learning Angular.

Sunday, December 15, 2019

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

Friday, December 06, 2019

How to prevent Burnout in the IT


Let's first think about what might cause it:
Burnout is a more and more frequent condition in the IT-sphere and is usually caused by working in a toxic work culture which includes:
- not enjoying the colleagues double-faced behavior, or what they do with their money :)
- colleagues who might be trying to get you out of their career path
- experiencing a non-supportive mixed joking / passive-aggressive behavior from supervisors, without being able to respond
- not enjoying the technologies working with such as outdated software, frameworks or languages
- trying to keep up with the pace by learning, and at the same time thinking if you don't know in details about the latest updates, you won't fit inside the team and will be fired
- trying to schedule your rest/work time, by being flooded at an unexpected time with task tickets (time-restricted)
- not having the opportunity to express your view on certain subjects, or when expressing them they are left without a response
- thinking that the whole IT sphere is getting more and more filled with people, who can as well as pick potatoes if the job is well payed
All those can quickly build up and you may start to have repetitive negative thoughts about doing the work and at the same time trying to be cheerful around the colleagues - a form of cognitive dissonance.

The following are my remedies:
You'll need to learn to quickly how to balance between your focused and default brain network:
Have at least 1 hour of walks in fresh air.
Here is some immediate basic exercise, you can do without postponing :)

Do sports, running combined with positively reinforced repetitions of I am ok, I am healthy... fill in some empowering words that work for you...
Work on a standing desk in order to reinforce your focused network, and having breaks as much as you would like. Remember your job and that of an HR is not of the same difficulty :) If, on a budget, you can do standing desk by yourself using some books or cardboard boxes.
Optional: extensively use high-quality headphones
About performing tasks: write the task, in the form of a mini and detailed plan on how to do the task and then just relax and have fun. When it is time to choose to do a particular task, just open the plan and do it, without having to think or improvise ways on what is the proper way to do the task or which task to choose.
Lastly - simply quit your job.

Subscribe To My Channel for updates

Modernizing old php project with the help of AI

0. Keep docker running in separate outside of VSCODE terminal 1. The importance of GIT for version control - create modernization branch 2. ...