Первое приложение на Angular за 20 минут

image

Для cправки: Angular это фреймворк построенный на базе JavaScript, созданный Misko Hevery и поддерживаемый Google. Вы можете посетить официальную страницу чтобы узнать больше.

Версия Angular, используемая в данном примере 5.2.10. Следует отметить, что одновременно существует первая версия 1.x и вторая версия 2.x, Angular и эти версии пролностью отличны одна от другой по своей структуре и методам. Об этом не стоит беспокоится, потому что в этой статье мы будем использовать второе поколение Angular 2.x.

Содержание

  • Добавление элемента (узнаете, как отправить форму в Angular)
  • Удаление элемента (узнаете как добавить событие в Angular)
  • Анимация в Angular(узнаете как анимировать компоненты)

Подготовка:

  • Node.js

Проверьте установлен ли Node.js на ваш компьютер. Больше об инсталяции.

  • npm (node package manager) устанавливается вместе с Node.js

Проверьте версию node.js :

node -v

Проверьте версию npm :

npm -v

Angular-CLI

У вас должна быть установлена последняя версия Angular-CLI (интерфейс коммандной строки Angular). Подробнее об Angular-CLI читайте здесь, и там-же можно найти инструкции по установке.

Для установки Angular-CLI выполните в терминале комманду:

npm install -g @angular/cli

Не лишним будет:

  • базовое знание JavaScript
  • относительные знание и понимание HTML и CSS

Знание Angular в данном случае не является необходимым условием.

Теперь, если все готово можно приступить к написанию первого приложения на Angular.

Создание первого приложения

Для создания и генерирования компонентов приложения будем использовать Angular-CLI. С его помощью сгенерируем все необходимые файлы и директории. Для создания нового Angular проекта с помощью Angular-CLI надо просто выполнить в терминале следующую комманду:

ng new my-app 

В примере выше "my-app" это название проекта.

Проект сгенерируется автоматически. Создадим наше приложение, которое назовем "todo-app".

ng new todo-app

Затем откроем соответствующую директорию в текстовом редакторе. Для данного проекта используется Sublime Text, но подойдет любой другой, например: Atom или Visual Studio Code. Структура созданной директории должна выглядеть примерно так:

Angular app

Не волнуйтесь о том, что увидели такое огромное количество файлов. Вся работа по написанию приложения будет происходить в поддиректории app. Она содержить всего пять файлов:

Angular app

Angular2 использует TypeScript в котором файлы имеют расширение ".ts".

Для создания интерфейса программы будем использовать фреймворк Bootstrap4.

Добавьте bootstrap cdn в файл index.html.

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/
bootstrap.min.css" integrity="sha384-
Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/
dAiS6JXm"crossorigin="anonymous">

Запустите приложение в терминале:

ng serve

Приложение будет запущего по локальному адресу http://localhost:4200/

App Works

Все работает !

Сейчас давайте создадим HTML структуру. Будем использовать готовые классы, которые есть в Bootstrap, чтобы создать простую форму.

To-Do App

app.component.html:

<div class="container">
 <form>
  <div class="form-group">
  <h1 class="text-center text-primary">Todo App</h1>
   <div class="input-group-prepend">
       <input type="text" class="form-control" placeholder="Add Todo" name="todo">
    <span class="input-group-text">Add</span>
   </div>
  </div>
 </form>
</div>

app.component.css:

body{
 padding: 0;
 margin: 0;
}
form{
 max-width: 25em;
 margin: 1em auto;
}

Чтобы получить входящее значение в Angular 2, мы можем использовать директиву ngModel. Вы можете вставить переменную как атрибут внутри элемента ввода.

ngModel

<input type="text" #todo class="form-control" placeholder="Add Todo" 
name="todo" ngModel>

Для создания переменной как атрибута используем #, а затем указываем имя переменной:

<input #myVariable type="text" name="text" ngModel>
// get the value of the Variable
<p>{{myVariable.value}}</p>

После получим значение переменоой "todo":

<p>{{todo.value}}</p>

Сохраним значение переменной, полученной из формы input. Мы можем создать пустой массив в app.components.ts внутри класса AppComponents:

export class AppComponents {
	todoArray=[ ]
	}

Затем добавим событие click к нашей кнопке, которая отправляет получаемые значения в массив todoArray.

todoArray

app.component.html:

<span class="input-group-text" (click)="addTodo(todo.value)">Add</span>

app.component.ts:

export class AppComponent {
 todoArray=[]
addTodo(value){
    this.todoArray.push(value)
    console.log(this.todos)
  }
 
}

Используйте комманду console.log(this.todoArray) чтобы увидеть значение массива

Получение данных из массива todoArray

Сейчас вы должны получить данные, хранимые в массиве todoArray. Для этого будем использовать директиву ngFor, чтобы циклом "for" пройтись по массиву и извлечь данные.

app.component.html::

<div class="data">
  <ul class="list-instyled">
   <li *ngFor="let todo of todoArray">{{todo}}</li>
  </ul>
  </div>

После прохождения цикла должно получиться следующее:

ngFor

Эти данные будут добавляться в массив автоматически после нажатия на кнопку "Ad".

To-Do App

Стилизация приложения

В данном проетке будем использовать Google-fonts and Material-icons, которые отлично себя зарекомендовали и, к тому же, бесплатны.

Добавим Google fonts в app.component.css:

/*Google fonts*/
@import url('https://fonts.googleapis.com/css?family=Raleway');

Также поступим с Material-icons в index.html:

<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">

После дополнительно стилизуем элементы приложения и получим примерно следующий вид:

ngFor

Применим Material-icons:

<i class="material-icons>iconName</i>

Добавим иконки "delete" и "add" в app.component.html:

// put add icon inside "input-group-text" div
<span class="input-group-text" (click)="addTodo(todo.value)">
<i class="material-icons">add</i>
</span>
// and delete icon inside list item
 
<li *ngFor="let todo of todoArray">{{todo}}
<i class="material-icons">delete</i>
</li>

Изменим таблицу стилей в app.component.css:

/*Google fonts*/
@import url('https://fonts.googleapis.com/css?family=Raleway');
body{
 padding: 0;
 margin: 0;
}
form{
 max-width: 30em;
 margin: 4em auto;
 position: relative;
 background: #f4f4f4;
 padding: 2em 3em;
}
form h1{
    font-family: "Raleway";
    color:#F97300; 
}
form input[type=text]::placeholder{
   font-family: "Raleway";
   color:#666; 
}
form .data{
    margin-top: 1em;
}
form .data li{
 background: #fff;
 border-left: 4px solid #F97300;
 padding: 1em;
 margin: 1em auto;
 color: #666;
 font-family: "Raleway";
}
form .data li i{
    float: right;
    color: #888;
    cursor: pointer;
}
form .input-group-text{
    background: #F97300;
    border-radius: 50%;
    width: 5em;
    height: 5em;
    padding: 1em 23px;
    color: #fff;
    position: absolute;
    right: 13px;
    top: 68px;
    cursor: pointer;
}
form .input-group-text i{
    font-size: 2em;
}
form .form-control{
 height: 3em;
    font-family: "Raleway";
}
form .form-control:focus{
 box-shadow: 0;
}

Наше приложение почти закончено, но надо еще добавить некоторые элементы. Функционал удаления должен позволять пользователю нажимать на икоку "delete" и удалять пункт из списка. Также было бы здорово иметь опцию включения в список новых пунктов с помощью простого нажатия на клавишу "Enter", а не нажимая каждый раз на кнопку "Add".

Deleting items

Для добавления функциональности удаления будем использовать метод массива "splice" и цикл "for". Пройдем циклом по всему массиву данных и выберем элемент, уоторый хотим удалить из списка.

Добавим событие "click" к иконке "delete" и передадим элемент "todo" как входящий параметр:

<li *ngFor="let todo of todoArray">{{todo}} <i (click)="deleteItem(todo)" 
class="material-icons">delete</i></li>

app.component.ts:

/*delete item*/
  deleteItem(){
   console.log("delete item")
  }

Когда вы нажмете на иконку "delete" консоль браузера должна возвратить:

Консоль браузера

Теперь нам нужно пройти циклом через массив todoArray, найти и удалить из списка элемент, который мы хотим удалить.

app.component.ts:

/*delete item*/
  deleteItem(todo){
   for(let i=0 ;i<= this.todoArray.length ;i++){
    if(todo== this.todoArray[i]){
     this.todoArray.splice(i,1)
    }
   }
  }

Результат должен быть примерно таким:

Консоль браузера

Неплохо !!

Функционал добавления элементов

Подтверждение отправки формы (submit) добавим следующим образом:

(ngSubmit)="TodoSubmit()"

Нам нужно добавить переменную #todoForm в форму и присвоить ей значение ngForm. В этом случае у нас есть только одно поле, поэтому мы получим только одно значение. Если у нас есть несколько полей, событие submit вернет значения всех полей в форме.

app.component.html

<form #todoForm= "ngForm" (ngSubmit)="todoSubmit(todoForm.value)"></form>

app.component.ts

// submit Form
  todoSubmit(value:any){
 console.log(value)
  }

Консоль браузера в этом слечае вернет значения объекта todo:

Консоль браузера

Итак, теперь мы должны подключить нажатие на клавишу "Enter" для изменения элементов массива todoArray:

// submit Form
  todoSubmit(value:any){
     if(value!==""){
    this.todoArray.push(value.todo)
     //this.todoForm.reset()
    }else{
      alert('Field required **')
    }
    
  }

