Bài viết trước mình đã đi qua về các thành phần chính của Ngrx và cách cài đặt.Ở bài viết này mình sẽ hướng dẫn các bạn chức năng Login sử dụng ngRx.
1.Bài toán
Chúng ta sẽ xây dựng xây dựng chức năng login với flow cơ bản như sau :
- Nhập email – password để login
- Login thành công hiện thông báo thành công , chuyển tới trang home và hiển thị username
- Login thất bại hiện thông báo thất bại
Bây giờ chúng ta cùng xem với Ngrx thì bài toán này sẽ được giải quyết như nào nhé.
2.Thực hiện
Như ở bài viết trước mình đã nói về các
thành phần của Ngrx.Bây giờ chúng ta cùng đi xây dựng nó nhé !
Đầu tiên cần tạo folder Store ,folder Store này sẽ là nơi chứa các Entity – thực thể, với bài toán của chúng ta thì Entity sẽ là User.Mỗi Entity này
sẽ gồm 4 thành phần chính :
- Actions
- State
- Reducer
- Selector
Chúng ta cùng đi vào chi tiết từng phần nhé !
Actions (user.actions.ts)
Tại file này chúng ta cần định nghĩa các Action
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token keyword">import</span> <span class="token punctuation">{</span> Action <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@ngrx/store'</span><span class="token punctuation">;</span> <span class="token comment">// định nghĩa type cho user action</span> <span class="token keyword">export</span> <span class="token keyword">enum</span> EUserActions <span class="token punctuation">{</span> <span class="token constant">LOGIN</span> <span class="token operator">=</span> <span class="token string">'[USER] Login'</span><span class="token punctuation">,</span> <span class="token constant">LOGIN_SUCCESS</span> <span class="token operator">=</span> <span class="token string">'[USER] Login Success'</span><span class="token punctuation">,</span> <span class="token constant">LOGIN_FAIL</span> <span class="token operator">=</span> <span class="token string">'[USER] Login Fail'</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">Login</span> <span class="token keyword">implements</span> <span class="token class-name">Action</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> readonly <span class="token keyword">type</span> <span class="token operator">=</span> EUserActions<span class="token punctuation">.</span><span class="token constant">LOGIN</span><span class="token punctuation">;</span> <span class="token keyword">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> payload<span class="token punctuation">:</span> <span class="token punctuation">{</span> email<span class="token punctuation">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> password<span class="token punctuation">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">LoginSuccess</span> <span class="token keyword">implements</span> <span class="token class-name">Action</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> readonly <span class="token keyword">type</span> <span class="token operator">=</span> EUserActions<span class="token punctuation">.</span><span class="token constant">LOGIN_SUCCESS</span><span class="token punctuation">;</span> <span class="token keyword">constructor</span><span class="token punctuation">(</span><span class="token keyword">public</span> payload<span class="token punctuation">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">LoginFail</span> <span class="token keyword">implements</span> <span class="token class-name">Action</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> readonly <span class="token keyword">type</span> <span class="token operator">=</span> EUserActions<span class="token punctuation">.</span><span class="token constant">LOGIN_FAIL</span><span class="token punctuation">;</span> <span class="token keyword">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">type</span> UserActions <span class="token operator">=</span> Login <span class="token operator">|</span> LoginSuccess <span class="token operator">|</span> LoginFail<span class="token punctuation">;</span> |
State (user.states.ts)
Tại file này chúng ta định nghĩa state được lưu trong store
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">export</span> <span class="token keyword">interface</span> <span class="token class-name">IUserLoginState</span> <span class="token punctuation">{</span> loading<span class="token punctuation">:</span> <span class="token builtin">boolean</span><span class="token punctuation">;</span> success<span class="token punctuation">:</span> <span class="token builtin">boolean</span><span class="token punctuation">;</span> fail<span class="token punctuation">:</span> <span class="token builtin">boolean</span><span class="token punctuation">;</span> userName<span class="token punctuation">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">interface</span> <span class="token class-name">IUserState</span> <span class="token punctuation">{</span> login<span class="token punctuation">:</span> IUserLoginState<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Reducer (user.reducer.ts)
Tại đây,dữ liệu sẽ được xử lý trước khi được “Đẩy” vào store
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <span class="token keyword">import</span> <span class="token punctuation">{</span> UserActions<span class="token punctuation">,</span> EUserActions <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.actions'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> IUserState<span class="token punctuation">,</span> IUserLoginState <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.states'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> initLoginState<span class="token punctuation">:</span> IUserLoginState <span class="token operator">=</span> <span class="token punctuation">{</span> loading<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> success<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> fail<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> userName<span class="token punctuation">:</span> <span class="token string">''</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> initUserState<span class="token punctuation">:</span> IUserState <span class="token operator">=</span> <span class="token punctuation">{</span> login<span class="token punctuation">:</span> initLoginState <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">userReducer</span><span class="token punctuation">(</span>state <span class="token operator">=</span> initUserState<span class="token punctuation">,</span> action<span class="token punctuation">:</span> UserActions<span class="token punctuation">)</span><span class="token punctuation">:</span> IUserState <span class="token punctuation">{</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span>action<span class="token punctuation">.</span><span class="token keyword">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> EUserActions<span class="token punctuation">.</span><span class="token constant">LOGIN</span><span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">></span> <span class="token operator">...</span>state<span class="token punctuation">,</span> login<span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span>initLoginState<span class="token punctuation">,</span> loading<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">case</span> EUserActions<span class="token punctuation">.</span><span class="token constant">LOGIN_SUCCESS</span><span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span>state<span class="token punctuation">,</span> login<span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span>state<span class="token punctuation">.</span>login<span class="token punctuation">,</span> loading<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> success<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> userName<span class="token punctuation">:</span> action<span class="token punctuation">.</span>payload <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">case</span> EUserActions<span class="token punctuation">.</span><span class="token constant">LOGIN_FAIL</span><span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span>state<span class="token punctuation">,</span> login<span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span>state<span class="token punctuation">.</span>login<span class="token punctuation">,</span> loading<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> fail<span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">default</span><span class="token punctuation">:</span> <span class="token keyword">return</span> state<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Ok.bây giờ để Reducer hoạt động chúng ta cần “Register” Reducer với Store
/store/index.ts
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> fromUser <span class="token keyword">from</span> <span class="token string">'./user'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> ActionReducerMap <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@ngrx/store'</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">interface</span> <span class="token class-name">IAppState</span> <span class="token punctuation">{</span> user<span class="token punctuation">:</span> fromUser<span class="token punctuation">.</span>IUserState<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">const</span> appReducer<span class="token punctuation">:</span> ActionReducerMap<span class="token operator"><</span>IAppState<span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">{</span> user<span class="token punctuation">:</span> fromUser<span class="token punctuation">.</span>userReducer <span class="token punctuation">}</span><span class="token punctuation">;</span> |
app.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <span class="token keyword">import</span> <span class="token punctuation">{</span> BrowserModule <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/platform-browser'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> NgModule <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/core'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> FormsModule<span class="token punctuation">,</span> ReactiveFormsModule <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/forms'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> AppRoutingModule <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./app-routing.module'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> AppComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./app.component'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> LoginComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./login/login.component'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> HomeComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./home/home.component'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> HttpClientModule <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/common/http'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> appReducer <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./store'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> EffectsModule <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@ngrx/effects'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> AppEffects <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./effects'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> StoreModule <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@ngrx/store'</span><span class="token punctuation">;</span> @<span class="token function">NgModule</span><span class="token punctuation">(</span><span class="token punctuation">{</span> declarations<span class="token punctuation">:</span> <span class="token punctuation">[</span> AppComponent<span class="token punctuation">,</span> LoginComponent<span class="token punctuation">,</span> HomeComponent <span class="token punctuation">]</span><span class="token punctuation">,</span> imports<span class="token punctuation">:</span> <span class="token punctuation">[</span> BrowserModule<span class="token punctuation">,</span> AppRoutingModule<span class="token punctuation">,</span> HttpClientModule<span class="token punctuation">,</span> FormsModule<span class="token punctuation">,</span> ReactiveFormsModule<span class="token punctuation">,</span> StoreModule<span class="token punctuation">.</span><span class="token function">forRoot</span><span class="token punctuation">(</span>appReducer<span class="token punctuation">)</span><span class="token punctuation">,</span> EffectsModule<span class="token punctuation">.</span><span class="token function">forRoot</span><span class="token punctuation">(</span>AppEffects<span class="token punctuation">)</span> <span class="token punctuation">]</span><span class="token punctuation">,</span> providers<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> bootstrap<span class="token punctuation">:</span> <span class="token punctuation">[</span>AppComponent<span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">AppModule</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
Đến đây chúng ta đã hoàn thành được 2/3 rồi.Tiếp theo chúng thực hiện việc Call Api để login.Ngrx cung cấp 1 package rất hay để xử lý việc
này là NgxEffect(các bạn tự tìm hiểu phần này nhé).
Tương tự với store chúng ta tạo folder effects
Effects
user.effects.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <span class="token keyword">import</span> <span class="token punctuation">{</span> Injectable <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"@angular/core"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Effect<span class="token punctuation">,</span> Actions<span class="token punctuation">,</span> ofType <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@ngrx/effects'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> switchMap<span class="token punctuation">,</span> map<span class="token punctuation">,</span> catchError <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'rxjs/operators'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> <span class="token keyword">of</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'rxjs'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> UserService <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'../user.service'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> fromUser <span class="token keyword">from</span> <span class="token string">'../store/user'</span><span class="token punctuation">;</span> @<span class="token function">Injectable</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserEffects</span> <span class="token punctuation">{</span> <span class="token keyword">constructor</span><span class="token punctuation">(</span><span class="token keyword">private</span> actions<span class="token punctuation">:</span> Actions<span class="token punctuation">,</span> <span class="token keyword">private</span> userService<span class="token punctuation">:</span> UserService<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> @<span class="token function">Effect</span><span class="token punctuation">(</span><span class="token punctuation">)</span> login$ <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>actions<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span> ofType<span class="token operator"><</span>fromUser<span class="token punctuation">.</span>Login<span class="token operator">></span><span class="token punctuation">(</span>fromUser<span class="token punctuation">.</span>EUserActions<span class="token punctuation">.</span><span class="token constant">LOGIN</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">switchMap</span><span class="token punctuation">(</span>action <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> email<span class="token punctuation">,</span> password <span class="token punctuation">}</span> <span class="token operator">=</span> action<span class="token punctuation">.</span>payload<span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>userService<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>email<span class="token punctuation">,</span> password<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span> <span class="token function">map</span><span class="token punctuation">(</span>res <span class="token operator">=></span> <span class="token keyword">new</span> <span class="token class-name">fromUser<span class="token punctuation">.</span>LoginSuccess</span><span class="token punctuation">(</span>email<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">catchError</span><span class="token punctuation">(</span>e <span class="token operator">=></span> <span class="token keyword">of</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">fromUser<span class="token punctuation">.</span>LoginFail</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
./effects/index.ts
1 2 3 4 | <span class="token keyword">import</span> <span class="token punctuation">{</span> UserEffects <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.effects'</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> AppEffects <span class="token operator">=</span> <span class="token punctuation">[</span>UserEffects<span class="token punctuation">]</span><span class="token punctuation">;</span> |
Components
login.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | <span class="token keyword">import</span> <span class="token punctuation">{</span> Component<span class="token punctuation">,</span> OnInit<span class="token punctuation">,</span> OnDestroy <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/core'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> FormGroup<span class="token punctuation">,</span> FormBuilder <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/forms'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> fromRoot <span class="token keyword">from</span> <span class="token string">'../store/index'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> fromUser <span class="token keyword">from</span> <span class="token string">'../store/user'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Store <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@ngrx/store'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Observable<span class="token punctuation">,</span> Subject <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'rxjs'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> takeUntil<span class="token punctuation">,</span> filter<span class="token punctuation">,</span> delay <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'rxjs/operators'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Router <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/router'</span><span class="token punctuation">;</span> @<span class="token function">Component</span><span class="token punctuation">(</span><span class="token punctuation">{</span> selector<span class="token punctuation">:</span> <span class="token string">'app-login'</span><span class="token punctuation">,</span> templateUrl<span class="token punctuation">:</span> <span class="token string">'./login.component.html'</span><span class="token punctuation">,</span> styleUrls<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'./login.component.scss'</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">LoginComponent</span> <span class="token keyword">implements</span> <span class="token class-name">OnInit</span><span class="token punctuation">,</span> OnDestroy <span class="token punctuation">{</span> loginForm<span class="token punctuation">:</span> FormGroup<span class="token punctuation">;</span> loading$<span class="token punctuation">:</span> Observable<span class="token operator"><</span><span class="token builtin">boolean</span><span class="token operator">></span><span class="token punctuation">;</span> success$<span class="token punctuation">:</span> Observable<span class="token operator"><</span><span class="token builtin">boolean</span><span class="token operator">></span><span class="token punctuation">;</span> error$<span class="token punctuation">:</span> Observable<span class="token operator"><</span><span class="token builtin">boolean</span><span class="token operator">></span><span class="token punctuation">;</span> destroy$<span class="token punctuation">:</span> Subject<span class="token operator"><</span><span class="token keyword">void</span><span class="token operator">></span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Subject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">constructor</span><span class="token punctuation">(</span> <span class="token keyword">private</span> fb<span class="token punctuation">:</span> FormBuilder<span class="token punctuation">,</span> <span class="token keyword">private</span> store<span class="token punctuation">:</span> Store<span class="token operator"><</span>fromRoot<span class="token punctuation">.</span>IAppState<span class="token operator">></span><span class="token punctuation">,</span> <span class="token keyword">private</span> router<span class="token punctuation">:</span> Router <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token function">ngOnInit</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>loading$ <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>store<span class="token punctuation">.</span><span class="token function">select</span><span class="token punctuation">(</span>fromUser<span class="token punctuation">.</span>getLoadingLogin<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">takeUntil</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>destroy$<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>success$ <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>store<span class="token punctuation">.</span><span class="token function">select</span><span class="token punctuation">(</span>fromUser<span class="token punctuation">.</span>getSuccessLogin<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">takeUntil</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>destroy$<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>error$ <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>store<span class="token punctuation">.</span><span class="token function">select</span><span class="token punctuation">(</span>fromUser<span class="token punctuation">.</span>getFailLogin<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">takeUntil</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>destroy$<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">initForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">onLoginSucess</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">ngOnDestroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>destroy$<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>destroy$<span class="token punctuation">.</span><span class="token function">complete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">initForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>loginForm <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>fb<span class="token punctuation">.</span><span class="token function">group</span><span class="token punctuation">(</span><span class="token punctuation">{</span> email<span class="token punctuation">:</span> <span class="token string">''</span><span class="token punctuation">,</span> password<span class="token punctuation">:</span> <span class="token string">''</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">submit</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> email<span class="token punctuation">,</span> password <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>loginForm<span class="token punctuation">.</span>value<span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">fromUser<span class="token punctuation">.</span>Login</span><span class="token punctuation">(</span><span class="token punctuation">{</span> email<span class="token punctuation">,</span> password <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">onLoginSucess</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>success$<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span> <span class="token function">filter</span><span class="token punctuation">(</span>success <span class="token operator">=></span> success<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">//đợi 3s sau khi login thành công,chuyển tới home page</span> <span class="token function">delay</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>success <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>router<span class="token punctuation">.</span><span class="token function">navigate</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'home'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
login.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h3</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text-center<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Login Page<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h3</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>alert alert-danger<span class="token punctuation">"</span></span> <span class="token attr-name">*ngIf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>error$ | async<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> Login fail <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>alert alert-success<span class="token punctuation">"</span></span> <span class="token attr-name">*ngIf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>success$ | async<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> Login success <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>login-form<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">(submit)</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>submit()<span class="token punctuation">"</span></span> <span class="token attr-name">[formGroup]</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>loginForm<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form-group<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>username<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Username<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form-control<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>username<span class="token punctuation">"</span></span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Enter email<span class="token punctuation">"</span></span> <span class="token attr-name">formControlName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form-group<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Password<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form-control<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Password<span class="token punctuation">"</span></span> <span class="token attr-name">formControlName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text-center<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>spinner-border<span class="token punctuation">"</span></span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>status<span class="token punctuation">"</span></span> <span class="token attr-name">*ngIf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>loading$ | async<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Loading...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>btn btn-primary<span class="token punctuation">"</span></span> <span class="token attr-name">[disabled]</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>loading$ | async<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Login<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> |