Liens
CLI
|
ng build
ng build --watch
ng serve --open
|
src
- main.ts is where the app starts running
- favicon.ico is the app's icon, just as you would find in any web site
- index.html is the app's top level HTML template
- style.css is the app's top level style sheet
- app
- app.component.ts app-root component, top-level Angular component in the app
- app.component.html component HTML template
- app.component.css component styles
- shared
- app.module.ts
- app.component.*
- component1
- module2
- shared
- module2.module.ts
- module2-routing.module.ts
- component2
- asset contains site images
- environments
gitignore
.gitignore
|
/dist
/tmp
/out-tsc
/bazel-out
/node_modules
npm-debug.log
yarn-error.log
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
.DS_Store
Thumbs.db
|
Astuces
Titre de l'onglet et favicon
src/index.html
|
<head>
<title>MonTitre</title>
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
String et substitution de variable
|
let myVar = 'texte';
let otherVar = `Contenu de myVar: ${myVar}`;
|
Object to string
|
console.log(JSON.stringify(myObject));
|
Timeout
|
setTimeout(() => {
}, 1000);
|
Propriété get
|
date: Date;
get formattedDate() {
return moment(this.date).format('MMMM YYYY');
}
|
Component
A component represents a view. generate
|
ng generate component '[component-name]'
|
- src/app
- [component-name]
- [component-name].component.css
- [component-name].component.html
- [component-name].component.ts
src/app/[component-name]/[component-name].component.ts
|
import { Component } from '@angular/core';
@Component({
selector: '[component-name]',
templateUrl: './[component-name].component.html',
template: `<div>Hello World</div>`,
styleUrls: ['./[component-name].component.css'],
styles: `div { background: pink; }`
})
export class ComponentName {
pageTitle: string = 'My Title';
persons: any[] = [
{ "Name": "Billy" },
{ "Name": "John" }
];
add() {
alert("add");
}
|
src/app/[component-name]/[component-name].component.html
|
<table *ngIf='persons && persons.length'>
<tr *ngFor='let person of persons'>
<td>{{ person.Name }}</td>
<a (click)="addItem()"><i class="fa fa-plus-circle"></i></a>
|
|
<body>
<[component-name]></[component-name]>
|
 |
À la création d'un nouveau component, penser à le déclarer dans le module. |
src/app/app.module.ts
|
import { ComponentName } from './[component-name]/[component-name].component';
@NgModule({
declarations: [
ComponentName
]
})
export class AppModule {}
|
Permet d'organiser les components par groupes. Un module par fonctionnalité.
|
ng generate module [module-name]
|
src/[module-name]/[module-name].module.ts
|
import { ComponentName } from './[component-name]/[component-name].component';
@NgModule({
declarations: [ ],
exports: [ ComponentName ]
})
export class ModuleName {}
|
Importing the feature module into the app module.
src/app/app.module.ts
|
import { ModuleName } from '../[module-name]/[module-name].module';
@NgModule({
imports: [ ModuleName ]
})
export class AppModule {}
|
src/app/app.component.html
|
<[component-name]></[component-name]>
|
src/app/child.component.ts
|
import { Component, Input } from '@angular/core';
export class ChildComponent {
@Input() name = '';
}
|
src/app/parent.component.html
|
<child [name]="childName"></child>
|
src/app/parent.component.ts
|
export class ParentComponent {
childName = 'Child Name';
}
|
ngFor
|
<ul>
<li *ngFor="let item of items; let i = index">
{{ item.name }} - {{ i }}
</li>
</ul>
|
items.component.html
|
<input type="text" [(ngModel)]="filterText" autofocus />
<div class="btn-group">
<input type="search" placeholder="Filtre" [(ngModel)]="filterText" autofocus>
<span id="filterclear" class="glyphicon glyphicon-remove-circle" (click)="clearFilter()"></span>
</div>
<ul>
<li *ngFor="let item of items | itemsFilter: filterText">
{{ item.name }}
</li>
</ul>
|
items.component.css
|
#filterclear {
position: absolute;
right: 5px;
top: 0;
bottom: 0;
height: 14px;
margin: auto;
font-size: 14px;
cursor: pointer;
}
|
items.component.ts
|
export class ItemsComponent {
filterText: string = "";
clearFilter() {
this.filterText = "";
}
}
|
items-filter.pipe.ts
|
import { Pipe, PipeTransform } from '@angular/core';
import { Item } from 'ClientApp/app/shared/item';
@Pipe({
name: 'itemsFilter',
pure: false
})
export class ItemsFilterPipe implements PipeTransform {
transform(items: Item[], filterText: string): Item[] {
if (!items || !filterText) {
return items;
}
filterText = filterText.toLowerCase();
return items.filter(item => item.name.toLowerCase().indexOf(filterText) !== -1);
}
}
|
app.module.ts
|
import { FormsModule } from '@angular/forms';
import { ItemsFilterPipe } from './components/items/items-filter.pipe';
@NgModule({
imports: [
FormsModule
],
declarations: [
ItemsFilterPipe
],
|
|
yarn add ngx-order-pipe
yarn add ngx-order-pipe@1.1.3
|
|
<ul>
<li *ngFor="let item of items | orderBy: 'name' : true">
{{ item.name }}
</li>
</ul>
|
app.module.ts
|
import { OrderModule } from 'ngx-order-pipe';
@NgModule({
imports: [
OrderModule
],
|
|
<div *ngIf="user">{{ user.name }}</div>
<div *ngIf="myObject.MyProperty === 10; else autreTexte">Texte</div>
<ng-template #autreTexte>
<div>Autre texte</div>
</ng-template>
|
Format
|
{{ 123.456 | number:'4.0-2':'en' }}
{{ 123.456 | number:'4.0-2':'fr' }}
|
|
{{ 0.05 | percent }}
|
|
{{ 1000 | currency:'EUR':'symbol':'1.2-2'}}
|
|
<div>{{ today | date: 'EEEE dd MMMM yyyy' }}</div>
|
app/app.module.ts
|
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
BrowserModule, HttpClientModule
],
|
item/item-list/item-list.component.ts
|
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Item } from '../item/item.module';
export class ItemListComponent implements OnInit {
public items: Item[] = [];
url: string = 'http://localhost:5235';
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get<Item[]>(`${this.url}/item`).subscribe({
next: result => this.items = result,
error: error => this.handleError(error)
});
this.http.post<Item>('/api/items', newItemToAdd).subscribe(newItemFromServer => ...);
this.http.delete('/api/items/42').subscribe();
this.http.put<Item>('/api/items', updatedItem).subscribe();
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(`Backend returned code ${error.status}, body was: ${error.error}`);
}
}
}
|
item/item.module.ts
|
export interface Item {
id: number;
name: string;
}
|
 |
