Hướng dẫn dùng angular 7.2 trong PHP
Show
Bài viết này tôi sẽ giải thích rõ từng thành phần cấu tạo và cách code Angular 4. Chúng ta sẽ đi lần lượt từ dễ đến khó về các khái niệm trong Angular 4, giúp bạn có cái nhìn tổng quan về cách code chuẩn nhất một hệ thống sử dụng Angular. Phiên bản mới nhất của Angular bây giờ là bản 6, tuy nhiên, phiên bản chính thức được sử dụng rất tốt bởi nhiều doanh nghiệp Enterprise, công ty lớn (ứng dụng nhiều người dùng, ứng dụng dành cho doanh nghiệp) và được Google hỗ trợ trọn đời (code sau 5 10 năm nữa cũng k cần chỉnh sửa gì dù công nghệ web có thay đổi ra sao đi nữa). Đó chính là phiên bản Angular 4. Do đó chúng ta hãy lấy bản này làm chuẩn. Còn bản 5, bản 6 thật ra đang là phiên bản thử nghiệm cho cộng đồng để tăng perfomance, thêm nhiều cách code hay ho hơn, nhưng cũng tiềm ẩn nhiều bugs hơn nếu xử lý code không tốt. Nếu bạn chưa biết gì hoặc mới học code Angular, bạn vẫn có thể sử dụng bài viết này để tham khảo và học hỏi cách code. Hãy upvote, share bạn bè, và clip (bookmark) bài này nếu bạn thấy hữu ích nhé! 1. ComponentsComponents là một khối code trong app Angular. Nó là sự kết hợp của bộ template html (bộ khung html) và nhúng kèm code TypeScript (hoặc Javascript). Các components là độc lập với nhau và độc lập với hệ thống. Nó có thể được cài vào hoặc tháo ra khỏi hệ thống dễ dàng. Một component có thể hiểu như một control trên màn hình hiển thị, gồm giao diện html và code logic xử lý sự kiện đi kèm control đó. Một component cũng có thể to lớn như là cả 1 màn hình chứa nhiều control hoặc một nhóm nhiều màn hình. Tức là là một component cũng có thể chứa và gọi được nhiều component khác nối vào. Như vậy Angular 4 rất linh hoạt trong việc chia nhỏ code ra các component. Trong Angular 4 chúng ta khai báo một Component với cấu trúc như sau:
Như chúng ta thấy từ khóa @Component sẽ giúp định nghĩa ra một bộ khung html cho nó. Và bên dưới là một class HelloWorld dùng để viết code logic. Trong định nghĩa bộ khung html, chúng ta có một số thuộc tính cần chú ý sau đây:
2. Bind dữ liệuAngular có cách code
Binding (kết nối giữa html và data) dữ liệu theo kiểu 2 chiều, nghĩa là html input thay đổi thì biến javascript sẽ ngay lập tức nhận được giá trị trả về và ngược lại, giá trị trong js thay đổi thì ngay lập tức màn hình html thay đổi theo. Chúng ta không cần đi nhặt nhạnh từng giá trị của các ô input như thời dùng jQuery nữa. Để bind một chuỗi ra ngoài màn hình html thì rất đơn giản sử dụng 2 dấu
ngoặc nhọn
Đó là hiển thị chuỗi string. Nhưng nếu muốn hiển thị giá trị đã có ra một ô input text, thì phải viết 2 dấu ngoặc vuông
Chú ý một chút, trong ví dụ này thì
3. Xử lý sự kiệnĐể gắn một sự kiện của một control html với một hàm javascript, trong Angular 4 chúng ta viết như sau:
Khi chúng ta viết (click) tức là muốn bind sự kiện click chuột của người dùng ở control này và gọi hàm updateTime() tương ứng trong code của Component này ra xử lý. 3.1 Xử lý thao tác của người dùngSự kiện thì có nhiều loại. Nếu sự kiện click thì đơn giản là khi nhấn xong chúng ta mới xử lý hành động. Nhưng có một số loại sự kiện cần xử lý data ngay trong lúc người dùng đang thao tác. Ví dụ người dùng gõ phím trên input text, người dùng chọn một option trong dropdownList, giá trị đang được chọn phải phản ánh ngay sang một control khác chẳng hạn. Lúc này chúng ta cần dùng đến biến events. Đoạn
code ví dụ sau đây, ngay khi người dùng gõ phím vào textbox, giá trị của textbox sẽ được lưu lại vào một biến
3.2 Xử lý thao tác của người dùng (ngon hơn cách 3.1)Cách viết code ở ví dụ 3.1 hoàn toàn chạy ngon và không ai bắt bẻ gì. Nhưng vấn đề là biến events nó chứa rất nhiều function/component con bên trong (nó chứa toàn bộ các hàm xử lý hàng trăm loại event khác nhau của một component, một control). Do đó sẽ là không khôn ngoan khi gửi và nhận cả một cục to như vậy đưa sang javascript trong khi cái chúng ta cần chỉ là giá trị đang được nhập của textbox. Hãy viết lại đoạn code vừa rồi như sau:
Như chúng ta thấy, hàm updateValue() lúc này nhận truyền vào là một biến Cách viết này rất được khuyên dùng. Các bạn lười quá thì viết kiểu 3.1 cũng được nhưng nếu biết chính xác cái sự kiện mình cần là gì thì nên viết theo 3.2. 3.3 Xử lý sự kiện binding 2 chiềuBan nãy, tôi đã bảo các bạn là viết như thế này là binding 2 chiều:
Nhưng tôi lừa các bạn đấy, viết như thế này là chỉ bind một chiều, nghĩa là chỉ show được giá trị ra thôi chứ không lấy được giá trị từ html tự động bỏ vào biến title. Ví dụ viết như sau thì giá trị của
Từ phiên bản Angular 2 trở lên thì anh Google đã quyết định là không nên cái gì cũng bind 2 chiều. Đó là vì bind 2 chiều sẽ làm khổ html. Nó sẽ phải render liên tục khi người dùng gõ vào ô input.
Rất đơn giản, lúc này chúng ta sẽ viết theo kiểu kẹp chuối. Viết theo cú pháp bên dưới đây sẽ giúp bạn bind được 2 chiều, khi gõ vào ô input thì giá trị của
Từ khóa
4. Sử dụng ngModel và form fieldsTừ khóa
Biến vm trong component chứa 2 thuộc tính là fname và lname. Chúng ta bind nó ra 2 input html để nhập giá trị cho nó. Tuy nhiên cần validate giá trị nhập vào. Nên ta kiểm tra bằng cách gọi {{fname.className}} để xem class của input textbox hiện tại đang là cái gì. Chú ý, khi sử dụng ngModel trong một form html. Bắt buộc phải có attribute If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions. Chúng ta sẽ có các class tự động sinh ra ở input type="text" như sau:
Các class sẽ tự động sinh ra và gắn vào input mỗi khi có sự thay đổi dữ liệu trên form. Và nhiệm vụ của bạn là định nghĩa css style tương ứng với các thay đổi đó. Ví dụ:
Sau khi áp dụng style thì sẽ như sau: 5. ngModuleModule là một khái niệm rộng nhất của Angular. Một module có thể bao gồm chứa các components, directives, pipes, v.v. Module có thể được biên dịch (compile) dưới dạng ahead-of-time (AoT). Nghĩa là biên dịch ra mã thực thi để hiện ra luôn trên trình duyệt không cần vẽ vời gì từ đầu. Hãy tưởng tượng component có html và js viết riêng, khi load trang thì 2 thứ này mới nhào nặn chung để hiển thị html+data lên màn hình. AoT là thứ html+data đã nhào sẵn. Module cũng có thể gọi module con và bắt tay được với các module khác. Ví dụ về module chúng ta có thể bắt gặp ngay ở trong app.module.ts
Như vậy thì bản thân một app Angular chính là một module khổng lồ, trong đó cài cắm nhiều module con. Các thuộc tính của module được định nghĩa như sau:
6. ServicesMột service là một đoạn code trong ứng dụng Angular mà phục vụ cho tác vụ gì đó, xử lý code logic gì đó. Ví dụ handle (xử lý) data gửi nhận từ/đến một API, hoặc cung cấp hàm authenticate... Tất nhiên là service thì chỉ có code không hề có giao diện. Để tạo ra một service thì chúng ta cần import và mô tả một class với từ khóa Ta hãy lấy một ví dụ:
Sau khi định nghĩa class TimeService là 6.1 Dependency Injection (DI)Khi một class muốn được gọi (được tiêm vào, inject vào) một component cần gọi hàm bên trong nó, chúng ta cần dùng đến Dependency Injection. Và rất đơn giản chỉ cần gọi ở hàm khởi tạo (constructor) của component là sẽ tiêm được service vào để dùng nó bên trong component đó.
6.2 Viết service dưới dạng dùng chungNếu chúng ta dùng service ở nhiều nơi cùng lúc và không muốn khai báo nhiều lần, component nào cũng phải tiêm nó vào. Thì lúc này có thể khai báo service ở phần
7. DirectivesDirectives có thể hiểu như là các đoạn mã typescript (hoặc javascript) kèm theo cả html và khi gọi thì gọi như là html luôn, ví dụ:
Từ Angular 2 trở đi, directives được chia làm các loại sau đây:
7.1 Ng-if… elseĐây là một Structural directives, có tác dụng kiểm tra điều kiện ngay ở html. Ví dụ:
Code ở trên, khi biến title có giá trị, thì chuỗi Như ta thấy dùng cái directive 7.2 Ng-TemplateĐây cũng là một Structural directives. Nó giúp gom cục html cần ẩn hiện.
Chú ý là đoạn code vừa rồi dùng 7.3 Ng-ContainerTương tự như Hãy xem ví dụ sau đây:
Sẽ được render ra như sau: Khi soi html chúng ta sẽ thấy: Tự dưng dòng div có Bây giờ hãy viết lại như sau:
Kết quả sẽ nuột nà ngay: Đó là vì html đã được dọn gọn gàng: 7.4 NgSwitch and NgSwitchCaseChúng ta hoàn toàn có thể sử dụng câu lệnh điều kiện switch case trong Angular y như switch case trong Javascript vậy. Cách viết như sau:
Trong trường hợp muốn dùng switch case default (nếu toàn bộ case k thỏa màn thì vào default) thì chúng ta viết như sau:
7.5 Hàm InputMột directive hoàn toàn có thể nhận giá trị truyền vào để hiển thị hoặc tính toán. Hãy xem một ví dụ sau đây. Giả sử chúng ta khai báo một
Chúng ta định nghĩa template html của component như sau:
Khi gọi render ra component login thì truyền cái biến Input cho nó như sau:
Nếu bạn muốn giá trị của biến
Trong đó
vẫn được nhé, hãy viết như sau ở khai báo @Input()
7.6 Hàm OutputMột directive nhận giá trị về để hiển thị được. Vậy có thể nào bên trong directive trả giá trị ngược trở lại được không? Được luôn. Lúc này chúng ta sẽ cần dùng đến EventEmitter (lấy giá trị trả về từ sự kiện người dùng thao tác). Ví dụ khi người dùng nhập xong id và password của một directive. Chúng ta muốn nhận được giá trị đã nhập ở một directive gọi directive login chứ không chỉ xử lý id và pass bên trong directive login. Lúc này cần import thư viện EventEmitter trước:
Sau
đó khai báo một
Ở html của directive con thì xử lý sự kiện click bình thường
Và ở code logic thì bắn giá trị nhận được từ input gửi sang cho thằng
Giờ thì sang viết ở
Trong code directive cha, giờ thì sự kiện nhận được từ directive con sẽ chứa Object truyền sang (là id và pass nhập từ directive con)
Như vậy là chúng ta đã biết cách để bắn giá trị từ 8. Phát hiện thay đổi trong AngularĐể binding được 2 chiều thì rõ ràng Angular phải có cơ chế để phát hiện sự thay đổi, cho dù là từ html hay là biến js thay đổi giá trị, đều phải quét lần lượt các component thì mới biết được cái gì thay đổi. Angular dùng cơ chế là quét từ trên xuống dưới (top-down), tức là từ component cha rồi đến component con được lần lượt kiểm tra.
Rất đơn giản, mỗi một component trong Angular đều có một class đi kèm với nó để so sánh. Khi có sự thay đổi value của từng biến trong component (do người dùng nghịch vào các events), lúc này giá trị ban đầu của component được lưu trước đó sẽ lấy ra so sánh. Nếu model có sự thay đổi, hiển nhiên là Angular lập tức gọi html làm việc, render ra giá trị mới trên DOM tức khắc. Đấy là cách lưu giá trị và so sánh cho các kiểu dữ liệu giá trị như là string, bool, int...Còn nếu dữ liệu là kiểu class phức tạp mà người dùng tự định nghĩa ra. Thì lúc này cơ chế so sánh lưu giá trị sẽ dùng 1 trong 2 cách sau: Shallow Comparison (So sánh nông): Tức là một trong số các thuộc tính của biến này (biến này là một class to) thay đổi thì cả biến đó vẫn không được nhận xét là đã thay đổi và không cập nhật giá trị. Tại sao lại so sánh khập khiễng như thế này? Cái này sẽ giúp ích trong trường hợp chúng ta dùng class dạng immutable (dùng biến như là hằng số). Rõ ràng cần phải tạo một biến mới để chứa giá trị thay đổi chứ bản thân giá trị đó k được phép thay đổi => update làm gì cho mất công. Deep Comparison (So sánh sâu): Đi lần lượt từng thuộc tính của biến và so sánh giá trị đã bị thay đổi. Dĩ nhiên là toàn bộ giá trị của class phải được lưu lại trước đó để so sánh. Khi một trong số thuộc tính bị thay đổi, toàn bộ biến đó coi như bị thay đổi và toàn bộ html cần thay đổi theo. 9. Transclusion (trao đổi giữa directive) trong AngularỞ mục 7 chúng ta đã biết về việc một Directive có thể nhận đầu vào và cả xuất ra đầu ra. Nhưng chúng ta chỉ có thể nhập và xuất directive ở thuộc tính html của tag gọi directive. Ví dụ
Nếu bây giờ chúng ta lại muốn viết vào giữa tag gọi directive thì sao? ví dụ viết vào giữa begin và end tag? Trong Angular bản 1.X thì có một khái niệm là Transclusion (trao đổi giá trị giữa các directive). Lên Angular 4 thì vẫn hỗ trợ. Lúc này ta có thể viết như sau:
Sau khi định nghĩa ra
Chỗ
này hơi khó hiểu một chút vì không có lời gọi directive (component) Rõ ràng là việc lấy được ruột html của directive cực kỳ hữu ích khi mà chúng ta có thể chứa html của 10. Sử dụng observables ở ngay htmlChúng ta biết là Observables là luồng dữ liệu được gửi nhận từ api. Observables sẽ chứa data json từ server gửi tới nhưng nó không phải là data json thuần. Nếu đưa luồng data này cho html thì nó sẽ không hiểu được để render ra màn hình. Tuy nhiên với từ khóa pipe async chúng ta có thể in ra trực tiếp như sau:
Lúc này biến Nếu chúng ta có một mảng ở dạng Observables thì
cũng hoàn toàn có thể in ra trực tiếp bằng async sử dụng
11. Không cho nhập giá trị NullTypeScript 4 hỗ trợ việc check giá trị Null hoặc Undefined và không cho phép gán 2 loại giá trị này cho một biến đã được khai báo kiểu cụ thể. Ví dụ:
Một biến cũng hoàn toàn có thể được khai báo là một trong 2 kiểu dữ liệu, như ví dụ dưới đây:
Mặc định không nói gì thì Typescript sẽ bật strictNullCheck là true. Do đó nếu muốn string có
thể chứa cả giá trị null, chúng ta có thể tắt nó đi bằng cách sửa ở file 12. Gọi đến HTTP API và nhận về luồng ObservablesĐể gọi được api từ server, Angular đã trang bị sẵn cho bạn bộ service http nằm ở thư viện
Hàm
Chú ý là chỗ này chúng ta sử dụng đến hàm
Dùng hàm map thì chúng ta vẫn chưa lấy được data json thực sự, cần phải dùng hàm subcribe để đọc ra cái data đã được map.
May thay cho bạn, là vẫn có một cách viết cho người lười. đó là dùng đến hàm pipe Ví dụ đây:
Và để hiển thị biến
Chúng ta có thể dùng dấu chấm để gọi cho các thuộc tính con của nó.
Chú ý một chút chỗ này: 13. Nhưng tôi yêu cách code kiểu Promises, tôi ghét ObservablesTrong Angular, mặc định thì rxjs được dùng để xử lý data trả về từ http request. Nhưng nếu chúng ta thích trả về Promises cho dễ thao tác hơn. Thì rxjs hoàn toàn đáp ứng được. Chúng ta sẽ có hàm
Cách sử dụng như sau:
Lúc này để lấy được data ra từ cục Promises thì cần dùng đến hàm callback.
Và ở html không cần dùng async gì lằng nhằng cứ bắn ra giá trị thôi nào:
14. RouterKhi sử dụng Router, chúng ta sẽ có thể dựng nên một trang web SPA (Single Page Application). Khi viết một route template, các components sẽ được map tương ứng với các URL cố định. Và khi click vào link, url sẽ load component mà không cần load lại cả trang. Dẫn đến hiệu ứng là trang web chạy trong 1 tab và các màn hình được load động. Cách hoạt động này khác với MPA (Multiple Page Application) thường thì mỗi màn hình sẽ có url tương ứng và phải bật một tab riêng trên trình duyệt. Router cũng có cache, tức là component đã load một lần thì sẽ được load lại không cần tải toàn bộ về từ server nữa. Để bắt đầu sử dụng Router thì khi tạo project bằng Angular CLI, chúng ta chạy dòng lệnh sau đây:
Còn nếu project của bạn đã có sẵn và chưa áp dụng Router, hãy chạy đoạn lệnh sau để thêm Routing vào application của bạn:
14.1 Router OutletMỗi một Router sẽ có một URL để load component. Và để biết được là component sẽ render ra chỗ nào thì chúng ta viết đoạn code sau vào khung html cần chèn:
14.2 Cài đặt Route cho ứng dụng AngularĐể cài đặt toàn bộ Router cho một ứng dụng Angular thì chúng ta cần tạo ra một đối tượng JSON chứa các thuộc tính như sau:
Hãy xem đoạn code ví dụ về Router bên dưới:
14.3 Child RoutesKhi chúng ta muốn một trang có các trang con bên trong nó. Ví dụ trang Grid data sẽ chứa trang Thêm, Sửa, Xóa tương ứng. Lúc này chúng ta viết thêm thuộc tính Cách viết như sau:
Như vậy là các component nếu dùng Route để định nghĩa lồng nhau thì chúng ta sẽ dùng lại biến 14.4 ParamsData hoàn toàn có thể được truyền từ màn hình này sang màn hình kia bằng cách vứt giá trị vào trong url để gọi (hay còn gọi là cách gọi hàm bằng truyền params URL). Các bước để làm được việc này như sau:
Kết bàiBài này là một bài dịch. Link bài gốc ở đây: https://www.dotnetcurry.com/angular/1385/angular-4-cheat-sheet Hi vọng các bạn sẽ share thật nhiều đến bạn bè của mình và lưu bài này lại để tham khảo về sau. Hẹn gặp lại các bạn trong các bài sắp tới !!! |