code
Для cправки: Angular это фреймворк построенный на базе JavaScript, созданный Misko Hevery и поддерживаемый Google. Вы можете посетить официальную страницу чтобы узнать больше.
Версия Angular, используемая в данном примере 5.2.10. Следует отметить, что одновременно существует первая версия 1.x и вторая версия 2.x, Angular и эти версии пролностью отличны одна от другой по своей структуре и методам. Об этом не стоит беспокоится, потому что в этой статье мы будем использовать второе поколение Angular 2.x.
Проверьте установлен ли Node.js на ваш компьютер. Больше об инсталяции.
Проверьте версию node.js :
node -v
Проверьте версию npm :
npm -v
У вас должна быть установлена последняя версия Angular-CLI (интерфейс коммандной строки Angular). Подробнее об Angular-CLI читайте здесь, и там-же можно найти инструкции по установке.
Для установки Angular-CLI выполните в терминале комманду:
npm install -g @angular/cli
Не лишним будет:
Знание 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. Структура созданной директории должна выглядеть примерно так:
Не волнуйтесь о том, что увидели такое огромное количество файлов. Вся работа по написанию приложения будет происходить в поддиректории 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/
Все работает !
Сейчас давайте создадим HTML структуру. Будем использовать готовые классы, которые есть в Bootstrap, чтобы создать простую форму.
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. Вы можете вставить переменную как атрибут внутри элемента ввода.
<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.
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. Для этого будем использовать директиву ngFor, чтобы циклом "for" пройтись по массиву и извлечь данные.
app.component.html::
<div class="data">
<ul class="list-instyled">
<li *ngFor="let todo of todoArray">{{todo}}</li>
</ul>
</div>
После прохождения цикла должно получиться следующее:
Эти данные будут добавляться в массив автоматически после нажатия на кнопку "Ad".
В данном проетке будем использовать 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">
После дополнительно стилизуем элементы приложения и получим примерно следующий вид:
Применим 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.