Значение вставляется без необходимости нажатия кнопки "Add", просто нажав клавишу "Enter":

Консоль браузера

Еще одна деталь. Чтобы очистить поле формы после отправки данных, добавьте метод resetForm() для отправки события.

<form #todoForm= "ngForm" (ngSubmit)="todoSubmit(todoForm.value); 
todoForm.resetForm()" ></form>

Поле формы будет очищаться после каждой отправки данных формы:

Консоль браузера

Добавление анимации

Было бы неплохо добавит немного анимации. Чтобы добавить анимацию, импортируйте компоненты анимации в файл app.component.ts:

import { Component,trigger,animate,style,transition,keyframes } from 
'@angular/core';

Затем добавьте свойство анимации в декоратор "@component":

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  animations:[
   trigger("moveInLeft",[
      transition("void=> *",[style({transform:"translateX(300px)"}),
        animate(200,keyframes([
         style({transform:"translateX(300px)"}),
         style({transform:"translateX(0)"})
 
          ]))]),
transition("*=>void",[style({transform:"translateX(0px)"}),
        animate(100,keyframes([
         style({transform:"translateX(0px)"}),
         style({transform:"translateX(300px)"})
 
          ]))])    
     
    ])
]
})

Теперь элементы анимированы приятными эффектами, когда они добавляются или удаляются.

Консоль браузера

Весь код

app.component.ts

import { Component,trigger,animate,style,transition,keyframes } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  animations:[
   trigger("moveInLeft",[
      transition("void=> *",[style({transform:"translateX(300px)"}),
        animate(200,keyframes([
         style({transform:"translateX(300px)"}),
         style({transform:"translateX(0)"})
 
          ]))]),
transition("*=>void",[style({transform:"translateX(0px)"}),
        animate(100,keyframes([
         style({transform:"translateX(0px)"}),
         style({transform:"translateX(300px)"})
 
          ]))])    
     
    ])
]
})
export class AppComponent {
  todoArray=[];
  todo;
  //todoForm: new FormGroup()
addTodo(value){
    if(value!==""){
     this.todoArray.push(value)
    //console.log(this.todos) 
  }else{
    alert('Field required **')
  }
    
  }
/*delete item*/
  deleteItem(todo){
   for(let i=0 ;i<= this.todoArray.length ;i++){
    if(todo== this.todoArray[i]){
     this.todoArray.splice(i,1)
    }
   }
  }
// submit Form
  todoSubmit(value:any){
     if(value!==""){
    this.todoArray.push(value.todo)
     //this.todoForm.reset()
    }else{
      alert('Field required **')
    }
    
  }
 
}

app.component.html

<div class="container">
 <form #todoForm= "ngForm"(submit)="todoSubmit(todoForm.value);
  todoForm.resetForm()" >
  <div class="form-group">
  <h1 class="text-center ">Todo App</h1>
   <div class="input-group-prepend">
       <input type="text" #todo  class="form-control"
        placeholder="Add Todo" name="todo" ngModel>
    <span class="input-group-text" (click)="addTodo(todo.value)">
    <i class="material-icons">add</i></span>
   </div>
  </div>
  <div class="data">
  <ul class="list-unstyled">
   <li [@moveInLeft]  *ngFor="let todo of todoArray">{{todo}} 
   <i (click)="deleteItem(todo)" class="material-icons">delete</i></li>
  </ul>
 </div>
 </form>
</div>

app.component.css

/*Google fonts*/
@import url('https://fonts.googleapis.com/css?family=Raleway');
body{
 padding: 0;
 margin: 0;
}
form{
 max-width: 30em;
 margin: 4em auto;
 position: relative;
    background: #f4f4f4;
    padding: 2em 3em;
    overflow: hidden;
}
form h1{
    font-family: "Raleway";
    color:#F97300; 
}
form input[type=text]::placeholder{
   font-family: "Raleway";
   color:#666; 
}
form .data{
    margin-top: 1em;
}
form .data li{
 background: #fff;
 border-left: 4px solid #F97300;
 padding: 1em;
 margin: 1em auto;
 color: #666;
 font-family: "Raleway";
}
form .data li i{
    float: right;
    color: #888;
    cursor: pointer;
}
form .input-group-text{
    background: #F97300;
    border-radius: 50%;
    width: 5em;
    height: 5em;
    padding: 1em 23px;
    color: #fff;
    position: absolute;
    right: 13px;
    top: 68px;
    cursor: pointer;
}
form .input-group-text i{
    font-size: 2em;
}
form .form-control{
 height: 3em;
    font-family: "Raleway";
}
form .form-control:focus{
 box-shadow: 0;
}

Все, мы закончили. Файлы и код проекта можно найти на Github.

Источник