Les objets récupérés sont de type Object et pas vraiment du type du cast.
Les attributs sont accessibles mais pas les méthodes. (lien) |
Projection d'un tableau dans un nouveau tableau.
|
import { map } from 'rxjs/operators';
let array1: number[] = [ 1, 2, 3 ];
let array2: string[] = array1.map((item, index, array) => {
return item.toString();
});
const numToString = map((val: number) => val.toString());
let array2: string[] = numToString(array1);
|
Bouton
item.component.html
|
<button (click)="myAction()">My Action</button>
|
item.component.ts
|
myAction() {
alert('action');
}
|
Affections conditionnelles de styles et classes CSS.
|
<div [ngStyle]="{'color':myVar > 0 ? 'green' : 'red' }"
[ngClass]="{'myCssClass':myVar > 0}">
</<div>
<div [style.color]="getColor(myVar)"
[class.myCssClass]="myVar > 0">
</<div>
|
Choix d'un template en fonction d'une variable:
|
<ng-container [ngTemplateOutlet]='templateChoice === 1 ? template1 : template2'
[ngTemplateOutletContext]="{arg1:arg1}">
</ng-container>
<ng-template #template1 let-arg1="arg1">
</ng-template>
|
Understanding Dynamic Scoping and TemplateRef
|
<div data-toggle="tooltip" data-placement="top" title="texte"></div>
<div data-toggle="tooltip" data-placement="top" [title]="myVar"></div>
|
app/app.module.ts
|
import { FormsModule } from '@angular/forms';
@NgModule({
imports: [
FormsModule
]
})
export class AppModule { }
|
Binding
myform.component.html
|
<form (submit)="onSubmit()" #myClassForm="ngForm">
<div class="form-group">
<label for="field1">Item name</label>
<input type="text" class="form-control" id="field1" name="field1" [(ngModel)]="model.field1" required />
<select [(ngModel)]="model.choice">
<option [value]="choice" *ngFor="let choice of choices">{{choice}}</option>
</select>
<input type="checkbox" id="checkbox1" name="checkbox1"
[(ngModel)]="model.checkbox1" [ngModelOptions]="{standalone: true}" (change)="onChange(model.checkbox1)">
</div>
<button type="submit" class="btn btn-success">Submit</button>
|
myform.component.ts
|
model = {
field1: "",
choice: "un"
};
choices = [ "un", "deux", "trois" ];
onSubmit() {
}
|
Si l'initialisation de model se fait dans ngOnInit, model est undefined dans le constructeur ainsi que dans le template.
|
{{ model?.name }}
<input [(ngModel)]="model && model.name" />
<input *ngIf='model' [(ngModel)]="model.name" />
|
|
model: Item = <Item>{};
|
Validation
myform.component.html
|
<form (submit)="onSubmit()" #myform="ngForm" novalidate>
<div class="form-group">
<input type="text" class="form-control" name="field1" [(ngModel)]="mydata.field1" #field1="ngModel" required />
<div class="text-danger" *ngIf="field1.touched && field1.invalid && field1.errors.required">Field1 is required</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-success" value="submit" [disabled]="myform.invalid" />
</div>
|
Autofocus
autofocus ne fonctionne pas nativement avec Angular.
Pour Angular 4.4.7, utiliser angular-autofocus-fix
app/app.shared.module.ts
|
import { AutofocusModule } from 'angular-autofocus-fix'
@NgModule({
imports: [
AutofocusModule
|
|
<input type="text" autofocus />
|
La date ne s'affiche pas correctement dans le champs input.
|
<input type="date" [ngModel] ="myDate | date:'yyyy-MM-dd'" (ngModelChange)="myDate = $event">
|
Événements
Clavier
|
<input type="text" (keydown.enter)="validate()">
|
|
<input type="text" (focus)="focusFunction()" (focusout)="validate()">
|
$event
|
<input type="text" (keydown.enter)="validate($event)">
|
|
validate(event: Event) {
let sourceElement = event.srcElement;
}
|
ngx-contextmenu: npm, git, demo, custom css
|
<div [contextMenu]="myContextMenu" [contextMenuSubject]="myObject">Texte</div>
<context-menu #myContextMenu>
<ng-template contextMenuItem (execute)="myFunction($event.item)">Context Menu 1</ng-template>
</context-menu>
|
|
import { ViewEncapsulation } from '@angular/core';
@Component({
encapsulation: ViewEncapsulation.None
myFunction(myObject: MyClass) { }
|
|
.dropdown-menu > li > a:hover {
text-decoration: none;
}
.dropdown-menu > li > a {
display: block;
padding: 0 10px;
color: white;
}
.dropdown-menu {
min-width: 0;
}
|
|
yarn add ngx-contextmenu @angular/cdk
|
app.module.ts
|
import { ContextMenuModule } from 'ngx-contextmenu';
@NgModule({
imports: [
ContextMenuModule.forRoot()
|
src/app/app.module.ts
|
import { LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';
@NgModule({
providers: [ {provide: LOCALE_ID, useValue: 'fr' } ]
})
export class AppModule {
constructor() {
registerLocaleData(localeFr, 'fr');
}
}
|
|
yarn add @ng-bootstrap/ng-bootstrap
|
app.module.ts
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
@NgModule({
imports: [ NgbModule ],
})
|
Bootstrap 4
|
yarn add bootstrap jquery popper.js
|
src/styles.css
|
@import url("~bootstrap/dist/css/bootstrap.min.css");
|
angular.json
|
"styles": [
"src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/bootstrap/dist/js/bootstrap.min.js"
]
|
Bootstrap 3
|
yarn add bootstrap3
|
angular.json
|
"styles": [
"src/styles.css",
"node_modules/bootstrap3/dist/css/bootstrap.min.css"
],
|
navmenu.component.html
|
<div class='main-nav'>
<div class='navbar navbar-inverse'>
<div class='navbar-header'>
<button type='button' class='navbar-toggle' data-toggle='collapse' data-target='.navbar-collapse'>
<span class='sr-only'>Toggle navigation</span>
<span class='icon-bar'></span>
<span class='icon-bar'></span>
<span class='icon-bar'></span>
</button>
<a class='navbar-brand' [routerLink]="['/home']">Home</a>
</div>
<div class='clearfix'></div>
<div class='navbar-collapse collapse'>
<ul class='nav navbar-nav'>
<li [routerLinkActive]="['link-active']">
<a [routerLink]="['/home']">
<span class='glyphicon glyphicon-home'></span> Home
</a>
</li>
<li [routerLinkActive]="['link-active']">
<a [routerLink]="['/menu1']">
<span class='glyphicon glyphicon-picture'></span> Menu1
</a>
</li>
</ul>
</div>
</div>
</div>
|
navmenu.component.css
|
li .glyphicon {
margin-right: 10px;
}
li.link-active a,
li.link-active a:hover,
li.link-active a:focus {
background-color: #4189C7;
color: white;
}
.main-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1;
}
@media (min-width: 768px) {
.main-nav {
height: 100%;
width: calc(16.66666667% - 20px);
}
.navbar {
border-radius: 0px;
border-width: 0px;
height: 100%;
}
.navbar-header {
float: none;
}
.navbar-collapse {
border-top: 1px solid #444;
padding: 0px;
}
.navbar ul {
float: none;
}
.navbar li {
float: none;
font-size: 15px;
margin: 6px;
}
.navbar li a {
padding: 10px 16px;
border-radius: 4px;
}
.navbar a {
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
|
Font Awesome
|
yarn add font-awesome
|
src/styles.css
|
@import url("~font-awesome/css/font-awesome.css");
|
angular.json
|
"styles": [
"src/styles.css",
"node_modules/font-awesome/css/font-awesome.min.css"
],
|
|
<i class="fa fa-edit"></i>
|
Global style
angular.json
|
{
"projects": {
"ClientApp": {
"architect": {
"build": {
"options": {
"styles": [
"src/styles.css",
"src/other-styles.css"
],
|
 |
La modification du fichier angular.json nécessite de recompiler le projet à la main. |
 |
Tous les styles sont concaténés au sein d'un seul fichier lors du build.
L'ordre des fichiers listés dans style n'est pas respecté lors de la concaténation (bug).
Ne lister que src/styles.css dans styles et utiliser @import dans src/styles.css.
L'ordre des @import est respecté lors de la concaténation. |
src/styles.css
|
@import url("src/other-styles.css");
|
Dark style
src/styles.css
|
html, body { height: 100%; }
|
src/app/app.component.css
|
.container-fluid {
background-color: #1f1f1f;
color: #cccccc;
min-height: 100%;
}
|
Animation
app.module.ts
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
imports: [
BrowserAnimationsModule
],
|
test/test.component.ts
|
import {style, state, animate, transition, trigger} from '@angular/animations';
@Component({
animations: [
trigger('fadeInOut', [
transition(':enter', [
style({ opacity: 0 }),
animate(500, style({ opacity: 1 }))
]),
transition(':leave', [
animate(500, style({ opacity: 0 }))
])
])
]
})
|
test/test.component.html
|
<div [@fadeInOut]>
|
Accèder aux éléments du DOM
|
let element = document.getElementById('myId');
(element as HTMLInputElement).value = "My Value";
document.querySelector(':focus').blur();
|
Versions
Version
|
Date
|
Commentaire
|
Angular 7 |
Octobre 2018 |
|
Angular 6 |
Mars 2018 |
|
Angular 5 |
Octobre 2017 |
|
Angular 4 |
Mars 2017 |
Pas de version 3.
|
Angular 2 |
Septembre 2016 |
TypeScript. Réécriture complète d'AngularJS.
|
AngularJS 1 |
Octobre 2010 |
Javascript
|
Langages
Langage
|
Description
|
EcmaScript 5 |
Sortie Décembre 2009.
|
EcmaScript 2015 / 6 |
Orienté objet. Sortie Juin 2015. fonctionnalités.
|
TypeScript |
Superset de JS. Stong types. Orienté objet.
|
Dart |
|
AngularJS vs Angular 2+
AngularJS
- Javascript
- Design basé sur MVC
Angular 2+
- Typescript
- Design basé sur Service/Controller
moment.js
|
yarn add moment ngx-moment
|
app.module.ts
|
import { MomentModule } from 'ngx-moment';
@NgModule({
imports: [
MomentModule
|
test/test.component.html
|
{{myDate | amDateFormat:'LL'}}
|
test/test.component.ts
|
import * as moment from 'moment';
const formattedDate = moment(myDate).format('LL');
|
jquery / jquery-ui
|
yarn add jquery jquery-ui-dist
|
angular.json
|
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/jquery-ui-dist/jquery-ui.min.js"
]
|
test/test.component.ts
|
import * as $ from 'jquery';
declare var $: any;
ngOnInit() {
$(document).ready(function() {
$('#id').MonthPicker({ Button: false });
});
|
angular-modal-gallery
Galerie d'images pour Angular 4,5,6.
|
yarn add @ks89/angular-modal-gallery hammerjs mousetrap
yarn add @types/hammerjs @types/mousetrap
yarn add rxjs-compat
|
app.module.ts
|
import 'hammerjs';
import 'mousetrap';
import { ModalGalleryModule } from '@ks89/angular-modal-gallery';
@NgModule({
imports: [
ModalGalleryModule.forRoot()
|
*.component.ts
|
import {
AccessibilityConfig,
Action,
AdvancedLayout,
ButtonEvent,
ButtonsConfig,
ButtonsStrategy,
ButtonType,
Description,
DescriptionStrategy,
DotsConfig,
GalleryService,
GridLayout,
Image,
ImageModalEvent,
LineLayout,
PlainGalleryConfig,
PlainGalleryStrategy,
PreviewConfig
} from '@ks89/angular-modal-gallery';
images: Image[] = [
new Image(0, { img: '../assets/images/1.png' }),
new Image(1, { img: '../assets/images/2.png' })
];
|
*.component.html
|
<ks-modal-gallery [id]="1" [modalImages]="images"></ks-modal-gallery>
<ks-modal-gallery *ngFor="let album of albums; let i = index"
[id]="i" [modalImages]="album.images"
</ks-modal-gallery>
|
Attributs
close outside |
[enableCloseOutside]="false"
|
infinite sliding but NO side previews |
[slideConfig]="{infinite: true, sidePreviews: {show: false}}"
|
bouton open / ouverture automatique
|
import { GalleryService } from '@ks89/angular-modal-gallery';
constructor(private galleryService: GalleryService) {}
openGallery() {
this.galleryService.openGallery(1, 0);
}
ngOnInit() {
this.delay(1).then(() => { this.galleryService.openGallery(1, 0); } );
}
delay(ms: number) {
return new Promise( resolve => setTimeout(resolve, ms) );
}
async ngOnInit() {
await this.delay(1);
this.galleryService.openGallery(1, 0);
}
|
|
<ks-modal-gallery [id]="1" [modalImages]="images"
[plainGalleryConfig]="plainGalleryRow"></ks-modal-gallery>
|
|
plainGalleryRow: PlainGalleryConfig = {
strategy: PlainGalleryStrategy.ROW,
layout: new LineLayout({ width: '80px', height: 'auto' }, { length: 1, wrap: true }, 'flex-start')
};
|
|
<ks-modal-gallery [buttonsConfig]="customButtonsConfig"
(buttonBeforeHook)="onButtonBeforeHook($event)"></ks-modal-gallery>
|
|
customButtonsConfig: ButtonsConfig = {
visible: true,
strategy: ButtonsStrategy.CUSTOM,
buttons: [
{
className: 'delete-image',
type: ButtonType.DELETE,
ariaLabel: 'Delete the current image',
title: 'Delete the current image',
fontSize: '20px'
},
{
className: 'close-image',
type: ButtonType.CLOSE,
ariaLabel: 'Close this modal image gallery',
title: 'Close this modal image gallery',
fontSize: '20px'
}
]
};
onButtonBeforeHook(event: ButtonEvent) {
console.log('onButtonBeforeHook ', event);
if (!event || !event.button) {
return;
}
if (event.button.type === ButtonType.DELETE) {
console.log('image to delete: id ' + event.image.id + 'path ' + event.image.modal.img);
this.http.delete('/api' + event.image.modal.img).subscribe();
this.images = this.images.filter((img: Image) => event.image && img.id !== event.image.id);
}
}
|
Preview Config (liste des images en bas)
|
<ks-modal-gallery [id]="1" [modalImages]="images"
[previewConfig]="{ number: 5 }">
</ks-modal-gallery>
|
Valeur par défaut: { visible: true, number: 3, arrows: true, clickable: true, size: { height: '50px', width: 'auto' }}
|
yarn add @swimlane/ngx-charts
|
app.module.ts
|
import { NgxChartsModule } from '@swimlane/ngx-charts';
imports: [
NgxChartsModule
]
|
test/test.component.html
|
<ngx-charts-bar-vertical-2d
[results]="barVertical2dData"
xAxis="true"
yAxis="true">
</ngx-charts-bar-vertical-2d>
<ngx-charts-line-chart
[results]="lineChartData"
xAxis="true"
yAxis="true"
showGridLines
roundDomains="true"
[xAxisTickFormatting]="xAxisTickFormatting">
</ngx-charts-line-chart>
|
test/test.component.ts
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
@Component({
encapsulation: ViewEncapsulation.None
})
barVertical2dData = [
{
'name': 'Groupe1',
'series': [
{ 'name': 'Texte1', 'value': 100 },
{ 'name': 'Texte2', 'value': 200 }
]
},
{
'name': 'Groupe2',
'series': [
{ 'name': 'Texte1', 'value': 300 },
{ 'name': 'Texte2', 'value': 400 }
]
},
];
lineChartData = [{
name: 'line1',
series: [
{ 'name': new Date(2018, 7, 1, 0, 0, 0, 0), 'value': 23.56 },
{ 'name': new Date(2018, 8, 1, 0, 0, 0, 0), 'value': 57.45 },
{ 'name': new Date(2018, 9, 1, 0, 0, 0, 0), 'value': 199.25 },
{ 'name': new Date(2018, 10, 1, 0, 0, 0, 0), 'value': 154.32 }
]
}];
xAxisTickFormatting(value: Date) {
if (value.getDate() < 9) {
return moment(value).format('MMM YYYY');
} else {
return '';
}
}
|
Debug
Firefox
Firefox → Inspect Element → Debugger → Webpack → src → app → *.ts
Ajouter des point d'arrêts
- Installer Debugger for Firefox
- Ajouter un nouvel élément de lancement
.vscode\launch.json
|
{
"name": "Debug Angular",
"type": "firefox",
"request": "launch",
"reAttach": true,
"url": "http://localhost:4200",
"webRoot": "${workspaceFolder}"
}
|
- Lancer le service Angular :
ng serve
- Lancer le debugage depuis VS code: Debug → Debug Angular → Run
|
ng build --prod
|
/etc/nginx/nginx.conf
|
try_files $uri $uri/ /index.html;
|
Variables d'environnement
src/environment.ts
|
export const environment = {
production: false,
myvar: 'dev'
};
|
src/environment.prod.ts
|
export const environment = {
production: true,
myvar: 'prod'
};
|
src/app/app.component.ts
|
import { environment } from '../environments/environment';
environment.myvar;
|
|
ng serve -c production
ng build --prod
|
|
npm install -g @angular/cli
yarn global add @angular/cli
yarn add @angular/cli
ng new MyAngularApp
cd MyAngularApp
ng serve --open
ng build
|
Windows
|
node --version
winget install OpenJS.NodeJS.LTS
|
Erreurs
Can't resolve 'rxjs/add/operator/map'
Vérifier que rxjs et rxjs-compat sont installés.
Got interpolation ({{}}) where expression was expected
Ne pas utiliser {{ }} dans un événement (click)
|
<a (click)="delete({{ item.id }})"><i class="fa fa-trash"></i></a>
<a (click)="delete(item.id)"><i class="fa fa-trash"></i></a>
|
|
import { NgZone } from '@angular/core';
this.http.get<Class[]>(`/api/class`).subscribe(data => {
this.ngZone.run(() => {
this.bindedValue = data;
});
});
|