WEB start

Компьютеры. Интернет. Профессиональное обучение. 055-966-10-17

hit 
counter

Наши преимущества

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


Регистрация на сайте

WEB дизайн

  • Angular 6

    Angular

    Angular - это фреймворк, разработанный Google для создания клиентских (frontend WEB development) приложений. Прежде всего он предназначен для разработки SPA - проектов (Single Page Application), то есть одностраничных приложений. В этом плане Angular является наследником другого фреймворка AngularJS. В то же время Angular, начиная с версии 2, это не новая версия AngularJS, а принципиально новый фреймворк.

    Последняя версия Angular на момент написания - Angular 6. Официальный репозиторий фреймворка на гитхаб: https://github.com/angular/angular.

    Одной из ключевых особенностей Angular является то, что он использует в качестве языка программирования TypeScript. Можно писать приложения на Angular с помощью таких языков как Dart, ECMAScript или JavaScript. TypeScript является основным языком для Angular.

    Язык TypeScript - это надмножество языка ECMAScript 6 (также известной как ECMAScript 2015, ES2015), которое компилируется в обычный код на JavaScript (ES5) и широко поддерживается современными ОС.

    На настоящий момент браузеры не имеют встроенной поддержки ни TypeScript, ни ECMAScript 6, поэтому для публикации на сервеере код должен быть преобразован в код на JavaScript, поддерживаемый всеми браузерами.

    Установка Angular

    https://angular.io/guide/setup#windows

    NodeJS

    Установка

    NodeJS ( Node.js® - это среда выполнения для языка JavaScript, построенная на платформе JavaScript V8 для Chrome. https://nodejs.org/en/)

    Node.js позволяет запускать JavaScript-код вне браузера.

    Чтобы JavaScript код выполнился вне браузера (на backend), он должен быть интерпретирован и выполнен. Именно это и делает Node.js. Для этого он использует движок V8 VM от Google — ту же самую среду исполнения для JavaScript, которую использует браузер Google Chrome.

    Скачать установочный пакет для нужной операционной системы и запустить установку, соогласно инструкции.

    Так, например, для 32 bit Windows нужен файл: node-v8.9.4-x86.msi . Программа установки NodeJS для Windows одной из опций предлагает поставить также и npn.

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

    node -v npm

    (npm - это менеджер пакетов для JavaScript и самый большой реестр программного обеспечения https://www.npmjs.com/)

    Если не поставили вместе с NodeJS, то скачать по ссылке https://nodejs.org/en/download/ и поставить дополнительно.

    Некоторые команды

    npm -v

    проверить версию

    p> npm list strong>

    получить перечень локально установленны пакетов

    npm list -g

    список глобально установленных пакетов

    Angular CLI

    Наиболее популярный инструмент для управления пректами Angular.

    https://cli.angular.io/

    На github:

    https://github.com/angular/angular-cli

    установить cli

    npm install -g @angular/cli

    удалить cli

    npm uninstall -g angular-cli

    npm cache clean

    npm cache clean --force

    проверить установленную версию

    ng --version

    Редактор кода

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

    Visual Studio Code

    Notepad++

    Новый проект

    Запустить консоль NodeJS

    Перейти в папку с проектами Angular и запустить создание нового - project1 командой:

    ng new project1

    Перейти в папку созданного проекта

    cd project1

    CLI автоматически создаёт начальную структуру папок и файлов проекта.

    В папке ./src/app находятся, в частности:

    • app.component.ts - первый Angular - компонент, корневой, он называется app-root
    • app.module.ts - исполняемый модуль
    • app.component.css - стили
    • app.component.html - шаблон HTML для вывода в окно браузера

    Запустить проект

    ng serve

    или, указав другой порт и директиву открыть сразу проект в браузере: 

    ng serve --port 3000 --open

    Открыть запущенный проект в браузере

    http://localhost:4200 (или, соответственно http://localhost:3000)

    Редактировать проект

    Файлы запущенного проекта можно редактировать в любом редакторе кодов (например: Notepad++). При сохранении изменений проект автоматически перезапускается и в окне браузера сразу отражаются изменения.

    Отредактируем файл шаблона корневого компонента нашего приложения (), заменим его на:

    <h1> Название проекта: {{ title }}! </h1> <h2> Наш первый проект с Angular 5 </h2>

    Сгенерировать проект для публикации

    ng build --prod

    Проект для публикации (HTML, CSS, JavaScript) по умолчанию создастся в папке dist

    Все команды ng (Angular):

    Wiki https://github.com/angular/angular-cli/wiki

    PDF https://cli.angular.io/reference.pdf

    Angular компоненты (Components)

    Основной составляющий блок проекта на Angular - компонент.

    Создаём новый компонент (Angular component)

    Создаём компонент с именем comp1 в паке существующего проекта

    ng generate component comp1

    По завершении команды в папке app проекта добавилась папка нашего нового компонента - src/app/comp1.

    В файл app.module.ts добавилась строки описания нашего компонента: 

    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { Comp1Component } from './comp1/comp1.component'; @NgModule({ declarations: [ AppComponent, Comp1Component ], imports: [ BrowserModule ], providers: [], bootstrap: [ AppComponent] }) export class AppModule { }

    По-умолчанию создался компонент с селектором: app-comp1. Используя этот селектор можно добавить новый компонент в наше приложение. Для этого в файле с шаблоном нашего приложения (app.component.html) добавим строки:

    Он примет вид:

    <div style="text-align:center"> <h1> Название проекта: {{ title }}! </h1> <H1> Наш первый проект с Angular 5 </H1> <app-comp1> </app-comp1>


    Шаблон нового компонента находится в его файле с именем:

    src\app\comp1\comp1.component.html

    Отредактируем его, вставив строки:

    <h2> Первый компонент! </h2>

    Запустить наше приложение с новым компонентом, проверить работу:

    ng serve


    Angular 5 web-start.top

    Структура компонента Angular

    Компонет состоит из 3-х секций:

    1. директива - import
    2. декоратор
    3. директива export

    Импортируем из библиотеки '@angular/core' необходимые модули:

    import { Component, OnInit } from '@angular/core';

    Некоторые компоненты могут содержать множество директив import

    Декоратор компонента позволяет менять некоторые свойства нашего компонента (метаданные).

    Приведённый ниже декоратор задаёт свойства компонента (selector, templateUrl, styleUrls).

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

    selector - имя тега, использование которого инициирует наш компонент.

    templateUrl - шаблон HTML (может быть именем файла или встроенным набором HTML - свойство template )

    styleUrls - листы стилей (список файлов или встроенный - inline набор описаний стилей - свойство styles )

    В директиве export описаны свойства и методы класса-компонента, которые будут доступны другим компонентам приложения

    export class Comp1Component implements OnInit { public title ; constructor() { } ngOnInit() { this.title = 'Первый компонент запущен.' } }  


    Файл компонента - программа на Typescript :

    import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-comp1', templateUrl: './comp1.component.html', styleUrls: ['./comp1.component.css'] }) export class Comp1Component implements OnInit { public title ; constructor() { } ngOnInit() { this.title = 'Первый компонент запущен.' } }


    Angular 5 web-start.top

    Шаблоны Angular (Angular templates)

    Создадим новый проект (app-my-first-component) и посмотрим, как работать с шаблонами и стилями.

    Встроенные и внешние шаблоны (inline & external Angular templates)

    Параметры templateUrl и styleUrls , заданные в декораторе, определяют путь к внешним файлам, содержащим шаблон.

    Параметры template и style описывают встроенный шаблон (соответственно HTML и CSS ). Если необходимо использовать несколько строк для inline описаний, то вместо ограничителя строки - кавычка (') используется ограничитель строки - backtick (`) 

    Например

    template: '<h1>Inline HTML template</h1>',

    Или:

    import { Component} from '@angular/core'; @Component({ selector: 'app-my-first-component', template: ` <h1>Inline HTML template</h1> <hr> <h2> Встроенный HTML шаблон из трёх строк</h2> `, styles: ['h2 {color:red;}'] })

    При использовании встроенного многострочного шаблона ограничитель строки - кавычка (') нужно заменить на другой символ - ` (backtick symbol слева сверху на клавиатуре)

    Angular 5 web-start.top

    Интерполяция строк (использование динамических данных)

    (Angular string interpolation)

    Свойства , заданные в описании класса компонента, могут быть вставлены в шаблон с использованием синтаксиса:


    {{ИМЯ_СВОЙСТВА}}


    Например, если в компоненте описано свойство title :

    export class FirstComponent{ title = 'Первый тест'; }

    То в шаблоне может быть использовано {{title}}:

    template : '<H1>{{title}}</H1>',

    Можно вставлять в шаблон свойства объекта (пример со встроенными - inline - стилями и шаблоном)

    import { Component} from '@angular/core'; @Component({ selector: 'app-my-first-component', template: ` <h1> Студент </h1> <h2> Имя: {{student.name}}</h2> <h2> Возраст: {{student.age}}</h2> <h2> Курс: {{student.course}}</h2>`, styles: ['h2 {color:red;}'] }) export class MyFirstComponent { // Описание класса student = { name: "Иванов", age: 22, course: "Angular" } }



     Подробнее - Angular components


    Структурные директивы (Angular Structural Directives)

    Структурные директивы отвечают за компоновку HTML - макета. Они формируют или изменяют структуру DOM, как правило, путем добавления, удаления или изменения элементов. 

    Директива ngFor

    Можно в объекте описать массив данных, тогда в шаблон можно вставлять элементы массива или, например, с помощью оператора ngFor пробегать по всему массиву в цикле.

    import { Component} from '@angular/core'; @Component({ selector: 'app-my-first-component', template: ` <h1> Студент </h1> <h2> Имя: {{students[0].name}}</h2> <h2> Возраст: {{students[0].age}}</h2> <h2> Курс: {{students[0].course}}</h2> `, styles: ['h2 {color:red;}'] }) export class MyFirstComponent { students = [ { name: "Иванов", age: 21, course: "'Angular 2'" }, { name: "Петров", age: 22, course: "'Angular 4'" }, { name: "Сидоров", age: 23, course: "'Angular 5'" }, ] }


    Angular 5 web-start.top

    Проход по массиву в цикле

    import { Component} from '@angular/core'; @Component({ selector: 'app-my-first-component', template: ` <h1> Студенты </h1> <ul> <li *ngFor="let item of students; let i = index"> {{i}} <b>{{students[i].name}}</b> {{students[i].age}} {{students[i].course}} </li> </ul> `, styles: ['h2 {color:red;}'] }) export class MyFirstComponent { students = [ { name: "Иванов", age: 21, course: "'Angular 2'" }, { name: "Петров", age: 22, course: "'Angular 4'" }, { name: "Сидоров", age: 23, course: "'Angular 5'" }, ] }



    Подробнее - Angular directives


  • Angular 6 component interaction

    Обмен данными между родительским и дочерним компонентом (Angular component interaction)

    @input


    @output


    Decorators


    Event emitter


    C помощью декораторов @Input, @Output и API EventEmitter можно обеспечить обмен данными между родительскими и дочерними компонентами.


    Декоратор @Input

    Дочерний компонент с помощью декоратора input может получать данные от родительского, а  с помощью декоратора output - посылать.


    Для получения данных от родительского компонента дочерним:

    - в дочернем компоненте создаём свойство, в которое данные будем получать, декорируем его с помощью декоратора @Input

    - в родительском компоненте создаём public - свойство, которое будем передавать

    - при вызове дочернего компонента через созданное нами свойство привязываем к свойству дочернего компонента данные из родительского.


    Родительский компонент:

    import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; public string1 = <string> 'Data from parent...'; }


    Шаблон родительского компонента - вызов дочернего:

    <h1>This is parent component:</h1> <hr> <app-inoutcomponent [inFromParent]='string1'></app-inoutcomponent>


    Дочерний компонент

    import { Component, OnInit, Input } from '@angular/core'; @Component({ selector: 'app-inoutcomponent', templateUrl: './inoutcomponent.component.html', styleUrls: ['./inoutcomponent.component.css'] }) export class InoutcomponentComponent implements OnInit { @Input() public inFromParent: string; constructor() { } ngOnInit() { } }


    Шаблон дочернего компонента 

    <h1>This is child component:</h1> <h3>{{inFromParent}}</h3>


    Результат



    Добавим в родительский компонент метод, который меняет это свойство. Привяжем его к событию click кнопки.

    import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; public string1 = <string> 'Data from parent...'; changeChildData() { this.string1 += ' Changed '; } }


    При каждом нажатии к строке будем приписывать текст: this.string1 += ' Changed ';


    Результат после 2-х кликов:



    Декоратор @Output и  EventEmitter 

    Передача данных от дочернего компонента к родительскому.

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


    У дочернего компонета создаём своё событие - outToParent (объект класса EventEmitter ), декорируя его декоратором @Output.

    Создадим в дочернем компоненте метод - sendToParent() . Его задача: передать событие родительскому объекту (метод emit()).

    Передано это событие будет через Angular объект - $event.

    Таким образом, созданное нами событие - outToParent произойдёт в тот момент, когда сработает sendToParent()и его (события) содержимое можно будет получить из $event.


    Дочерний компонент

    import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-inoutcomponent', templateUrl: './inoutcomponent.component.html', styleUrls: ['./inoutcomponent.component.css'] }) export class InoutcomponentComponent implements OnInit { @Input() public inFromParent: string; @Output() public outToParent = new EventEmitter(); constructor() { } ngOnInit() { } sendToParent() { this.outToParent.emit('Child sent this message to parent...'); } }


    Привяжем обработчик событий - click к кнопке в шаблоне дочернего компонента и по этому клику вызовем метод sentToParent, который в свою очередь включит событие outToParent:

    Шаблон дочернего компонента

    <h1>This is child component:</h1> <h3>{{inFromParent}}</h3> <br> <button (click)='sendToParent()'>Click to send data!</button> <br>


    Стиль дочернего компонента

    * {
    color: green;
    }



    Родительский компонент получает данные события методом, который мы в нём создали - getNessage()

    import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; public string1 = <string> 'Data from parent...'; public string2 = ''; changeChildData() { this.string1 += ' Changed '; } receiveFromChild(evnt){ this.string2 = evnt; } }



    Шаблон родительского компонента (outToParent - новое событие, которое мы создали)

    <h1>This is parent component:</h1> <button (click)='changeChildData()'>Change child data </button> <hr> <strong>{{string2}}</strong> <app-inoutcomponent (outToParent)='receiveFromChild($event)' [inFromParent]='string1'></app-inoutcomponent>


    До клика



    После клика



    Декоратор @Component, свойства - inputs, outputs


    Вместо использования декораторов свойств - @Input и @Outpur можно использовать свойства декоратора класса - @Component (inputs, outputs).


    import { Component, OnInit, EventEmitter } from '@angular/core'; // import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-inoutcomponent', templateUrl: './inoutcomponent.component.html', styleUrls: ['./inoutcomponent.component.css'], inputs: ['inFromParent'], outputs:['outToParent'] }) export class InoutcomponentComponent implements OnInit { // @Input() public inFromParent: string; inFromParent: string; // @Output() public outToParent = new EventEmitter(); outToParent = new EventEmitter(); constructor() { } ngOnInit() { } sendToParent() { this.outToParent.emit('Child sent this message to parent...'); } }


    Но Angular рекомендуют использовать @Input и @Output 

    https://angular.io/guide/styleguide#style-05-12)%20(use-output-property-decorator

    style 05-12






  • Angular 6 directives (part2)

    Встроенные директивы Angular (Angular built-in directives)

    Примеры


    app.modules.ts


    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { StudentsComponent } from './students/students.component'; @NgModule({ declarations: [ AppComponent, StudentsComponent ], imports: [ BrowserModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }



    StudentsComponent

    import { Component, OnInit } from '@angular/core'; import { StudentsInterface } from '../students-interface'; @Component({ selector: 'app-students', templateUrl: './students.component.html', styleUrls: ['./students.component.css'] }) export class StudentsComponent implements OnInit { students: StudentsInterface[]; constructor() { } ngOnInit() { this.students = [ { name: 'Anna', id: 1234567, age: 22, course: 'Angular' }, { name: 'Haim', id: 987654, age: 18, course: 'WEB' }, { name: 'Yossy', id: 456687456, age: 44, course: 'C' }, { name: 'Vasily', id: 1234567, age: 22, course: 'PHP' }, { name: 'Bob', id: 14312554, age: 37, course: 'Photoshop' }, { name: 'Bob', id: 657856784567, age: 37, course: 'WEB' }, ]; } }



    StudentsInterface

    export interface StudentsInterface { name: string; id?: number; age: number; course: string; }



    students.component.html


    <h1>Students</h1> <hr> <h2>Names -all</h2> <ng-container *ngFor='let student of students; let n = index;'> <p>{{n}} : {{student.name}}</p> </ng-container> <hr> <h2>WEB students</h2> <ul *ngFor='let stud of students'> <li *ngIf='stud.course === "WEB"'>{{stud.course}} -> {{stud.name}}</li> </ul> <hr> <h2>Colored list</h2> <ul *ngFor='let studnt of students'> <ng-container [ngSwitch]='studnt.course'> <div style='color:red' *ngSwitchCase='"WEB"'>Name: {{studnt.name}}, Age: {{studnt.age}}, Course: {{studnt.course}}, Id: {{studnt.id}}</div> <div style='color:green' *ngSwitchCase='"PHP"'>Name: {{studnt.name}}, Age: {{studnt.age}}, Course: {{studnt.course}}, Id: {{studnt.id}}</div> <div style='color:blue' *ngSwitchCase='"C"'>Name: {{studnt.name}}, Age: {{studnt.age}}, Course: {{studnt.course}}, Id: {{studnt.id}}</div> <div style='color:lightgray' *ngSwitchDefault>Name: {{studnt.name}}, Age: {{studnt.age}}, Course: {{studnt.course}}, Id: {{studnt.id}}</div> </ng-container> </ul>





  • Angular 6 directives (part3)


    Примеры Angular директив

    (Angular built in directives)



    <H1>Students</H1> <table> <tr> <th>N</th> <th>Name</th> <th>Age</th> <th>Course</th> </tr> <tr *ngFor='let student of students; let n = index'> <td>{{n+1}}</td> <td>Name: {{student['Name']}}</td> <td>Age: {{student['Age']}}</td> <td>Course: {{student['Course']}}</td> </tr> </table> <hr> <h1>WEB students</h1> <table> <tr> <th>N</th> <th>Name</th> <th>Age</th> <th>Course</th> </tr> <ng-container *ngFor='let item of students; let n = index'> <tr *ngIf="item['Course'] == 'WEB'"> <td>{{n+1}}</td> <td>Name: {{item['Name']}}</td> <td>Age: {{item['Age']}}</td> <td>Course: {{item['Course']}}</td> </tr> </ng-container> </table> <hr> <ng-container *ngFor='let student of students'> <div *ngIf="student['Age'] >= 20; then adult; else child">this is ignored</div> <ng-template #adult>Adult: {{student['Name'] + ' Age:' + student['Age'] }}<br></ng-template> <ng-template #child>Child: {{student['Name'] + ' Age:' + student['Age'] }}<br></ng-template> </ng-container> <hr> <ng-container *ngFor='let student of students; let n = index'> {{n + 1}} <ng-container [ngSwitch]='student["Course"]'> <div *ngSwitchCase='"WEB"' style='color:red'> WEB : {{student['Name']}}<br> </div> <div *ngSwitchCase='"PHP"' style='color:green'> PHP : {{student['Name']}}<br> </div> <div *ngSwitchCase='"C++"' style='color:blue'> C++ : {{student['Name']}}<br> </div> </ng-container> </ng-container>



    import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-students', templateUrl: './students.component.html', styleUrls: ['./students.component.css'] }) export class StudentsComponent implements OnInit { students = []; constructor() { } ngOnInit() { this.students = [ {'Name': 'Ivan', 'Age': '25', 'Course': 'WEB'}, {'Name': 'Haim', 'Age': '20', 'Course': 'PHP'}, {'Name': 'Kate', 'Age': '19', 'Course': 'C++'}, {'Name': 'Ivan', 'Age': '25', 'Course': 'WEB'}, {'Name': 'Haim', 'Age': '30', 'Course': 'PHP'}, {'Name': 'Kate', 'Age': '19', 'Course': 'C++'}, {'Name': 'Ivan', 'Age': '16', 'Course': 'WEB'}, {'Name': 'Haim', 'Age': '33', 'Course': 'PHP'}, {'Name': 'Kate', 'Age': '10', 'Course': 'C++'} ]; console.log(this.students); } }






  • Angular 6 HTTP запросы (part2)

    Структура проекта

    my-post.service.ts - сервис, который обменивается данными с сервером

    my-post-interface.ts - структура данных 

    my-post.component.ts - компонент, который этот сервис использует


    Сервис (Injectable )

    import { Injectable, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { MyPostInterface } from './my-post-interface'; @Injectable({ providedIn: 'root' }) export class MyPostService { myData = []; myUrl = 'http://angularhttp/myAngularPostV4.php'; constructor(private myHttp: HttpClient) { } sendRequest() { this.myHttp.post(this.myUrl, {observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Request N: ' , this.myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return this.myData; } }


    Интерфейс

    export interface MyDataInterface { id: number; name: string; title: string; msg: string; }


    Компонент

    import { Component, OnInit } from '@angular/core'; import { MyPostService } from '../my-post.service'; @Component({ selector: 'app-my-post', templateUrl: './my-post.component.html', styleUrls: ['./my-post.component.css'] }) export class MyPostComponent implements OnInit { myDataArray = []; constructor(private connectToServer: MyPostService) { } ngOnInit() { } getData() { this.myDataArray = this.connectToServer.sendRequest(); } }


    app-module

    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HttpClientModule } from '@angular/common/http' import { MyPostService } from './my-post.service'; import { MyPostComponent } from './my-post/my-post.component'; @NgModule({ declarations: [ AppComponent, MyPostComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [MyPostService], bootstrap: [AppComponent] }) export class AppModule { }


    Шаблон компонента


    import { Component, OnInit } from '@angular/core'; import { MyPostService } from '../my-post.service'; @Component({ selector: 'app-my-post', templateUrl: './my-post.component.html', styleUrls: ['./my-post.component.css'] }) export class MyPostComponent implements OnInit { myDataArray = []; constructor(private connectToServer: MyPostService) { } ngOnInit() { } getData() { this.myDataArray = this.connectToServer.sendRequest(); } }


    Стили компонента


    TABLE { border-collapse: collapse; width: 100%; } TABLE TH { color: red; font-size: 1.2rem; } TABLE TH, TABLE TD { border: 1px solid lightgray; padding: 5px; } .testbutton { color: #14396A; text-shadow: 1px 1px 0px #7CACDE; box-shadow: 1px 1px 1px #BEE2F9; padding: 10px 25px; border-radius: 10px; border: 2px solid #3866A3; background: #63B8EE; background: linear-gradient(to bottom, #63B8EE, #468CCF); } .testbutton:hover { color: #F00; background: #468CCF; background: linear-gradient(to bottom, #468CCF, #63B8EE); }



    Результат - до запроса к серверу



    После запроса


    Поиск данных на сервере

    Пошлём серверу имя пользователя (Anna), чтобы получить полную информации о нём

    Сервис

    import { Injectable, OnInit } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { MyPostInterface } from './my-post-interface'; @Injectable({ providedIn: 'root' }) export class MyPostService { constructor(private myHttp: HttpClient) { } sendRequest() { const myUrl = 'http://angularhttp/myAngularPostV4.php'; let myData = []; this.myHttp.post(myUrl, {observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Server requested: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } getUserData() { const myUrl = 'http://angularhttp/myAngularPostV5.php'; const myHeaders = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); let myData = []; this.myHttp.post(myUrl, {name : 'Anna'}, {headers: myHeaders, observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Server requested: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } }



    Компонент

    import { Component, OnInit } from '@angular/core'; import { MyPostService } from '../my-post.service'; @Component({ selector: 'app-my-post', templateUrl: './my-post.component.html', styleUrls: ['./my-post.component.css'] }) export class MyPostComponent implements OnInit { allUsers = []; foundUser = []; constructor(private connectToServer: MyPostService) { } ngOnInit() { } getAllData() { this.allUsers = this.connectToServer.sendRequest(); } getUserData() { this.foundUser = this.connectToServer.getUserData(); } }



    Шаблон компонента

    <h1>POST test component</h1> <hr> <button class='testbutton' (click)='getAllData()'>Request all data from server</button> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of allUsers[0]'> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </tr> </table> <hr> <button class='testbutton' (click)='getUserData()'>Get user data</button> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of foundUser[0]'> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </tr> </table> <hr>



    app.module.ts
    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HttpClientModule } from '@angular/common/http' import { MyPostService } from './my-post.service'; import { MyPostComponent } from './my-post/my-post.component'; @NgModule({ declarations: [ AppComponent, MyPostComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [MyPostService], bootstrap: [AppComponent] }) export class AppModule { }


    Результат 



    Server side

    Используется  Apache на локальном компьютере. Адрес сервера: http://angularhttp/ Запросы обрабатывает PHP - программа myAngularPostV4.php.

    Формат данных и способ их интерпретации зависит от HTTP заголовков (руфвукы), которые выставлены и в Angular 

    const myHeaders = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

    и 

    {observe: 'body', responseType: 'json'}

    и в PHP

    header('Content-type: application/x-www-form-urlencoded; charset=UTF-8');

    PHP должен интерпретировать то, что посылает Angular через метод subscribe() объекта Observable. Если при посылке меняем формат, то и в PHP его надо менять.


    Программа PHP получает запрос от Angular и в ответ посылает строку с данными (в формате JSON) - myAngularPostV4.php

    <?php header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/json'); header("Access-Control-Allow-Headers: *"); header('Access-Control-Allow-Methods: POST'); $outstr = '[{ "id" : 1000, "name" : "Anna", "title" : "Manager", "msg" : "Sales department" }, { "id" : 1001, "name" : "Bob", "title" : "Technician", "msg" : "Server support team" }, { "id" : 1002, "name" : "Alex", "title" : "WEB developer", "msg" : "Corporate web development team" } ]'; echo($outstr); ?>



    Эхо - тест (получили запрос - отдали то, что получили) - myAngularPostV3.php

    <?php header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/json'); header("Access-Control-Allow-Headers: *"); header('Access-Control-Allow-Methods: POST'); $_POST = json_decode(file_get_contents('php://input'), true); $id = $_POST['id']; $name = $_POST['name']; $title = $_POST['title']; $msg = $_POST['msg']; $outstr = '[{ '; $outstr .= '"id": "'; $outstr .= $id; $outstr .= '", "name": "'; $outstr .= $name; $outstr .= '", "title": "'; $outstr .= $title; $outstr .= '", "msg":"'; $outstr .= $msg; $outstr .= '" }]'; echo($outstr); ?>


    Найти пользователя по имени (myAngularPostV5.php)


    <?php //if($_SERVER['HTTP_ORIGIN'] == "http://localhost:4200") header('Access-Control-Allow-Origin: http://localhost:4200'); header("Access-Control-Allow-Headers: *"); header('Content-type: application/x-www-form-urlencoded; charset=UTF-8'); header('Access-Control-Allow-Methods: POST'); $data = json_decode(file_get_contents("php://input")); $name = $data->name; $users = Array(); $users[] = Array ("id"=> 1111, "name"=> "Bob", "title"=> "Manager", "msg"=> "CEO"); $users[] = Array("id"=> 222, "name"=> "Nik", "title"=> "Sales", "msg"=> "Corporate sales dept"); $users[] = Array("id"=> 4444, "name"=> "Anna", "title"=> "Technician", "msg"=> "Network support team"); $users[] = Array("id"=> 5, "name"=> "Haim", "title"=> "HR", "msg"=> "Human resource"); $users[] = Array("id"=> 76, "name"=> "Ronald", "title"=> "CA", "msg"=> "Accounting") ; foreach($users as $key => $user){ if($user['name'] == $name){ $outstr = '[{ '; $outstr .= '"id": "'; $outstr .= $user['id']; $outstr .= '", "name": "'; $outstr .= $user['name']; $outstr .= '", "title": "'; $outstr .= $user['title']; $outstr .= '", "msg": "'; $outstr .= $user['msg']; $outstr .= '" }]'; } } error_log( $outstr); echo($outstr); ?>



    Асинхронный поиск по мере ввода имени

    В этом примере в окне браузера (в поле INPUT ) вводится имя сотрудника. По мере ввода (событие - keyup ) имя пересылается по POST серверу и проверяется PHP программой на сервере. Если PHP не нашёл сотрудника по имени (ищем в массиве сотрудников), он выдаёт сообщение (также в формате JSON)  

    Сервис


    import { Injectable, OnInit } from '@angular/core'; import { HttpClient, HttpHeaders} from '@angular/common/http'; import { MyPostInterface } from './my-post-interface'; import { PostOptionsInterface } from './post-options-interface'; @Injectable({ providedIn: 'root' }) export class MyPostService { constructor(private myHttp: HttpClient) { } sendRequest() { const myUrl = 'http://angularhttp/myAngularPostV4.php'; let myData = []; this.myHttp.post(myUrl, {observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Server request: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } getSingleUser() { const myUrl = 'http://angularhttp/myAngularPostV5.php'; const myHeaders = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); let myData = []; this.myHttp.post(myUrl, {name : 'Anna'}, {headers: myHeaders, observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Server request: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } findUser(userName){ const httpHdr = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); const postUrl = 'http://angularhttp/myAngularPostV6.php'; const postBody = {name : userName}; let myData = []; this.myHttp.post(postUrl, postBody, { headers: httpHdr, observe: 'body', responseType: 'json' }) .subscribe({ next: data => console.log('Server requested: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } }


    Компонент


    import { Component, OnInit } from '@angular/core'; import { MyPostService } from '../my-post.service'; @Component({ selector: 'app-my-post', templateUrl: './my-post.component.html', styleUrls: ['./my-post.component.css'] }) export class MyPostComponent implements OnInit { allUsers = []; singleUser = []; foundUser = []; constructor(private connectToServer: MyPostService) { } ngOnInit() { } getAllData() { this.allUsers = this.connectToServer.sendRequest(); } getSingleUser() { this.singleUser = this.connectToServer.getSingleUser(); } findUser(evnt){ console.log(evnt.target.value); this.foundUser = this.connectToServer.findUser(evnt.target.value); } removeHint(evnt){ evnt.target.value = ''; evnt.target.select(); } }


    HTML - шаблон компонента


    <h1>POST test component</h1> <hr> <button class='testbutton' (click)='getAllData()'>Request all users data from server</button> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of allUsers[0]'> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </tr> </table> <hr> <button class='testbutton' (click)='getSingleUser()'>Get data of user: Anna</button> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of singleUser[0]'> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </tr> </table> <hr> <input type='text' (keyup)='findUser($event)' (mouseenter)='removeHint($event); ' name='' value='Type case-sensitive user name here...'> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of foundUser[0]'> <td colspan=4 *ngIf="str['id'] == 0; else found">{{str['name']}} {{str['title']}} {{str['msg']}}</td> <ng-template #found> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </ng-template> </tr> </table> <hr>



    CSS - стили компонента



    BUTTON, INPUT { margin: 10px 0px; } INPUT { width: 98.5%; padding: 5px; background-color: #EFEFEF; } TABLE { border-collapse: collapse; width: 100%; } TABLE TH { color: red; font-size: 1.2rem; } TABLE TH, TABLE TD { border: 1px solid lightgray; padding: 5px; } .testbutton { color: #FFF; text-shadow: 1px 1px 0px #7CACDE; box-shadow: 1px 1px 1px #BEE2F9; padding: 10px 25px; border-radius: 10px; border: 2px solid #3866A3; background: #63B8EE; background: linear-gradient(to bottom, #63B8EE, #468CCF); } .testbutton:hover { color: #F00; background: #468CCF; background: linear-gradient(to bottom, #468CCF, #63B8EE); }



    app.module.ts


    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HttpClientModule } from '@angular/common/http' import { MyPostService } from './my-post.service'; import { MyPostComponent } from './my-post/my-post.component'; @NgModule({ declarations: [ AppComponent, MyPostComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [MyPostService], bootstrap: [AppComponent] }) export class AppModule { }




    Интерфес - структура данных: my-post-interface.ts

    export interface MyPostInterface { id: number; name: string; title: string; msg: string; }



    Server side: PHP - ищет сотрудника по имени (http://angularhttp/myAngularPostV6.php)

    <?php // if($_SERVER['HTTP_ORIGIN'] == "http://localhost:4200") header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/x-www-form-urlencoded; charset=UTF-8'); header('Access-Control-Allow-Methods: POST'); $data = json_decode(file_get_contents("php://input")); $name = $data->name; $users = []; $users[] = ["id"=> 1111, "name"=> "Bob", "title"=> "Manager", "msg"=> "CEO"]; $users[] = ["id"=> 222, "name"=> "Nik", "title"=> "Sales", "msg"=> "Corporate sales dept"]; $users[] = ["id"=> 4444, "name"=> "Anna", "title"=> "Technician", "msg"=> "Network support team"]; $users[] = ["id"=> 5, "name"=> "Haim", "title"=> "HR", "msg"=> "Human resource"]; $users[] = ["id"=> 76, "name"=> "Ronald", "title"=> "CA", "msg"=> "Accounting"] ; $outstr = '[{ "id":"00000", "name":"User", "title":"not", "msg":"found" }]'; foreach($users as $key => $user){ if($user['name'] == $name){ $outstr = '[{ '; $outstr .= '"id": '; $outstr .= $user['id']; $outstr .= ', "name": "'; $outstr .= $user['name']; $outstr .= '", "title": "'; $outstr .= $user['title']; $outstr .= '", "msg": "'; $outstr .= $user['msg']; $outstr .= '" }]'; } } error_log($name); error_log( $outstr); echo($outstr); ?>


    Server side: PHP выводит всех сотрудников ((http://angularhttp/myAngularPostV4.php))


    <?php header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/x-www-form-urlencoded; charset=UTF-8'); header("Access-Control-Allow-Headers: *"); header('Access-Control-Allow-Methods: POST'); $users = []; $users[] = ["id"=> 1111, "name"=> "Bob", "title"=> "Manager", "msg"=> "CEO"]; $users[] = ["id"=> 222, "name"=> "Nik", "title"=> "Sales", "msg"=> "Corporate sales dept"]; $users[] = ["id"=> 4444, "name"=> "Anna", "title"=> "Technician", "msg"=> "Network support team"]; $users[] = ["id"=> 5, "name"=> "Haim", "title"=> "HR", "msg"=> "Human resource"]; $users[] = ["id"=> 76, "name"=> "Ronald", "title"=> "CA", "msg"=> "Accounting"] ; $outstr = json_encode($users, JSON_PRETTY_PRINT); echo($outstr); ?>


    Результат - вывели всех сотрудников




    Результат при начале набора в поле ввода




    Результат - нашлось имя



    PHP - error log (при каждом событии keyup PHP получает имя и пишет для отладки в error log полученное имя и строку для отправки в Angular ):

    [01-Jun-2018 15:43:53 UTC] R [01-Jun-2018 15:43:53 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:53 UTC] R [01-Jun-2018 15:43:53 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:54 UTC] Ron [01-Jun-2018 15:43:54 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:54 UTC] Ron [01-Jun-2018 15:43:54 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:54 UTC] Rona [01-Jun-2018 15:43:54 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:55 UTC] Ronal [01-Jun-2018 15:43:55 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:55 UTC] Ronald [01-Jun-2018 15:43:55 UTC] [{ "id": 76, "name": "Ronald", "title": "CA", "msg": "Accounting" }]









  • Angular 6 routing

    Angular - навигация по сайту (Angular routing)

    При помощи  Routing - модуля Angular позволяет организовать привычную навигацию по страничкам сайта:

    • если ввести в адресной строке браузера IRI нужной странички, то она откроется
    • если кликнуть по ссылке на нужную страничку сайта (меню сайта, другие внутренние ссылки) , то Angular откроет её в окне браузера
    • если пользоваться кнопками браузера НАЗАД, ВПЕРЁД, то мы будем перемещаться по истории посещённых страничек сайта.

    Сконфигурируем сайт, который будет состоять из: одной главной странички - home, страничек  About, Contacts и специальной странички, которая будет открываться в том случае, если посетитель сайта пытается перейти на несуществующую страничку - NotFound.

    Для этого:

    • генерируем новый проект с опцией - routing (ng new routing-test1 --routing) в дополнение к стандарной конфигурации проекта появится модуль app-routing.module.ts
    • генерируем модуль с названием header для меню сайта
    • генерируем модули для каждой нужной странички сайта (home, about, contacts, notFound)
    • проверяем наличие тега <base href="/"> в файле index.html, что обязательно для работы router 
    • конфигурируем router - модуль (ссылки и их привязки к компонентам)
    • конфигурируем шаблон сайта в модуле app.component

    Angular создаёт app-routing.module.ts

    import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }


    Генерируем нужные компоненты:

    ng g c not-found

    ng g c contacts

    ng g c home

    ng g c header

    ng g c about


    Все компоненты и Router импортированы в app.module - проверяем:

    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { HomeComponent } from './home/home.component'; import { HeaderComponent } from './header/header.component'; import { AboutComponent } from './about/about.component'; import { ContactsComponent } from './contacts/contacts.component'; import { NotFoundComponent } from './not-found/not-found.component'; @NgModule({ declarations: [ AppComponent, HomeComponent, HeaderComponent, AboutComponent, ContactsComponent, NotFoundComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }


    Конфигурируем - app.component

    import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { }


    Его HTML шаблон:

    <div id='wrapper'> <app-header></app-header> <router-outlet></router-outlet> </div>

    Через него определяем место (placeholder ) в окне браузера для компонента-меню (<app-header></app-header>)

    И для меняющихся компонентов-страничек ( <router-outlet></router-outlet>)

    Его стили:

    #wrapper { display: grid; grid-template-rows: auto auto; grid-template-columns: 1fr; }


    Компоненты страничек практически ничем, в нашем примере, друг от друга не отличаются (только текстом в HTML).

    import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-about', templateUrl: './about.component.html', styleUrls: ['./about.component.css'] }) export class AboutComponent implements OnInit { constructor() { } ngOnInit() { } }


    HTML

    <h1>About Us</h1>


    Компонент header - это меню сайта (он показывает кнопки меню и привязывает их к тем путям URI , которые мы задали в раутере, он появляется на каждой страничке):

    import { Component} from '@angular/core'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.css'] }) export class HeaderComponent { constructor() { } }


    HTML

    Директивы routerLink привязывают тег A к пути, который задан в модуле Router (константа routes )

    Директивы routerLinkActive присваивают элементам A класс стилей myActive в тот момент, когда ссылка активна.

    <div id='navBlock'> <a class='menuItem' routerLink='/home' routerLinkActive="myActive">Home</a> <a class='menuItem' routerLink='/about' routerLinkActive="myActive">About</a> <a class='menuItem' [routerLink]="['/contacts']" routerLinkActive="myActive">Contacts</a> </div>


    Стили

    Селектор  .menuItem[class*='myActive'] описывает стиль для активной ссылки. Класс myActive она получает по директиве routerLinkActive

    #navBlock { display: grid; grid-template-columns: repeat(3, minmax(auto, 300px)); grid-template-rows: 1fr; justify-content: center; align-content: space-between; border-bottom: 1px solid #aaa; } .menuItem { display: inline-block; text-align: center; padding: 10px 0px; margin: 10px; border: 1px solid #FFF; font-weight: bold; font-size: 1.2re; border-radius: 5px; box-shadow: 0px 2px 5px 1px rgba(100, 100, 100, 0.294); } .menuItem:hover { border-color: red; box-shadow: 0px 5px 10px 3px rgba(100, 100, 100, 0.294); } .menuItem[class*='myActive'] { color: red ! important; } .menuItem:visited { color: blue; } A { text-decoration: none; }




    Конфигурируем router.

    Конфигурируем в константе routes массив ссылок. Каждый элемент массива - путь и компонент, который к этому пути привязан.

    Элемент массива {path: '', redirectTo: '/home', pathMatch: 'full'} переадресовывает ссылки в корень сайта на страничку home

    Элемент массива {path: '**', component: NotFoundComponent} переадресовывает все странички, путь к которым не соответствует фильтрам пути в предыдущих элементах, на страничку NotFound 

    import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { AboutComponent } from './about/about.component'; import { ContactsComponent } from './contacts/contacts.component'; import { HomeComponent } from './home/home.component'; import { NotFoundComponent } from './not-found/not-found.component'; const routes: Routes = [ {path: '', redirectTo: '/home', pathMatch: 'full'}, {path: 'home', component: HomeComponent}, {path: 'about', component: AboutComponent}, {path: 'contacts', component: ContactsComponent}, {path: '**', component: NotFoundComponent} ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }



    Результат :