From 802f78d0c1326994168177a847442bbc7364ca5f Mon Sep 17 00:00:00 2001 From: Bruno Leonardo Michels Date: Fri, 22 Jun 2018 00:54:13 -0300 Subject: [PATCH 1/9] Install mobx mobx-angular --- package-lock.json | 10 ++++++++++ package.json | 2 ++ 2 files changed, 12 insertions(+) diff --git a/package-lock.json b/package-lock.json index 61793c9..e17a7cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9010,6 +9010,16 @@ } } }, + "mobx": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/mobx/-/mobx-5.0.3.tgz", + "integrity": "sha1-U7l/Kg+bDdd3TJYkn4G/LVE9jhw=" + }, + "mobx-angular": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mobx-angular/-/mobx-angular-3.0.1.tgz", + "integrity": "sha512-PoEUEw74LoR7Ib6iGGCqvw8xMlmA/Zr5/0TVyhshq4kuzA8pHdvtCiE5AeyRK0w4LhyS7J0Qt0GboTgdhuys+A==" + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", diff --git a/package.json b/package.json index b3ac062..bc9485f 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,8 @@ "camelcase-keys": "^4.2.0", "core-js": "^2.4.1", "marked": "^0.4.0", + "mobx": "^5.0.3", + "mobx-angular": "^3.0.1", "ngx-redux-state-props": "0.0.6", "ngx-take-until-destroy": "^3.0.0", "redux": "^4.0.0", From 97613d65d51b616efc28e4c3e2c373bd6f86e7b8 Mon Sep 17 00:00:00 2001 From: Bruno Leonardo Michels Date: Fri, 22 Jun 2018 00:56:59 -0300 Subject: [PATCH 2/9] Import store modules in app module --- src/app/app.module.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 556f9f8..ecfa34b 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -2,11 +2,17 @@ import { NgReduxRouterModule } from '@angular-redux/router'; import { NgReduxModule } from '@angular-redux/store'; import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; +import { MobxAngularModule } from 'mobx-angular'; import { NgxReduxStatePropsModule } from 'ngx-redux-state-props'; +import { AboutStoreService } from './about/about-store.service'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app.router'; +import { ContactStoreService } from './contact/contact-store.service'; +import { AppStoreService } from './core/app-store.service'; +import { HeroesStoreService } from './heroes/heroes-store.service'; import { SharedModule } from './shared/shared.module'; +import { TutorialsStoreService } from './tutorials/tutorials-store.service'; @NgModule({ declarations: [AppComponent], @@ -14,11 +20,12 @@ import { SharedModule } from './shared/shared.module'; AppRoutingModule, BrowserModule, SharedModule, + MobxAngularModule, NgReduxModule, NgReduxRouterModule.forRoot(), NgxReduxStatePropsModule, ], - providers: [], + providers: [AppStoreService, AboutStoreService, ContactStoreService, HeroesStoreService, TutorialsStoreService], bootstrap: [AppComponent], }) export class AppModule {} From f8f780a8733c6b7098a907b400ea256019ee9218 Mon Sep 17 00:00:00 2001 From: Bruno Leonardo Michels Date: Fri, 22 Jun 2018 00:57:45 -0300 Subject: [PATCH 3/9] Add stores --- src/app/about/about-store.service.spec.ts | 15 +++++++++++++++ src/app/about/about-store.service.ts | 15 +++++++++++++++ src/app/contact/contact-store.service.spec.ts | 15 +++++++++++++++ src/app/contact/contact-store.service.ts | 6 ++++++ src/app/core/app-store.service.spec.ts | 15 +++++++++++++++ src/app/core/app-store.service.ts | 18 ++++++++++++++++++ src/app/heroes/heroes-store.service.spec.ts | 15 +++++++++++++++ src/app/heroes/heroes-store.service.ts | 6 ++++++ .../tutorials/tutorials-store.service.spec.ts | 15 +++++++++++++++ src/app/tutorials/tutorials-store.service.ts | 6 ++++++ 10 files changed, 126 insertions(+) create mode 100644 src/app/about/about-store.service.spec.ts create mode 100644 src/app/about/about-store.service.ts create mode 100644 src/app/contact/contact-store.service.spec.ts create mode 100644 src/app/contact/contact-store.service.ts create mode 100644 src/app/core/app-store.service.spec.ts create mode 100644 src/app/core/app-store.service.ts create mode 100644 src/app/heroes/heroes-store.service.spec.ts create mode 100644 src/app/heroes/heroes-store.service.ts create mode 100644 src/app/tutorials/tutorials-store.service.spec.ts create mode 100644 src/app/tutorials/tutorials-store.service.ts diff --git a/src/app/about/about-store.service.spec.ts b/src/app/about/about-store.service.spec.ts new file mode 100644 index 0000000..a7b9ce9 --- /dev/null +++ b/src/app/about/about-store.service.spec.ts @@ -0,0 +1,15 @@ +import { inject, TestBed } from '@angular/core/testing'; + +import { AboutStoreService } from './about-store.service'; + +describe('AboutStoreService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [AboutStoreService], + }); + }); + + it('should be created', inject([AboutStoreService], (service: AboutStoreService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/src/app/about/about-store.service.ts b/src/app/about/about-store.service.ts new file mode 100644 index 0000000..06d563b --- /dev/null +++ b/src/app/about/about-store.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { action, observable } from 'mobx-angular'; + +@Injectable({ + providedIn: 'root', +}) +export class AboutStoreService { + @observable title = 'about:hello world'; + + @action + randomTitle() { + // tslint:disable-next-line:no-magic-numbers + this.title = Math.random().toString(32); + } +} diff --git a/src/app/contact/contact-store.service.spec.ts b/src/app/contact/contact-store.service.spec.ts new file mode 100644 index 0000000..508433f --- /dev/null +++ b/src/app/contact/contact-store.service.spec.ts @@ -0,0 +1,15 @@ +import { inject, TestBed } from '@angular/core/testing'; + +import { ContactStoreService } from './contact-store.service'; + +describe('ContactStoreService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ContactStoreService], + }); + }); + + it('should be created', inject([ContactStoreService], (service: ContactStoreService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/src/app/contact/contact-store.service.ts b/src/app/contact/contact-store.service.ts new file mode 100644 index 0000000..7303a23 --- /dev/null +++ b/src/app/contact/contact-store.service.ts @@ -0,0 +1,6 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class ContactStoreService {} diff --git a/src/app/core/app-store.service.spec.ts b/src/app/core/app-store.service.spec.ts new file mode 100644 index 0000000..03725f9 --- /dev/null +++ b/src/app/core/app-store.service.spec.ts @@ -0,0 +1,15 @@ +import { inject, TestBed } from '@angular/core/testing'; + +import { AppStoreService } from './app-store.service'; + +describe('AppStoreService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [AppStoreService], + }); + }); + + it('should be created', inject([AppStoreService], (service: AppStoreService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/src/app/core/app-store.service.ts b/src/app/core/app-store.service.ts new file mode 100644 index 0000000..080905f --- /dev/null +++ b/src/app/core/app-store.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@angular/core'; + +import { AboutStoreService } from '../about/about-store.service'; +import { ContactStoreService } from '../contact/contact-store.service'; +import { HeroesStoreService } from '../heroes/heroes-store.service'; +import { TutorialsStoreService } from '../tutorials/tutorials-store.service'; + +@Injectable({ + providedIn: 'root', +}) +export class AppStoreService { + constructor( + public about: AboutStoreService, + public contact: ContactStoreService, + public heroes: HeroesStoreService, + public tutorials: TutorialsStoreService, + ) {} +} diff --git a/src/app/heroes/heroes-store.service.spec.ts b/src/app/heroes/heroes-store.service.spec.ts new file mode 100644 index 0000000..bcffbae --- /dev/null +++ b/src/app/heroes/heroes-store.service.spec.ts @@ -0,0 +1,15 @@ +import { inject, TestBed } from '@angular/core/testing'; + +import { HeroesStoreService } from './heroes-store.service'; + +describe('HeroesStoreService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [HeroesStoreService], + }); + }); + + it('should be created', inject([HeroesStoreService], (service: HeroesStoreService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/src/app/heroes/heroes-store.service.ts b/src/app/heroes/heroes-store.service.ts new file mode 100644 index 0000000..f24cae8 --- /dev/null +++ b/src/app/heroes/heroes-store.service.ts @@ -0,0 +1,6 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class HeroesStoreService {} diff --git a/src/app/tutorials/tutorials-store.service.spec.ts b/src/app/tutorials/tutorials-store.service.spec.ts new file mode 100644 index 0000000..8e56a37 --- /dev/null +++ b/src/app/tutorials/tutorials-store.service.spec.ts @@ -0,0 +1,15 @@ +import { inject, TestBed } from '@angular/core/testing'; + +import { TutorialsStoreService } from './tutorials-store.service'; + +describe('TutorialsStoreService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [TutorialsStoreService], + }); + }); + + it('should be created', inject([TutorialsStoreService], (service: TutorialsStoreService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/src/app/tutorials/tutorials-store.service.ts b/src/app/tutorials/tutorials-store.service.ts new file mode 100644 index 0000000..681180c --- /dev/null +++ b/src/app/tutorials/tutorials-store.service.ts @@ -0,0 +1,6 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class TutorialsStoreService {} From 37b03c331d8b6afbf7c1249701b74431877e80a7 Mon Sep 17 00:00:00 2001 From: Bruno Leonardo Michels Date: Fri, 22 Jun 2018 00:58:10 -0300 Subject: [PATCH 4/9] Use stores --- src/app/about/about.component.html | 6 ++++++ src/app/about/about.component.ts | 13 ++++++++++++- src/app/contact/form/form.component.html | 5 +++++ src/app/contact/form/form.component.ts | 4 +++- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/app/about/about.component.html b/src/app/about/about.component.html index 66cac57..ac62a4e 100644 --- a/src/app/about/about.component.html +++ b/src/app/about/about.component.html @@ -4,6 +4,12 @@

