Skip to content

Instantly share code, notes, and snippets.

@KarolinaCzo
Created August 7, 2018 12:19
Show Gist options
  • Save KarolinaCzo/64111ff1a8b4ecdcac9cbeb1cad70629 to your computer and use it in GitHub Desktop.
Save KarolinaCzo/64111ff1a8b4ecdcac9cbeb1cad70629 to your computer and use it in GitHub Desktop.
'AppTranslationService' with Feature Module Store (dispatchers, actions, reducers) - Angular 2/6
1) In 'main-page-module.ts':
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
// Import Bootstrap
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
// Import components
import { MainPageComponent } from './main-page.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { FooterComponent } from './components/footer/footer.component';
import { JumbotronComponent } from './components/jumbotron/jumbotron.component';
import { AdvertisementsComponent } from './components/advertisements/advertisements.component';
import { RouterModule } from '@angular/router';
// Translate
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
// Import translation service
import { AppTranslateService } from './translation.service';
// Import for reducers to work
import { StoreModule, ActionReducerMap, Action } from '@ngrx/store';
import { reducers, FEATURE_STORE_NAME } from './main-page.reducers';
// Import dispatcher
import { MainPageDispatcher } from './main-page.dispatcher';
// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, '/assets/i18n/main-page/', '.json');
}
@NgModule({
imports: [
CommonModule,
NgbModule.forRoot(),
RouterModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
// Define a feature module Store, give it a name and show where to look for reducers
// Remember about inports!
StoreModule.forFeature(FEATURE_STORE_NAME, reducers)
],
declarations: [
MainPageComponent,
NavbarComponent,
FooterComponent,
JumbotronComponent,
AdvertisementsComponent
],
bootstrap: [MainPageComponent],
exports: [MainPageComponent],
// Add the AppTranslationService and MainPageDispatcher to providers
providers: [AppTranslateService, MainPageDispatcher]
})
export class MainPageModule {}
2) In 'navbar.component.ts':
import { Component, OnInit, HostListener } from '@angular/core';
// Import translate service
import { AppTranslateService } from '../../translation.service';
// Import Store
import { Store } from '@ngrx/store';
// Import dispatcher
import { MainPageDispatcher } from '../../main-page.dispatcher';
// Import State from reducers
import { MainPageState, getLanguage } from '../../main-page.reducers';
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent {
constructor(
private translateService: AppTranslateService,
private store: Store<MainPageState>, // Pass the component state
private dispatcher: MainPageDispatcher
) {}
// Listen to clicks on language icons
onLanguageChange(language: string) {
this.dispatcher.changeLanguage(language);
}
// Listen to 'window:scroll' event for window level scrolling.
@HostListener('window:scroll', ['$event'])
onWindowScroll($event: any) {
const navbar = document.getElementById('navbar');
// Check if the page offset is grater than 0 and if 'navbar' isn't 'null'.
if (window.pageYOffset > 0 && navbar) {
// Stick the 'navbar' to the top of the page.
navbar.style.top = '0';
}
}
}
3) In 'main-page.dispatcher.ts':
// Import store
import { Store } from '@ngrx/store';
// Import State from reducers
import { MainPageState } from './main-page.reducers';
// Import Injectable
import { Injectable } from '@angular/core';
// Import Actions from actions
import { ChangeLanguageAction } from './main-page.actions';
@Injectable()
export class MainPageDispatcher {
constructor(private store: Store<MainPageState>) {}
changeLanguage(language: string) {
this.store.dispatch(new ChangeLanguageAction(language));
}
}
4) In 'main-page.actions.ts':
import { Action } from '@ngrx/store';
// Create variables to be sure that the names of actions are always the same
export const LANGUAGE_CHANGE = 'LANGUAGE_CHANGE';
// Create actions
export class ChangeLanguageAction implements Action {
readonly type = LANGUAGE_CHANGE;
constructor(public payload: string) {}
}
export type MainPageActions = ChangeLanguageAction;
5) In 'main-page.reducers.ts':
// Import for reducers to work
import {
StoreModule,
ActionReducerMap,
Action,
ActionReducer,
createFeatureSelector,
createSelector
} from '@ngrx/store';
// Import actions
import { LANGUAGE_CHANGE, ChangeLanguageAction } from './main-page.actions';
// Define the feature module name as const to avoid mistakes
export const FEATURE_STORE_NAME = 'main-page';
// Define a feature state
export interface MainPageState {
language: string;
}
// Create a feature state selector
export const selectFeature = createFeatureSelector<MainPageState>(
FEATURE_STORE_NAME
);
// Create a selector for the counter (to update it)
export const getLanguage = createSelector(
selectFeature,
state => state.language
);
// Create a reducer
export const MainPageReducer: ActionReducer<string, ChangeLanguageAction> = (
state: string = 'de',
action: ChangeLanguageAction
) => {
switch (action.type) {
case LANGUAGE_CHANGE:
state = action.payload;
return state;
default:
return state;
}
};
// Update the language with the curent state
export const reducers: ActionReducerMap<MainPageState, ChangeLanguageAction> = {
language: MainPageReducer
};
6) In 'translation.service.ts':
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
// Import translate service
import { TranslateService } from '@ngx-translate/core';
// Import Observable
import { Observable } from 'rxjs';
// Import reducers
import { Store } from '@ngrx/store';
import { MainPageState, getLanguage } from './main-page.reducers';
@Injectable()
export class AppTranslateService {
// Create an Observable to listen for language change
private language$: Observable<string>;
constructor(
private translate: TranslateService,
private store: Store<MainPageState>
) {
translate.addLangs(['de', 'en']);
translate.setDefaultLang('de');
this.language$ = this.store.select(getLanguage);
this.language$.subscribe(value => {
this.translate.use(value);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment