@web-atoms/core
Version:
165 lines (126 loc) • 4.69 kB
text/typescript
import { App } from "../../App";
import { BindableProperty } from "../../core/BindableProperty";
import { CancelToken, IClassOf } from "../../core/types";
import XNode from "../../core/XNode";
import { IPageOptions, NavigationService } from "../../services/NavigationService";
import AtomPageLinkStyle from "../styles/AtomPageLinkStyle";
import { AtomStyle } from "../styles/AtomStyle";
import { IStyleDeclaration } from "../styles/IStyleDeclaration";
import { AtomControl } from "./AtomControl";
export class AtomPageLink extends AtomControl {
public static page = XNode.prepare("page", true, true);
public page: string | IClassOf<AtomControl>;
public parameters: any;
public isOpen: boolean;
public cancelToken: CancelToken;
public options: IPageOptions;
/**
* Fired after the result was received from popup/window successfully
*/
public eventResult: any;
/**
* Fired after popup/window was cancelled
*/
public eventError: any;
/**
* Fired before opening popup/window.
* In the event's detail object, you must set parameters property as shown below...
* eventGetParameters={Bind.event((e) => e.detail.parameters = ({}))}
*/
public eventGetParameters: any;
/**
* Block opening Popup/Page again till the opened page is closed or cancelled.
* If set true, toggle will not work. Default is false.
*/
public modal: boolean;
/**
* Setting Toggle (default true) true will close the already opened Popup/window, otherwise it will
* open a new window if Modal is false.
*/
public toggle: boolean;
constructor(app: App, e?: HTMLElement) {
super(app, e || document.createElement("span"));
}
public preCreate(): void {
this.page = null;
this.parameters = null;
this.isOpen = false;
this.options = null;
this.modal = false;
this.toggle = true;
this.defaultControlStyle = AtomPageLinkStyle;
super.preCreate();
this.bindEvent(
this.element,
"click",
() => {
if (this.modal) {
return this.openPopup();
}
return this.app.runAsync(() => this.openPopup());
});
this.bind(
this.element,
"styleClass",
[["this", "isOpen"]],
false ,
(v) => ({
[this.controlStyle.name]: 1,
"is-open": v,
"atom-page-link": 1
}),
this);
this.registerDisposable({
dispose: () => {
const ct = this.cancelToken;
if (ct) {
ct.cancel();
}
}
});
}
protected async openPopup(): Promise<void> {
if (this.cancelToken) {
if (this.toggle) {
this.cancelToken.cancel();
this.cancelToken = null;
this.isOpen = false;
return;
} else {
this.cancelToken.dispose();
}
}
this.cancelToken = new CancelToken();
let o: IPageOptions = null;
try {
const navigationService = this.app.resolve(NavigationService) as NavigationService;
const pt = this.page;
if (!pt) {
// tslint:disable-next-line:no-console
console.error("No popup template specified in PopupButton");
return;
}
this.isOpen = true;
o = this.options ?
{ ... this.options, cancelToken: this.cancelToken } :
{ cancelToken: this.cancelToken };
o.onInit = (view: AtomControl) => {
view.setLocalValue(view.element, "styleClass", `${this.controlStyle.name} page` );
};
const getParametersEvent = new CustomEvent("getParameters", { detail: {} as any});
this.element.dispatchEvent(getParametersEvent);
const p = getParametersEvent.detail.parameters || this.parameters;
const result = await navigationService.openPage(pt, p, o);
this.element.dispatchEvent(new CustomEvent("result", { detail: result }));
} catch (e) {
// if element is disposed or null, ignore
if (this.element) {
this.element.dispatchEvent(new CustomEvent("error", { detail: e }));
}
} finally {
this.cancelToken = null;
this.isOpen = false;
if (o) { o.onInit = null; }
}
}
}