Reputation: 680
I want to add some method to existed class that come from library.
Known some basic type like String
, Element
can extension via interface
and add it's prototype
.
interface String {
extFunc():Function;
}
String.prototype.extFunc = function () {
//blabla
};
"a".extFunc();
I also find the way to add extension method of Observable<T>
.
declare module 'rxjs/Observable' {
interface Observable<T> {
foo: String;
}
}
Observable.prototype.foo= "bar";
console.log(Observable.of("a").foo);
But when i try to do same thing to NavController(an lib from ionic), it will override entire NavController to the interface that i declare.
declare module 'ionic-angular' {
interface NavController {
replace(page: Page): Promise<any>;
}
}
navCtrl.replace(...); //ok
navCtrl.push(...); //original function => "not exist"
Does anyone know what is best way to add extension method to those class? thanks~
Edit: There is actual code
import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
import {GuidePage} from '../guide/guide.component';
@Component({
selector: 'page-home',
templateUrl: 'home.component.html'
})
export class HomePage {
pageName = "home";
// navCtrl is come from angular2's Dependency Injection,
// it may not suitable to extend NavController
constructor(public navCtrl: NavController) {}
gotoGuide(): void {
//wanna replace this
this.navCtrl.push(GuidePage).then(() => {
let index = this.navCtrl.getActive().index;
this.navCtrl.remove(index - 1);
});
//with this custom extension method
//this.navCtrl.replace(GuidePage);
}
}
Upvotes: 8
Views: 5595
Reputation: 680
Ok, I reference to this answer and solve my question with the following code.
In polyfill.ts
import {Page} from 'ionic-angular/navigation/nav-util';
// the class we wanna create extension method
import {NavController} from 'ionic-angular/navigation/nav-controller';
// ionic provide this as NavController
import {NavControllerBase} from 'ionic-angular/navigation/nav-controller-base';
// add extension method on both class via interface
declare module "ionic-angular/navigation/nav-controller" {
interface NavController {
// replacePage?: typeof replacePage;
replacePage(page: Page, data?: any);
}
}
declare module "ionic-angular/navigation/nav-controller-base" {
interface NavControllerBase {
// replacePage?: typeof replacePage;
replacePage(page: Page, data?: any);
}
}
// define extension method
function replacePage(this: NavController, page: Page, data?: any): Promise<any> {
return this.push(page, data).then(() => {
let index = this.getActive().index;
this.remove(index - 1);
});
}
// finally add this function to the class that ionic provide
NavControllerBase.prototype.replacePage = replacePage;
usage:
constructor(private navCtrl: NavController)
foo(){
this.navCtrl.replacePage(HomePage, {nextPage: OtherPage});
}
This way to add extension method on other class, wish this help someone after.
Upvotes: 7
Reputation: 28128
Your question is how to extend a class, but your code shows interfaces.
How to extend a class from a library:
class LibraryThing {
// this is a class from a library
doSomething(){
}
}
class MyThing extends LibraryThing {
// here you can add your own methods to the existing class
doMyThing(){
}
}
Now you can create a MyThing instance which will have all the library methods and your own methods:
let t = new MyThing();
t.doSomething();
t.doMyThing();
If you want to use interfaces you can simply implement them. You can implement existing library interfaces and complement that with your own interfaces
interface LibraryInterface {}
interface MyOwnInterface {}
class CoolThing implements LibraryInterface, MyOwnInterface {
// this class uses methods from the library interface and your own
}
You do not need prototype when working with typescript.
EDIT
I have not tried if this works, but instead of passing the navcontroller in the constructor, you can pass your own class that extends navcontroller.
import {Component} from '@angular/core';
import {CustomController} from '../mystuff/customcontroller';
import {GuidePage} from '../guide/guide.component';
@Component({
selector: 'page-home',
templateUrl: 'home.component.html'
})
export class HomePage {
pageName = "home";
// here we receive our own CustomController
constructor(public navCtrl: CustomController) {}
gotoGuide(): void {
this.navCtrl.myOwnCustomStuff();
}
}
In CustomController you can import Navcontroller and extend it:
import { Injectable } from '@angular/core'
import {NavController} from 'ionic-angular'
@injectable()
export class CustomController extends NavController {
}
I haven't tested if this is allowed for an ionic component though!
You also have to register your own new injectable as a provider for angular DI, follow the steps in your link
Upvotes: 1