+
+

Mobx

+

{{ store?.about?.title }}

+ +
+ - diff --git a/src/app/about/about.component.ts b/src/app/about/about.component.ts index 2069efb..8b61299 100644 --- a/src/app/about/about.component.ts +++ b/src/app/about/about.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { NgxReduxStatePropsService } from 'ngx-redux-state-props'; import { AppState } from '../app-state.model'; +import { AppStoreService } from '../core/app-store.service'; import { AboutActions } from './services/about.actions'; @Component({ @@ -17,7 +18,11 @@ export class AboutComponent { - here - or here`; - constructor(private actions: AboutActions, private redux: NgxReduxStatePropsService) {} + constructor( + private actions: AboutActions, + private redux: NgxReduxStatePropsService, + public store: AppStoreService, + ) {} get state() { return this.redux.appState && this.redux.appState.about; @@ -30,4 +35,10 @@ export class AboutComponent { getNasaApod() { this.actions.getNasaApod(); } + + updateTitle() { + // tslint:disable-next-line:no-magic-numbers + this.store.about.title = `${Math.random() * 10000}`; + // this.store.about.randomTitle(); + } } diff --git a/src/app/contact/form/form.component.html b/src/app/contact/form/form.component.html index 86daccb..5698e97 100644 --- a/src/app/contact/form/form.component.html +++ b/src/app/contact/form/form.component.html @@ -1,3 +1,8 @@ +
+

About page title is

+

{{ store?.about?.title }}

+
+
diff --git a/src/app/contact/form/form.component.ts b/src/app/contact/form/form.component.ts index 361fe1c..2ed6ae5 100644 --- a/src/app/contact/form/form.component.ts +++ b/src/app/contact/form/form.component.ts @@ -1,6 +1,8 @@ import { Component } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; +import { AppStoreService } from '../../core/app-store.service'; + @Component({ selector: 'app-form', templateUrl: './form.component.html', @@ -12,7 +14,7 @@ export class FormComponent { message: this.formBuilder.control('', Validators.required), }); - constructor(private formBuilder: FormBuilder) {} + constructor(private formBuilder: FormBuilder, public store: AppStoreService) {} submit() { if (this.contactForm.invalid) { From 9f813a0e99be511601ea816de27aeb7b5735939b Mon Sep 17 00:00:00 2001 From: Bruno Leonardo Michels Date: Fri, 22 Jun 2018 01:06:37 -0300 Subject: [PATCH 5/9] Move app store --- src/app/about/about.component.ts | 2 +- src/app/{core => }/app-store.service.spec.ts | 0 src/app/{core => }/app-store.service.ts | 8 ++++---- src/app/app.module.ts | 2 +- src/app/contact/form/form.component.ts | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename src/app/{core => }/app-store.service.spec.ts (100%) rename src/app/{core => }/app-store.service.ts (51%) diff --git a/src/app/about/about.component.ts b/src/app/about/about.component.ts index 8b61299..6299a52 100644 --- a/src/app/about/about.component.ts +++ b/src/app/about/about.component.ts @@ -2,7 +2,7 @@ import { Component } from '@angular/core'; import { NgxReduxStatePropsService } from 'ngx-redux-state-props'; import { AppState } from '../app-state.model'; -import { AppStoreService } from '../core/app-store.service'; +import { AppStoreService } from '../app-store.service'; import { AboutActions } from './services/about.actions'; @Component({ diff --git a/src/app/core/app-store.service.spec.ts b/src/app/app-store.service.spec.ts similarity index 100% rename from src/app/core/app-store.service.spec.ts rename to src/app/app-store.service.spec.ts diff --git a/src/app/core/app-store.service.ts b/src/app/app-store.service.ts similarity index 51% rename from src/app/core/app-store.service.ts rename to src/app/app-store.service.ts index 080905f..f78b1fa 100644 --- a/src/app/core/app-store.service.ts +++ b/src/app/app-store.service.ts @@ -1,9 +1,9 @@ import { Injectable } from '@angular/core'; -import { AboutStoreService } from '../about/about-store.service'; -import { ContactStoreService } from '../contact/contact-store.service'; -import { HeroesStoreService } from '../heroes/heroes-store.service'; -import { TutorialsStoreService } from '../tutorials/tutorials-store.service'; +import { AboutStoreService } from './about/about-store.service'; +import { ContactStoreService } from './contact/contact-store.service'; +import { HeroesStoreService } from './heroes/heroes-store.service'; +import { TutorialsStoreService } from './tutorials/tutorials-store.service'; @Injectable({ providedIn: 'root', diff --git a/src/app/app.module.ts b/src/app/app.module.ts index ecfa34b..e5a111a 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -6,10 +6,10 @@ import { MobxAngularModule } from 'mobx-angular'; import { NgxReduxStatePropsModule } from 'ngx-redux-state-props'; import { AboutStoreService } from './about/about-store.service'; +import { AppStoreService } from './app-store.service'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app.router'; import { ContactStoreService } from './contact/contact-store.service'; -import { AppStoreService } from './core/app-store.service'; import { HeroesStoreService } from './heroes/heroes-store.service'; import { SharedModule } from './shared/shared.module'; import { TutorialsStoreService } from './tutorials/tutorials-store.service'; diff --git a/src/app/contact/form/form.component.ts b/src/app/contact/form/form.component.ts index 2ed6ae5..6244832 100644 --- a/src/app/contact/form/form.component.ts +++ b/src/app/contact/form/form.component.ts @@ -1,7 +1,7 @@ import { Component } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; -import { AppStoreService } from '../../core/app-store.service'; +import { AppStoreService } from '../../app-store.service'; @Component({ selector: 'app-form', From a63728edfb5d7d8c9b0a74fb344a056c7a68e75d Mon Sep 17 00:00:00 2001 From: Bruno Leonardo Michels Date: Fri, 22 Jun 2018 01:10:07 -0300 Subject: [PATCH 6/9] Enforce actions --- src/app/about/about.component.ts | 4 +--- src/app/app-store.service.ts | 5 ++++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/app/about/about.component.ts b/src/app/about/about.component.ts index 6299a52..ea4d6aa 100644 --- a/src/app/about/about.component.ts +++ b/src/app/about/about.component.ts @@ -37,8 +37,6 @@ export class AboutComponent { } updateTitle() { - // tslint:disable-next-line:no-magic-numbers - this.store.about.title = `${Math.random() * 10000}`; - // this.store.about.randomTitle(); + this.store.about.randomTitle(); } } diff --git a/src/app/app-store.service.ts b/src/app/app-store.service.ts index f78b1fa..eaef4b6 100644 --- a/src/app/app-store.service.ts +++ b/src/app/app-store.service.ts @@ -1,4 +1,5 @@ import { Injectable } from '@angular/core'; +import { configure } from 'mobx'; import { AboutStoreService } from './about/about-store.service'; import { ContactStoreService } from './contact/contact-store.service'; @@ -14,5 +15,7 @@ export class AppStoreService { public contact: ContactStoreService, public heroes: HeroesStoreService, public tutorials: TutorialsStoreService, - ) {} + ) { + configure({ enforceActions: 'strict' }); + } } From 14e704e954261492338b2b8d7f89b92189628030 Mon Sep 17 00:00:00 2001 From: Bruno Leonardo Michels Date: Fri, 22 Jun 2018 01:24:30 -0300 Subject: [PATCH 7/9] Remove strict in favor of unit tests --- src/app/app-store.service.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/app/app-store.service.ts b/src/app/app-store.service.ts index eaef4b6..f78b1fa 100644 --- a/src/app/app-store.service.ts +++ b/src/app/app-store.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@angular/core'; -import { configure } from 'mobx'; import { AboutStoreService } from './about/about-store.service'; import { ContactStoreService } from './contact/contact-store.service'; @@ -15,7 +14,5 @@ export class AppStoreService { public contact: ContactStoreService, public heroes: HeroesStoreService, public tutorials: TutorialsStoreService, - ) { - configure({ enforceActions: 'strict' }); - } + ) {} } From 5859e55c5353adf87b074bd61bd60b1e1e7af87e Mon Sep 17 00:00:00 2001 From: Bruno Leonardo Michels Date: Fri, 22 Jun 2018 01:24:55 -0300 Subject: [PATCH 8/9] Add mobx on readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 28ad457..5a24fdf 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,10 @@ Each Pull Request will contain explanation and steps taken to complete a feature ## Installing Frameworks and Libs - [Add Boostrap 4](https://github.com/brunolm/angular-how-to/pull/5) +- [Add Mobx (redux-like)](https://github.com/brunolm/angular-how-to/pull/22) - [Add Redux](https://github.com/brunolm/angular-how-to/pull/14) - [API call in Redux](https://github.com/brunolm/angular-how-to/pull/16) + - [redux tag](https://github.com/brunolm/angular-how-to/tree/redux) ## Routes From 8b0347c9680cfb544ca55eb973bb07cff328a7f4 Mon Sep 17 00:00:00 2001 From: Bruno Leonardo Michels Date: Fri, 22 Jun 2018 19:37:43 -0300 Subject: [PATCH 9/9] Enable strict mode --- src/app/about/about-store.service.ts | 11 ++++++++++- src/app/app.component.ts | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/app/about/about-store.service.ts b/src/app/about/about-store.service.ts index 06d563b..456d7c0 100644 --- a/src/app/about/about-store.service.ts +++ b/src/app/about/about-store.service.ts @@ -5,7 +5,16 @@ import { action, observable } from 'mobx-angular'; providedIn: 'root', }) export class AboutStoreService { - @observable title = 'about:hello world'; + @observable title: string; + + constructor() { + this.initialize(); + } + + @action + private initialize() { + this.title = 'about:hello world'; + } @action randomTitle() { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 0ef9d42..c1648cb 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,6 +1,7 @@ import { NgReduxRouter, routerReducer } from '@angular-redux/router'; import { DevToolsExtension, NgRedux } from '@angular-redux/store'; import { Component } from '@angular/core'; +import { configure } from 'mobx'; import { combineReducers } from 'redux'; import thunk from 'redux-thunk'; @@ -30,6 +31,7 @@ export class AppComponent { this.devTools.isEnabled() ? [this.devTools.enhancer()] : undefined, ); this.ngReduxRouter.initialize(); + configure({ enforceActions: 'strict' }); } createReducer(ReducerService) {