Typescript and multiple classes
I have a component class like EventSchedulePage
. It extends the class HandleStorageService
abstract
as shown below. You can see that this subclass has a method named showInvalidTokenAlert()
. I need to call this method every and every component (this method gives the user an error message on the token). So can you tell me how to implement or redesign my classes to suit this situation? because I don't like to put showInvalidTokenAlert()
for every component. I would like to keep the implementation of this method in one place.
Subclass
export class EventSchedulePage extends HandleStorageService {
constructor() {
super();
}
showInvalidTokenAlert() {
//show alert
}
}
abstract class
export abstract class HandleStorageService {
result: string = '';
constructor() {
}
}
source to share
You can create BasePage
and place all common code there.
import { Component, Injector } from '@angular/core';
import { AlertController, ...} from 'ionic-angular';
@Component({ selector: '', template: '<span></span>' })
export class BasePage {
private _alertCtrl: AlertController;
private _toastCtrl: ToastController;
constructor(public injector: Injector) { }
// Get methods used to obtain instances from the injector just once
// ----------------------------------------------------------------
// AlertController
public get alertCtrl(): AlertController {
if (!this._alertCtrl) {
this._alertCtrl = this.injector.get(AlertController);
}
return this._alertCtrl;
}
// ToastController
public get toastCtrl(): ToastController {
if (!this._toastCtrl) {
this._toastCtrl = this.injector.get(ToastController);
}
return this._toastCtrl;
}
// ...
// Helper methods
// ----------------------------------------------------------------
public showAlertMessage(message: string): void {
let alert = this.alertCtrl.create({ ... });
alert.present();
}
public showToastMessage(message: string): void {
let toast = this.toastCtrl.create({ ... });
toast.onDidDismiss(() => {
console.log('Dismissed toast');
});
toast.present();
}
}
The key is what BasePage
gets the injector instance from the subclass, so you can get whatever instance you want from it (like the instance AlertController
you need to show a warning message). Using get methods, each instance will be fetched from the injector only once.
And then on all pages of your application:
import { Component, Injector } from '@angular/core';
import { BasePage } from '../path/to/base';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage extends BasePage {
constructor(public injector: Injector) {
super(injector);
}
public someMethod(): void {
// You can use the methods from the BasePage!
this.showAlertMessage('Your message...');
}
public someOtherMethod(): void {
this.showToastMessage('Another message');
}
}
It's very easy to add a few more helper methods this way.
source to share
You can create a separate provider class using the function showInvalidTokenAlert()
@Injectable()
export class AlertProvider{
constructor(){}
showInvalidTokenAlert(){
//...
}
}
Set it to app.module.ts as provider if you want to use singleton
@ngModule({
//...
providers:[
AlertProvider,
//..
]
})
Input to any component you need.
export class EventSchedulePage extends HandleStorageService {
constructor(private alertProvider:AlertProvider) {
super();
}
//call this.alertProvider.showInvalidTokenAlert()
}
source to share
Hmm .. It seems there is no anti-pattern? I mean using a service layer to handle the UI? This is why I tried to find a TS based solution. What do you think of this? - Sampat
It's definitely more MVCS-like (Model-View-Controller-Service) to handle this in a controller. But this is a widely accepted approach .
If you want to go for this @ suraj's answer is my personal recommendation.
Handling warnings on the controller is certainly possible. Read on.
event-schedule-page.service.ts
export class EventSchedulePage extends HandleStorageService {
// ...
foo() {
if (!bar) {
throw new Error('Something went wrong.');
}
// ...
}
}
home.controller.ts
export class HomeController {
// ...
foo() {
try {
eventSchedulePageService.foo();
} catch (error) {
window.alert(error); // Handle and UI display the error on the controller.
}
}
}
To keep track of, you can use custom error classes or separate functions to throw / handle your errors.
source to share