Это вторая часть о создании презентационного приложения Angular2. В этой части я покажу вам, как добавить необходимую логику (сервисы, компоненты и т. Д.). Первая часть была о создании приложения с помощью angular-cli, и теперь у вас должен быть свежий инициированный проект Angular2 в качестве отправной точки.

Это ссылка на репозиторий: https://github.com/EsSpricht/angular2-bootstrap

Страница представления должна содержать следующее:

  • Изображение, представляющее пользователя (аватар)
  • Некоторая личная информация, например имя пользователя и т. Д.
  • Хронология, представляющая своего рода резюме

начнем с изображения и личной информации. Начнем с создания нового класса под названием Owner:

ng generate class Owner --spec

это отличный пример того, насколько полезен angular-cli. Он создаст класс внутри правильной папки и уже добавит несколько выражений по умолчанию.
src/app/owner.ts

Если вы поближе познакомитесь с этим каталогом, вы увидите еще один файл с именем src/app/owner.spec.ts. Этот файл понадобится вам для определения ваших модульных тестов, и он есть, потому что мы использовали флаг спецификации, но я объясню это позже.

Давайте сосредоточимся на файле owner.ts и откроем его:

export class Owner {
}

Довольно пусто, правда? мы должны добавить все необходимое, чтобы получился отличный хозяин:

export class Owner {
  name: string = '';
  age: number;
  country: string = '';
  jobtitle: string = '';
  company: string = '';
  constructor(values: Object = {}) 
   {
    Object.assign(this, values);
   }
 }

Это должно быть все, чтобы абстрагироваться от владельца. Я просто определил для него некоторые переменные и создал конструктор, которому нужен массив со значениями для всех переменных в качестве параметра, например:

let owner = new Owner({
  name: 'Baerree',
  age: 33,
  country: 'GER',
  jobtitle: 'Software Developer',
  company: 'ABC DEV'
});

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

$ ng generate class Task --spec

У вас снова будет два новых файла в папке src / app. Откройте файл task.ts и добавьте немного логики:

export class Task {
  id: number;
  title: string = '';
  description: string = '';
  fromDate: string = '';
  toDate: string = '';
  constructor(values: Object = {}) {
   Object.assign(this, values);
  }
}

Я использую строковые переменные для дат, чтобы сэкономить время, вы можете изменить это позже. Давайте создадим задачу и владельца в нашем основном компоненте:

Это будет всего лишь небольшой тест, чтобы убедиться, что все работает должным образом, позже вы удалите это снова. Вначале я буду использовать только один компонент, но Angular2 предназначен для использования множества из них, но для моей цели достаточно одного основного компонента.
Не волнуйтесь, мы добавим другие компоненты позже. Чтобы лучше разбираться в компонентах, прочтите это. В общем, вы можете представить себе компонент как часть головоломки. Это всего лишь одна часть вашего веб-приложения. Достаточно сказать, откройте компонент приложения:

src/app/app.component.ts

и создайте переменную типа Владелец:

import { Component } from '@angular/core';
import { Owner } from './owner';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  owner = new Owner({
   name: 'Baerree',
   age: 33,
   country: 'GER',
   jobtitle: 'Software Developer',
   company: 'ABC DEV'
});
}

Я удалил переменную заголовка и добавил свойство владельца. Как видите, я определил все значения внутри массива с парами ключ-значение и «,» в качестве разделителя. Это возможно, потому что у Owner есть конструктор с

values: Object = {}

как входной параметр. Следующим шагом является соединение логики html с логикой в ​​app.component. Объем html-файла всегда является областью компонента, на который он ссылается. В этом случае app.component.html может получить доступ к контексту app.component.ts. Angular-cli определил это уже внутри аннотации @component:

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

Это связь между кодом HTML (app.component.html) и кодом компонента (app.component.ts). И поэтому вы можете написать что-то вроде этого:

<h1>{{title}}</h1>

Это синтаксис шаблона Angular2, и Angular решит его за вас. Давайте добавим несколько ссылок на только что созданное свойство owner. Откройте app.component.html и добавьте к нему следующее:

<h1>
 {{owner.name}}
 {{owner.age}}
 {{owner.country}}
 {{owner.jobtitle}}
 {{owner.company}}
</h1>

запустите приложение, набрав: ng serve

Не красиво, но работает! Позже вы все стилизуете. На данный момент следующим шагом является создание службы, которая будет представлять временную шкалу и предоставлять / управлять всеми данными (задачами) и функциями для нее. В идее услуги нет ничего нового. В AngularJS было обычным способом сделать данные доступными из любой точки вашего приложения.

Вы рано или поздно столкнетесь с проблемой, что вам нужны данные, определенные вне вашего контекста, и именно поэтому angular придумал сервисы. Вы установите свои данные и функции внутри службы и внедрите эту службу, где бы она вам ни понадобилась. Чтобы лучше понять сервисы, прочтите это руководство.

Хорошо, снова открываем терминал и создаем сервис:

$ ng generate service Tasks

Это сгенерирует следующие файлы:

src/app/tasks.service.ts and src/app/tasks.service.spec.ts

И да, есть файл .spec даже без использования параметра --spec, angular-cli автоматически создает модульный тест, когда дело доходит до служб.

Мне нравится называть сервис во множественном числе того, что он представляет. Задача - ›Задачи, поскольку angular-cli добавит часть * .service. * Соответственно к имени файла. Откройте src/app/tasks.service.ts и посмотрите:

import { Injectable } from '@angular/core';
@Injectable()
export class TasksService {
  constructor() { }
}

Здесь нет ничего особенного и довольно прямолинейного, вместо одной маленькой детали:

@Injectable()

Позвольте мне потерять несколько слов по этому поводу. Эта аннотация или декоратор не означает, что класс TasksService является инъекционным! Я знаю, что это сбивает с толку, но если вы не ссылаетесь на другие службы в своем сервисе (вложенные зависимости), вам это в основном не нужно. Это вообще не требуется для услуги. Для единообразия рекомендуется добавлять его в каждую службу.

Для получения дополнительной информации о внедрении зависимостей и о том, как это работает в Angular2, прочтите этот документ.

Прежде чем мы добавим логику к сервису, нам понадобится еще один файл, содержащий несколько примеров задач. На этот раз вам нужно создать его вручную без использования angular-cli, поскольку это просто контейнер с константами. Создайте следующий файл:

src/app/mock-tasks.ts

откройте его и добавьте несколько таких задач:

import { Task } from './task';
export const TASKS: Task[] = [
{id: 1, title: 'Software School Worms',
description: 'A software school for children.',
fromDate: '01.01.2009',
toDate: '20.08.2010'},
{id: 2, title: 'Siemens Education Program',
description: 'Software Enegneer Apprenticeship',
fromDate: '01.09.2010',
toDate: '01.10.2013'},
{id: 3, title: 'Junior Developer Professional Service',
description: 'Working as junior software developer for ABC DEV in the professional service dep.',
fromDate: '01.10.2013',
toDate: '01.12.2015'},
{id: 4, title: 'Software Developer and Consultant ,Research and Innovation',
description: 'Working as developer and consultant for software solutions at ABC DEVs research and innovation dep.',
fromDate: '01.12.2015',
toDate: ''}
];

Этого должно быть достаточно. Давайте наконец добавим в сервис бизнес-логику:

import { Injectable } from '@angular/core';
import { Task } from './task';
import { TASKS } from './mock-tasks';
@Injectable()
export class TasksService {
  tasklist: Task[];
  currentID: number;
  constructor() {
   this.tasklist = TASKS;
   this.currentID = this.tasklist.length;
  }
  addTask(newTask: Task){
   let newID =  ++this.currentID;
   newTask.id = newID;
   this.tasklist.push(newTask);
  }
  deleteTask(id: number) {
   this.tasklist = this.tasklist.filter(task => task.id !== id);
  }
  getTasklist(): Task[] {
   return this.tasklist;
  }
}

Здесь есть что объяснить. Прежде всего импорт; Я импортировал сам класс Task, потому что сервису нужно сейчас ссылаться на него. Я также импортирую фиктивный список ЗАДАЧ. Позже вы замените его вызовом базы данных, но пока он нам нужен. В injectable () нет необходимости, поскольку нет ссылки на другой сервис, но, как я упоминал ранее, мы должны сохранить его.

Я также определил две переменные tasklist, которые представляют собой массив задач, и currentID, которые представляют длину массива списка задач. Я буду использовать его, чтобы найти следующий свободный идентификатор, но это непоследовательно и подходит только для этого случая.

addTask() и deleteTask(id: number) делают то, что подразумевает их название. Вы будете использовать его позже, но уже можете скопировать / вставить.

getTasklist() просто вернет список задач. Важнее всего в этом сервисе его конструктор. Переменная tasklist указывает на константы ЗАДАЧИ и позволяет получить к ней доступ извне службы. currentID равен размеру массива, который вначале равен 4, потому что я определил только 4 задачи в фиктивном классе.

Давайте улучшим компонент и, следовательно, HTML. откройте src/app/app.component.ts и добавьте:

import { Component } from '@angular/core';
import { Owner } from './owner';
import { TasksService } from './tasks.service';
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css'],
 providers: [TasksService]
})
export class AppComponent {
  constructor(private tasksService: TasksService) {}
  owner = new Owner({
   name: 'Baerree',
   age: 33,
   country: 'GER',
   jobtitle: 'Software Developer',
   company: 'ABC DEV'
  });
  get tasks(){
   return this.tasksService.getTasklist();
  }
}

Прежде всего вам нужно импортировать службу import { TasksService} from './tasks.service';, но этого недостаточно, чтобы внедрить службу, необходимо сообщить инжектору зависимостей, что он должен ее найти. Это делается добавлением: providers: [TasksService]

Последнее, что вам нужно сделать, прежде чем вы получите доступ к службе, - это создать ее переменную. Лучше всего это сделать внутри конструктора. Добавив private tasksService: TaskService в качестве параметра. На этом этапе на компонент будет введена ссылка.

get tasks() - это просто пересылка на getTasklist() внутри службы. В этом нет необходимости, потому что вы можете использовать tasksService напрямую из html. Поскольку логическая часть удовлетворена, единственное, чего не хватает, - это представления. Добавьте это в html-файл src/app/app.component.html:

<h1>
{{owner.name}}
{{owner.age}}
{{owner.country}}
{{owner.jobtitle}}
{{owner.company}}
</h1>
<section>
 <header>
 <h1>Tasks ({{tasksService.currentID}}):</h1>
 </header>
 <section *ngIf="tasks.length > 0">
  <ul>
   <li *ngFor="let task of tasks">
    <div>
     <label>{{task.id}}</label>
     <label><b>{{task.title}}</b></label>
     <label>{{task.description}}</label>
    </div>
   </li>
  </ul>
 </section>
</section>

Вы частично знакомы с синтаксисом шаблона, потому что использовали его для владельца, например {{owner.name}}. Я сделал то же самое с тегом <h1>. Вы должны признать, что я обращался к службе taskService напрямую. Это возможно и удобно, если вам не нужно добавлять лог. Другая возможность - создать дополнительную функцию внутри компонента, которая вызывает служебную функцию, как мы это делали с get tasks(){..}.

Давайте посмотрим на второй тег <section>, оператор *ngIf="tasks.length > 0" также является частью синтаксиса шаблона Angular2. ngIf полностью удаляет элемент и его дочерние элементы из DOM, если условие tasks.length > 0 ложно. Вы будете использовать это утверждение очень часто.

Чтобы лучше разобраться в шаблоне синтаксиса Angular2, настоятельно рекомендую прочитать официальную документацию.

Следующим новым оператором является *ngFor внутри элемента списка <li>. Это простой цикл FOREACH, который выполняет итерацию по всем задачам и добавляет элемент списка в DOM. Хорошо то, что он генерирует элемент Task на каждом проходе, поэтому вы можете получить к нему доступ, как {{task.title}}.

Запуск $ ng serve обновит браузер и покажет нам уродливое, но работающее веб-приложение, показывающее всю информацию, которую вы добавили до сих пор.

На этом все. Все готово, и вы должны стилизовать его в части 3.
Я покажу вам, как улучшить проект, добавив больше логики и маршрутизации в части 4. Другие части также будут выполнены (модульные тесты, база данных и т. Д.) )

CU в следующей части и спасибо за прочтение.