How to get the instance of current page on elsewhere in project
Since routing is very important for mobile applications, Smartface Router provides many different useful features for easily navigating&communicating between different screens.
Recommended way
In this example, we pass the current page instance to the Menu
component. Menu component will use the instance to show menu and its items.
- Page
- Menu
import PageInstanceExampleDesign from 'generated/pages/pageInstanceExample';
import { withDismissAndBackButton } from '@smartface/mixins';
import { Router, Route } from '@smartface/router';
import { initMenu } from 'lib/menu';
export default class PageInstanceExample extends withDismissAndBackButton(PageInstanceExampleDesign) {
constructor(private router?: Router, private route?: Route) {
super({});
}
/**
* @event onShow
* This event is called when the page appears on the screen (everytime).
*/
onShow() {
super.onShow();
this.initBackButton(this.router); //Addes a back button to the page headerbar.
initMenu(this); // setting page instance to menu
}
/**
* @event onLoad
* This event is called once when the page is created.
*/
onLoad() {
super.onLoad();
}
}
import Menu from '@smartface/native/ui/menu';
import MenuItem from '@smartface/native/ui/menuitem';
import Page from '@smartface/native/ui/page';
export function initMenu(page: Page) {
const myMenu = new Menu();
myMenu.headerTitle = 'My Menu Title';
const menuItem1 = new MenuItem({
title: 'Menu Item 1',
onSelected: function () {
console.log('menu item 1 clicked');
}
});
const menuItem2 = new MenuItem({
title: 'Menu Item 2',
onSelected: function () {
console.log('menu item 2 clicked');
}
});
myMenu.items = [menuItem1, menuItem2];
myMenu.show(page); // page instance
Alternative way using router state (not recommended)
To get your application's current working page instance from elsewhere in your project, you can use the currentRouter object from the Router.
import { NativeRouter } from "@smartface/router";
const page: Page1 = NativeRouter.currentRouter.getState().view;
// this might be undefined so it's a good idea to type guard it.
To make it work, you have to set the page
instance to the every router state .
Route.of<Pages.yourPage>({
path: `${basePath}/yourPage`,
build(router, route) {
const page = new Pages.yourPage(router, route);
router.setState({ view: page });
return page;
}
}),
Here is a sample usage where you can use the currentRouter object of the Router. In this sample, we get the current working page instance when declaring an event listener for the Application's ReceivedNotification event on app.ts file. So it gives us the ability to reach methods & properties of that page itself (e.g. display a popup for an incoming notification on the page).
import PageWithNotifier from "pages/pageWithNotifier";
import Application from "@smartface/native/application";
import { NativeRouter } from "@smartface/router";
// ... rest of your code
Application.on('receivedNotification', () => {
const activePage = NativeRouter.currentRouter.getState().view;
if (activePage instanceof PageWithNotifier) {
activePage.showPopup();
}
// By this way, you can reach any of the properties
// or methods of the active page instance. Including life-cycle methods
});
- Example 1 - Setting Page ID
- Example 2 - Image picker from gallery
In this example, we are using the currentRouter object of the Router to get the current working page instance for setting the unique Page ID
export function setID(uniqueKey: string): void {
//@ts-ignore
const pageName = Router.currentRouter.getState().view?.pageName;
if (!pageName) return;
const id = removeSpaces(pageName + '/' + uniqueKey);
}
function removeSpaces(str: string) {
return str.replace(/ /g, '');
}
In this example, we set the page instance to the page
property.
page: Router.currentRouter.getState().view
export const onGallerySelect = (opts: IPhotoEdit = {}) => {
const permission = System.android.apiLevel < 33 ?
Permissions.ANDROID.READ_EXTERNAL_STORAGE :
[Permissions.ANDROID.READ_MEDIA_IMAGES, Permissions.ANDROID.READ_MEDIA_VIDEO];
return Permission.android.requestPermissions(permission).then((e) => {
return new Promise((resolve, reject) => {
const pickFromGalleryOpts = {
type: Multimedia.Type.IMAGE,
allowsEditing: !opts.blockAllowsEditing,
onSuccess: ({ image }) => {
return compressImage(image, opts)
.then((base64) => resolve(base64))
.catch(reject);
},
onCancel: () => {
Contacts.onActivityResult = contactActivity;
reject();
},
onFailure: reject,
android: {
cropShape:
opts.cropShape === 'RECTANGLE' ? Multimedia.Android.CropShape.RECTANGLE : Multimedia.Android.CropShape.OVAL,
rotateText: 'Rotate',
scaleText: 'Stretch',
cropText: 'Crop',
headerBarTitle: 'Photo Edit',
hideBottomControls: false
},
page: Router.currentRouter.getState().view
};
!opts.freeAspectRatio && (pickFromGalleryOpts['aspectRatio'] = { x: 1, y: 1 });
!opts.freeMaxResultSize &&
(pickFromGalleryOpts['android']['maxResultSize'] = {
width: PROFILE_IMAGE_DIMENSIONS.WIDTH,
height: PROFILE_IMAGE_DIMENSIONS.HEIGHT
});
return Multimedia.pickFromGallery(pickFromGalleryOpts);
});
});
};
interface IPhotoEdit {
resizeRateMultiplier?: number; //Divides the height and width with this value
compressionRate?: number;
blockAllowsEditing?: boolean;
freeAspectRatio?: boolean;
freeMaxResultSize?: boolean;
maximumWidth?: number;
cropShape?: string; //"OVAL" | "RECTANGLE" => Multimedia.Android.CropShape.OVAL | Multimedia.Android.CropShape.RECTANGLE;
}