Semua Perks, Tanpa Kerumitan: Tutorial Sudut 9
Diterbitkan: 2022-03-11"Setiap tahun internet rusak," kata pepatah, dan pengembang biasanya harus pergi dan memperbaikinya. Dengan Angular versi 9 yang telah lama ditunggu-tunggu, orang mungkin berpikir ini akan berlaku, dan aplikasi yang dikembangkan pada versi sebelumnya harus melalui proses migrasi besar-besaran.
Tapi bukan itu masalahnya! Tim Angular sepenuhnya mendesain ulang kompilernya, menghasilkan build yang lebih cepat, pengujian yang lebih cepat, ukuran bundel yang lebih kecil, dan yang terpenting, kompatibilitas mundur dengan versi yang lebih lama. Dengan Angular 9, pengembang pada dasarnya mendapatkan semua fasilitas tanpa kerumitan.
Dalam tutorial Angular 9 ini, kita akan membangun aplikasi Angular dari awal. Kami akan menggunakan beberapa fitur Angular 9 terbaru dan membahas peningkatan lainnya di sepanjang jalan.
Tutorial Angular 9: Memulai dengan Aplikasi Angular Baru
Mari kita mulai contoh proyek Angular kita. Pertama, mari kita instal versi terbaru CLI Angular:
npm install -g @angular/cli
Kami dapat memverifikasi versi Angular CLI dengan menjalankan ng version
.
Selanjutnya, mari kita buat aplikasi Angular:
ng new ng9-app --create-application=false --strict
Kami menggunakan dua argumen dalam perintah ng new
kami:
-
--create-application=false
akan memberi tahu CLI untuk hanya menghasilkan file ruang kerja. Ini akan membantu kita mengatur kode kita dengan lebih baik ketika kita perlu memiliki lebih dari satu aplikasi dan beberapa perpustakaan. -
--strict
akan menambahkan aturan yang lebih ketat untuk menegakkan lebih banyak pengetikan TypeScript dan kebersihan kode.
Sebagai hasilnya, kami memiliki folder dan file ruang kerja dasar.
Sekarang, mari tambahkan aplikasi baru. Untuk melakukan itu, kita akan menjalankan:
ng generate application tv-show-rating
Kami akan diminta:
? Would you like to share anonymous usage data about this project with the Angular Team at Google under Google's Privacy Policy at https://policies.google.com/privacy? For more details and how to change this setting, see http://angular.io/analytics. No ? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? SCSS
Sekarang, jika kita menjalankan ng serve
, kita akan melihat aplikasi berjalan dengan perancah awalnya.
Jika kita menjalankan ng build --prod
, kita dapat melihat daftar file yang dihasilkan.
Kami memiliki dua versi untuk setiap file. Satu kompatibel dengan browser lawas, dan yang lainnya dikompilasi dengan menargetkan ES2015, yang menggunakan API yang lebih baru dan membutuhkan lebih sedikit polyfill untuk dijalankan di browser.
Satu peningkatan besar dari Angular 9 adalah ukuran bundel. Menurut tim Angular, Anda dapat melihat penurunan hingga 40% untuk aplikasi besar.
Untuk aplikasi yang baru dibuat, ukuran bundel cukup mirip dengan Angular 8, tetapi seiring pertumbuhan aplikasi, Anda akan melihat ukuran bundel menjadi lebih kecil dibandingkan versi sebelumnya.
Fitur lain yang diperkenalkan di Angular 9 adalah kemampuan untuk memperingatkan kita jika salah satu file CSS gaya komponen lebih besar dari ambang batas yang ditentukan.
Ini akan membantu kami menangkap impor gaya buruk atau file gaya komponen besar.
Menambahkan Formulir untuk Menilai Acara TV
Selanjutnya, kami akan menambahkan formulir untuk menilai acara TV. Untuk itu, pertama kita akan menginstal bootstrap
dan ng-bootstrap
:
npm install bootstrap @ng-bootstrap/ng-bootstrap
Peningkatan lain pada Angular 9 adalah i18n (internasionalisasi). Sebelumnya, pengembang perlu menjalankan build lengkap untuk setiap lokal di aplikasi. Sebagai gantinya, Angular 9 memungkinkan kita membangun aplikasi sekali dan menghasilkan semua file i18n dalam proses pasca-pembuatan, yang secara signifikan mengurangi waktu pembuatan. Karena ng-bootstrap
memiliki ketergantungan pada i18n, kami akan menambahkan paket baru ke proyek kami:
ng add @angular/localize
Selanjutnya, kita akan menambahkan tema Bootstrap ke styles.scss
aplikasi kita :
@import "~bootstrap/scss/bootstrap";
Dan kami akan menyertakan NgbModule
dan ReactiveFormsModule
di AppModule
kami di app.module.ts
:
// ... import { ReactiveFormsModule } from '@angular/forms'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; @NgModule({ imports: [ // ... ReactiveFormsModule, NgbModule ], })
Selanjutnya, kami akan memperbarui app.component.html
dengan kisi dasar untuk formulir kami:
<div class="container"> <div class="row"> <div class="col-6"> </div> </div> </div>
Dan hasilkan komponen formulir:
ng gc TvRatingForm
Mari perbarui tv-rating-form.component.html
dan tambahkan formulir untuk menilai acara TV.
<form [formGroup]="form" (ngSubmit)="submit()" class="mt-3"> <div class="form-group"> <label>TV SHOW</label> <select class="custom-select" formControlName="tvShow"> <option *ngFor="let tvShow of tvShows" [value]="tvShow.name">{{tvShow.name}}</option> </select> </div> <div class="form-group"> <ngb-rating [max]="5" formControlName="rating"></ngb-rating> </div> <button [disabled]="form.invalid || form.disabled" class="btn btn-primary">OK</button> </form>
Dan tv-rating-form.component.ts
akan terlihat seperti ini:
// ... export class TvRatingFormComponent implements OnInit { tvShows = [ { name: 'Better call Saul!' }, { name: 'Breaking Bad' }, { name: 'Lost' }, { name: 'Mad men' } ]; form = new FormGroup({ tvShow: new FormControl('', Validators.required), rating: new FormControl('', Validators.required), }); submit() { alert(JSON.stringify(this.form.value)); this.form.reset(); } }
Terakhir, mari tambahkan formulir ke app.component.html
:
<!-- ... --> <div class="col-6"> <app-tv-rating-form></app-tv-rating-form> </div>
Pada titik ini, kami memiliki beberapa fungsionalitas UI dasar. Sekarang, jika kita menjalankan ng serve
lagi, kita bisa melihatnya beraksi.
Sebelum kita melanjutkan, mari kita lihat sekilas beberapa fitur Angular 9 baru yang menarik yang ditambahkan untuk membantu debugging. Karena ini adalah tugas yang sangat umum dalam pekerjaan kita sehari-hari, ada baiknya mengetahui apa yang telah berubah untuk membuat hidup kita sedikit lebih mudah.
Men-debug dengan Angular 9 Ivy
Peningkatan besar lainnya yang diperkenalkan di Angular 9 dan Angular Ivy adalah pengalaman debugging. Kompiler sekarang dapat mendeteksi lebih banyak kesalahan dan membuangnya dengan cara yang lebih "dapat dibaca".
Mari kita lihat dalam tindakan. Pertama, kita akan mengaktifkan pemeriksaan template di tsconfig.json
:
{ // ... "angularCompilerOptions": { "fullTemplateTypeCheck": true, "strictInjectionParameters": true, "strictTemplates": true } }
Sekarang, jika kita memperbarui array tvShows
dan mengganti name
menjadi title
:
tvShows = [ { title: 'Better call Saul!' }, { title: 'Breaking Bad' }, { title: 'Lost' }, { title: 'Mad men' } ];
…kita akan mendapatkan error dari compiler.
Pengecekan jenis ini akan memungkinkan kami untuk mencegah kesalahan ketik dan penggunaan jenis TypeScript yang salah.
Validasi Ivy Sudut untuk @Input()
Validasi bagus lainnya yang kami dapatkan adalah dengan @Input()
. Misalnya, kami dapat menambahkan ini ke tv-rating-form.component.ts
:
@Input() title: string;
…dan ikat di app.component.html
:
<app-tv-rating-form [title]="title"></app-tv-rating-form>
…dan kemudian ubah app.component.ts
seperti ini:
// ... export class AppComponent { title = null; }
Jika kita membuat ketiga perubahan ini, kita akan mendapatkan jenis kesalahan lain dari kompiler.
Jika kita ingin melewatinya, kita dapat menggunakan $any()
pada template untuk memberikan nilai ke any
dan memperbaiki kesalahan:
<app-tv-rating-form [title]="$any(title)"></app-tv-rating-form>
Namun, cara yang tepat untuk memperbaikinya adalah dengan membuat title
pada formulir dapat dibatalkan:
@Input() title: string | null ;
ExpressionChangedAfterItHasBeenCheckedError
di Angular 9 Ivy
Salah satu kesalahan yang paling ditakuti dalam pengembangan Angular adalah ExpressionChangedAfterItHasBeenCheckedError
. Untungnya, Ivy mengeluarkan kesalahan dengan cara yang lebih jelas, membuatnya lebih mudah untuk menemukan dari mana masalahnya berasal.
Jadi, mari kita perkenalkan kesalahan ExpressionChangedAfterItHasBeenCheckedError
. Untuk melakukannya, pertama, kami akan membuat layanan:
ng gs Title
Selanjutnya, kita akan menambahkan BehaviorSubject
, dan metode untuk mengakses Observable
dan untuk memancarkan nilai baru.
export class TitleService { private bs = new BehaviorSubject < string > (''); constructor() {} get title$() { return this.bs.asObservable(); } update(title: string) { this.bs.next(title); } }
Setelah itu, kita akan menambahkan ini ke app.component.html
:

<!-- ... --> <div class="col-6"> <h2> {{title$ | async}} </h2> <app-tv-rating-form [title]="title"></app-tv-rating-form> </div>
Dan di app.component.ts
, kami akan menyuntikkan TitleService
:
export class AppComponent implements OnInit { // ... title$: Observable < string > ; constructor( private titleSvc: TitleService ) {} ngOnInit() { this.title$ = this.titleSvc.title$; } // ... }
Terakhir, di tv-rating-form.component.ts
, kita akan menyuntikkan TitleService
dan memperbarui judul AppComponent
, yang akan memunculkan kesalahan ExpressionChangedAfterItHasBeenCheckedError
.
// ... constructor( private titleSvc: TitleService ) { } ngOnInit() { this.titleSvc.update('new title!'); }
Sekarang kita dapat melihat detail error di konsol dev browser, dan mengklik app.component.html
akan mengarahkan kita ke lokasi error.
Kami dapat memperbaiki kesalahan ini dengan membungkus panggilan layanan dengan setTimeout
:
setTimeout(() => { this.titleSvc.update('new title!'); });
Untuk memahami mengapa kesalahan ExpressionChangedAfterItHasBeenCheckedError
terjadi dan menjelajahi kemungkinan lain, posting Maxim Koretskyi tentang topik ini layak untuk dibaca.
Angular Ivy memungkinkan kita untuk menampilkan kesalahan dengan cara yang lebih jelas dan membantu menegakkan pengetikan TypeScript dalam kode kita. Di bagian berikut, kita akan membahas beberapa skenario umum di mana kita akan memanfaatkan Ivy dan debugging.
Menulis Tes untuk Aplikasi Angular 9 Kami dengan Komponen Harness
Di Angular 9, API pengujian baru diperkenalkan yang disebut komponen harness . Ide di baliknya adalah untuk menghapus semua tugas yang diperlukan untuk berinteraksi dengan DOM, membuatnya lebih mudah untuk dikerjakan dan lebih stabil untuk dijalankan.
API komponen harness disertakan dalam perpustakaan @angular/cdk
, jadi mari kita instal dulu di proyek kita:
npm install @angular/cdk
Sekarang kita dapat menulis pengujian dan memanfaatkan komponen memanfaatkan. Di tv-rating-form.component.spec.ts
, mari siapkan pengujian:
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { ReactiveFormsModule } from '@angular/forms'; describe('TvRatingFormComponent', () => { let component: TvRatingFormComponent; let fixture: ComponentFixture < TvRatingFormComponent > ; beforeEach(async (() => { TestBed.configureTestingModule({ imports: [ NgbModule, ReactiveFormsModule ], declarations: [TvRatingFormComponent] }).compileComponents(); })); // ... });
Selanjutnya, mari kita implementasikan ComponentHarness
untuk komponen kita. Kita akan membuat dua harness: satu untuk TvRatingForm
, dan satu lagi untuk NgbRating
. ComponentHarness
memerlukan bidang static
, hostSelector
, yang harus mengambil nilai pemilih komponen.
// ... import { ComponentHarness, HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; class TvRatingFormHarness extends ComponentHarness { static hostSelector = 'app-tv-rating-form'; } class NgbRatingHarness extends ComponentHarness { static hostSelector = 'ngb-rating'; } // ...
Untuk TvRatingFormHarness
, kami akan membuat pemilih untuk tombol kirim dan fungsi untuk memicu click
. Anda dapat melihat betapa mudahnya menerapkan ini.
class TvRatingFormHarness extends ComponentHarness { // ... protected getButton = this.locatorFor('button'); async submit() { const button = await this.getButton(); await button.click(); } }
Selanjutnya, kami akan menambahkan metode untuk menetapkan peringkat. Di sini kita menggunakan locatorForAll
untuk mencari semua elemen <span>
yang mewakili bintang yang dapat diklik pengguna. Fungsi rate
hanya mendapatkan semua bintang peringkat yang mungkin dan mengklik bintang yang sesuai dengan nilai yang dikirim.
class NgbRatingHarness extends ComponentHarness { // ... protected getRatings = this.locatorForAll('span:not(.sr-only)'); async rate(value: number) { const ratings = await this.getRatings(); return ratings[value - 1].click(); } }
Bagian terakhir yang hilang adalah menghubungkan TvRatingFormHarness
ke NgbRatingHarness
. Untuk melakukannya, kita cukup menambahkan locator pada kelas TvRatingFormHarness
.
class TvRatingFormHarness extends ComponentHarness { // ... getRating = this.locatorFor(NgbRatingHarness); // ... }
Sekarang, mari kita tulis pengujian kita:
describe('TvRatingFormComponent', () => { // ... it('should pop an alert on submit', async () => { spyOn(window, 'alert'); const select = fixture.debugElement.query(By.css('select')).nativeElement; select.value = 'Lost'; select.dispatchEvent(new Event('change')); fixture.detectChanges(); const harness = await TestbedHarnessEnvironment.harnessForFixture(fixture, TvRatingFormHarness); const rating = await harness.getRating(); await rating.rate(1); await harness.submit(); expect(window.alert).toHaveBeenCalledWith('{"tvShow":"Lost","rating":1}'); }); });
Perhatikan bahwa untuk select
kami dalam formulir, kami tidak menerapkan pengaturan nilainya melalui harness. Itu karena API masih tidak mendukung pemilihan opsi. Tapi ini memberi kita kesempatan untuk membandingkan di sini seperti apa interaksi dengan elemen sebelum memanfaatkan komponen.
Satu hal terakhir sebelum kita menjalankan tes. Kami perlu memperbaiki app.component.spec.ts
karena kami memperbarui title
menjadi null
.
describe('AppComponent', () => { // ... it(`should have as title 'tv-show-rating'`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app.title).toEqual(null); }); });
Sekarang, ketika kami menjalankan ng test
, pengujian kami lulus.
Kembali ke Aplikasi Contoh Angular 9 Kami: Menyimpan Data dalam Basis Data
Mari selesaikan tutorial Angular 9 kita dengan menambahkan koneksi ke Firestore dan menyimpan peringkat dalam database.
Untuk melakukan itu, kita perlu membuat Proyek Firebase. Kemudian, kita akan menginstal dependensi yang diperlukan.
npm install @angular/fire firebase
Dalam pengaturan proyek Firebase Console, kita akan mendapatkan konfigurasinya dan menambahkannya ke environment.ts
dan environment.prod.ts
:
export const environment = { // ... firebase: { apiKey: '{your-api-key}', authDomain: '{your-project-id}.firebaseapp.com', databaseURL: 'https://{your-project-id}.firebaseio.com', projectId: '{your-project-id}', storageBucket: '{your-project-id}.appspot.com', messagingSenderId: '{your-messaging-id}', appId: '{your-app-id}' } };
Setelah itu, kami akan mengimpor modul yang diperlukan di app.module.ts
:
import { AngularFireModule } from '@angular/fire'; import { AngularFirestoreModule } from '@angular/fire/firestore'; import { environment } from '../environments/environment'; @NgModule({ // ... imports: [ // ... AngularFireModule.initializeApp(environment.firebase), AngularFirestoreModule, ], // ... })
Selanjutnya, di tv-rating-form.component.ts
, kami akan menyuntikkan layanan AngularFirestore
dan menyimpan peringkat baru pada pengiriman formulir:
import { AngularFirestore } from '@angular/fire/firestore'; export class TvRatingFormComponent implements OnInit { constructor( // ... private af: AngularFirestore, ) { } async submit(event: any) { this.form.disable(); await this.af.collection('ratings').add(this.form.value); this.form.enable(); this.form.reset(); } }
Sekarang, ketika kita pergi ke Firebase Console, kita akan melihat item yang baru dibuat.
Terakhir, mari daftarkan semua peringkat ke dalam AppComponent
. Untuk melakukan itu, di app.component.ts
, kita akan mendapatkan data dari koleksi:
import { AngularFirestore } from '@angular/fire/firestore'; export class AppComponent implements OnInit { // ... ratings$: Observable<any>; constructor( // ... private af: AngularFirestore ) { } ngOnInit() { // ... this.ratings$ = this.af.collection('ratings').valueChanges(); } }
…dan di app.component.html
, kami akan menambahkan daftar peringkat:
<div class="container"> <div class="row"> // ... <div class="col-6"> <div> <p *ngFor="let rating of ratings$ | async"> {{rating.tvShow}} ({{rating.rating}}) </p> </div> </div> </div> </div>
Seperti inilah tampilan aplikasi tutorial Angular 9 kami ketika semuanya disatukan.
Angular 9 dan Angular Ivy: Pengembangan Lebih Baik, Aplikasi Lebih Baik, dan Kompatibilitas Lebih Baik
Dalam tutorial Angular 9 ini, kita telah membahas pembuatan formulir dasar, menyimpan data ke Firebase, dan mengambil item darinya.
Sepanjang jalan, kami melihat peningkatan dan fitur baru mana yang disertakan pada Angular 9 dan Angular Ivy. Untuk daftar lengkapnya, Anda dapat memeriksa posting rilis terbaru resmi blog Angular.
Sebagai Partner Google Cloud, para ahli Toptal bersertifikasi Google tersedia untuk perusahaan sesuai permintaan untuk proyek terpenting mereka.