The previous article I went through about the main components of Ngrx and how to install it. In this article, I will guide you the Login function using ngRx.
1. Maths
We will build the login function with basic flow as follows:
- Enter email – password to login
- Successful login now shows success message, redirects to home page and displays username
- Login failed shows failure message
Now let’s see with Ngrx how this problem will be solved.
2. Make it
As in the previous article I talked about the components of Ngrx. Now let’s go build it offline!
First need to create a Store folder, this Store folder will be where the Entities are stored – entities, with our problem, Entity will be the User. Each Entity will consist of 4 main components:
- Actions
- State
- Reducer
- Selector
Let’s go into each part details!
Actions (user.actions.ts)
In this file we need to define the 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)
In this file we define the state stored in the 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)
Here, the data will be processed before being “Pushed” into the 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. Now for Reducer to work we need to “Register” Reducer with the 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> |
At this point, we have completed two-thirds of the time. Next, we make Call Api to login.Ngrx provides a very nice package to handle this is NgxEffect (you can find out for yourself this section). Similar to the store we create 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> |