npm i -g @angular/cli
ng new warsawjs-workshop-29-movies
ng
, np.
ng serve
start
z package.json - dopisać opcję
--open
npm start
webpack-dev-server
uruchamia apkę i reaguje na zmiany w
kodzietitle
na
"WarsawJS-Movies"
AppComponent
(plik app.component.ts),
można "osadzić" w HTML-u (app.component.html)title
:
test = 'nowości';
{{test}}
np. zamiast linijki z
imgonClick() { alert('Klik, klik!'); }
<h1>
:
<h1 (click)="onClick()">
h1 { cursor: pointer; }
export class Movie {
id: number;
title: string;
description: string;
url: string;
}
import { Component, NgModule } from '@angular/core';
@NgModule({ /* opcje */ })
export class AppModule { }
@Component({ /* opcje */ })
export class AppComponent {
/* ... */
}
ng g component movie
<div style="text-align:center">
<h1 (click)="onClick()">
Witaj w {{ title }}!
</h1>
{{test}}
</div>
<app-movie></app-movie>
<wjs-movie>
zamiast <app-movie>
MovieComponent
dodać:
movie: Movie = {
id: 1,
title: 'Subiektywny przegląd sytuacji na froncie - meet.js Poznań',
description: '"Nowy dzień, nowy framework". Jak żyć?',
url: 'https://www.youtube.com/embed/Aybh_2pIi2I'
}
import { Movie } from './movie';
Movie
<h1>{{movie.title}}</h1>
<iframe width="560" height="315" src="{{movie.url}}" frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen>
</iframe>
<p>{{movie.description}}</p>
import { DomSanitizer } from '@angular/platform-browser';
private sanitizer: DomSanitizer;
constructor(sanitizer: DomSanitizer) {
this.sanitizer = sanitizer;
}
getWrappedMovieUrl
:
getWrappedMovieUrl() {
return this.sanitizer.bypassSecurityTrustResourceUrl(this.movie.url);
}
[src]="getWrappedMovieUrl()"
private sanitizer: DomSanitizer;
constructor(sanitizer: DomSanitizer) {
this.sanitizer = sanitizer;
}
można:
constructor(private sanitizer: DomSanitizer) {}
get
jest częstym tematem i
zamiast:
getWrappedMovieUrl() { /* ... */ }
można:
get wrappedMovieUrl() { /* ... */ }
[src]="wrappedMovieUrl"
ng add @angular/material
@import "@angular/material/prebuilt-themes/pink-bluegrey.css";
class="mat-app-background"
do znacznika
<body>
w index.html
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';
i użyć ich w opcji imports
<mat-card>
<mat-card-header>
<mat-card-title>{{movie.title}}</mat-card-title>
</mat-card-header>
<iframe mat-card-image height="315" [src]="wrappedMovieUrl" frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen>
</iframe>
<mat-card-content>
<p>{{movie.description}}</p>
</mat-card-content>
<mat-card-actions>
<button mat-button>LIKE</button>
</mat-card-actions>
</mat-card>
mat-card { width: 560px; }
<app-movie>
(lub wjs-movie
) do
app.component.htmlmovies
:
ng g component movies
Movie
w nowym komponencie:
import { Component, OnInit } from '@angular/core';
import { Movie } from '../movie/movie';
@Component({
selector: 'wjs-movies',
templateUrl: './movies.component.html',
styleUrls: ['./movies.component.css']
})
export class MoviesComponent implements OnInit {
movies: Movie[] = [{
id: 1,
title: 'Subiektywny przegląd sytuacji na froncie - meet.js Poznań',
description: '"Nowy dzień, nowy framework". Jak żyć?',
url: 'https://www.youtube.com/embed/Aybh_2pIi2I'
}, {
id: 2,
title: 'Mateusz Chrzonstowski - Subiektywny przegląd front-endów |#49 IT Akademia j-labs',
description: `"Nowy dzień, nowy framework". Słyszeliście o tym?
Mateusz jest jedną z osób śledzących front-endy i chce podzielić się z Wami swoimi obserwacjami.`,
url: 'https://www.youtube.com/embed/KDTP9Dfkh1Q'
}]
constructor() {}
ngOnInit() {}
}
Input
z
'@angular/core'
movie
(usunąć stare przypisanie):
@Input() movie: Movie;
<wjs-movie *ngFor="let m of movies" [movie]="m"></wjs-movie>
:host {
display: flex;
justify-content: space-around;
}
movies
używa w swoim HTML-u komponentu movie
, więc
musi wstawić mu coś w @Input
<wjs-movie [movie]="currentMovie"></wjs-movie>
:host
pozwala nadać styl komponentowi, bezpośrednio
ng g service movies --flat=false
import { Injectable } from '@angular/core';
import { Movie } from '../movie/movie';
@Injectable({
providedIn: 'root'
})
export class MoviesService {
constructor() { }
readMovies(): Promise<Movie[]> {
return Promise.resolve([{/* 1 */}, {/* 2 */}, {
id: 3,
title: 'Lessons from writing my own Angular utility lib',
description: `I had a dream.
I wanted to create a popular open-source solution on top of Angular 2+`,
url: 'https://www.youtube.com/embed/AKZ_GShIg48'
}])
}
}
import { MoviesService } from './movies.service';
MoviesService
do MoviesComponent
(tak jak
DomSanitizer
w MovieComponent
)
ngOnInit
:
async ngOnInit() {
this.movies = await this.service.readMovies();
}
flex-wrap: wrap;
do stylu :host
a w
movies.component.css
ngOnInit
- odpala się po konstruktorze, gdy Input
y
już znane; wołana razPromise
- obietnica zwrócenia jakichś danychasync
, await
- czekanie aż obietnica będzie zawierać
dane
{
"id": 1,
"title": "Subiektywny przegląd sytuacji na froncie - meet.js Poznań",
"description": "\"Nowy dzień, nowy framework\". Jak żyć?",
"url": "https://www.youtube.com/embed/Aybh_2pIi2I"
}
moviesUrl: 'http://localhost:4200/assets/movies.json'
import { HttpClientModule } from '@angular/common/http';
HttpClientModule
do imports
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment';
HttpClient
w konstruktorze MoviesService
(tak
jak
DomSanitizer
w MovieComponent
)
readMovies
na:
return this.http.get<Movie[]>(environment.moviesUrl).toPromise();
import { FormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
movies
w movies.component.ts:
searchTitle = '';
private movies: Movie[] = [];
get filteredMovies() {
return this.movies
.filter(m => m.title.toLowerCase()
.includes(this.searchTitle.toLowerCase()));
}
<mat-form-field>
<input matInput type="search" placeholder="Szukaj" [(ngModel)]="searchTitle">
</mat-form-field>
<main>
<wjs-movie *ngFor="let m of filteredMovies" [movie]="m"></wjs-movie>
</main>
mat-form-field {
display: block;
width: 20em;
margin: 0 auto;
}
main {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
*ngIf
DomSanitizer
a