feat(route): adds route-link

This commit is contained in:
Manu Mtz.-Almeida
2018-03-08 01:42:08 +01:00
parent d609a222eb
commit 4a3030f087
9 changed files with 74 additions and 52 deletions

View File

@ -2546,31 +2546,30 @@ declare global {
import { import {
RouteLink as IonRouteLink RouteLink as IonAnchor
} from './components/route-link/route-link'; } from './components/route-link/route-link';
declare global { declare global {
interface HTMLIonRouteLinkElement extends IonRouteLink, HTMLStencilElement { interface HTMLIonAnchorElement extends IonAnchor, HTMLStencilElement {
} }
var HTMLIonRouteLinkElement: { var HTMLIonAnchorElement: {
prototype: HTMLIonRouteLinkElement; prototype: HTMLIonAnchorElement;
new (): HTMLIonRouteLinkElement; new (): HTMLIonAnchorElement;
}; };
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"ion-route-link": HTMLIonRouteLinkElement; "ion-anchor": HTMLIonAnchorElement;
} }
interface ElementTagNameMap { interface ElementTagNameMap {
"ion-route-link": HTMLIonRouteLinkElement; "ion-anchor": HTMLIonAnchorElement;
} }
namespace JSX { namespace JSX {
interface IntrinsicElements { interface IntrinsicElements {
"ion-route-link": JSXElements.IonRouteLinkAttributes; "ion-anchor": JSXElements.IonAnchorAttributes;
} }
} }
namespace JSXElements { namespace JSXElements {
export interface IonRouteLinkAttributes extends HTMLAttributes { export interface IonAnchorAttributes extends HTMLAttributes {
router?: any; href?: string;
url?: string;
} }
} }
} }

View File

@ -1,7 +1,7 @@
import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core';
import { CssClassMap } from '../../index'; import { CssClassMap } from '../../index';
import { BlurEvent, FocusEvent } from '../../utils/input-interfaces'; import { BlurEvent, FocusEvent } from '../../utils/input-interfaces';
import { getButtonClassMap, getElementClassMap } from '../../utils/theme'; import { getButtonClassMap, getElementClassMap, openURL } from '../../utils/theme';
@Component({ @Component({
@ -133,16 +133,16 @@ export class Button {
const attrs = (TagType === 'button') const attrs = (TagType === 'button')
? { type: this.type } ? { type: this.type }
: {}; : { href: this.href };
return ( return (
<TagType <TagType
{...attrs} {...attrs}
class={buttonClasses} class={buttonClasses}
disabled={this.disabled} disabled={this.disabled}
href={this.href}
onFocus={this.onFocus.bind(this)} onFocus={this.onFocus.bind(this)}
onKeyUp={this.onKeyUp.bind(this)} onKeyUp={this.onKeyUp.bind(this)}
onClick={(ev) => openURL(this.href, ev)}
onBlur={this.onBlur.bind(this)}> onBlur={this.onBlur.bind(this)}>
<span class='button-inner'> <span class='button-inner'>
<slot name='icon-only'></slot> <slot name='icon-only'></slot>

View File

@ -1,5 +1,5 @@
import { Component, Element, Listen, Prop, State } from '@stencil/core'; import { Component, Element, Listen, Prop, State } from '@stencil/core';
import { createThemedClasses, getElementClassMap } from '../../utils/theme'; import { createThemedClasses, getElementClassMap, openURL } from '../../utils/theme';
import { CssClassMap } from '../../index'; import { CssClassMap } from '../../index';
@ -104,10 +104,10 @@ export class Item {
const clickable = !!(this.href || this.onclick || this.tappable); const clickable = !!(this.href || this.onclick || this.tappable);
let TagType = 'div'; const TagType = clickable
if (clickable) { ? this.href ? 'a' : 'button'
TagType = this.href ? 'a' : 'button'; : 'div';
}
const attrs = (TagType === 'button') const attrs = (TagType === 'button')
? {type: 'button'} ? {type: 'button'}
: {href: this.href}; : {href: this.href};
@ -125,7 +125,10 @@ export class Item {
this.hasStyleChange = false; this.hasStyleChange = false;
return ( return (
<TagType class={themedClasses} {...attrs}> <TagType
{...attrs}
class={themedClasses}
onClick={(ev) => openURL(this.href, ev)}>
<slot name='start'></slot> <slot name='start'></slot>
<div class='item-inner'> <div class='item-inner'>
<div class='input-wrapper'> <div class='input-wrapper'>

View File

@ -7,24 +7,14 @@
## Properties ## Properties
#### router #### href
any
#### url
string string
## Attributes ## Attributes
#### router #### href
any
#### url
string string

View File

@ -1,12 +1,17 @@
import { Component, Prop } from '@stencil/core'; import { Component, Prop } from '@stencil/core';
import { openURL } from '../../utils/theme';
@Component({ @Component({
tag: 'ion-route-link' tag: 'ion-anchor'
}) })
export class RouteLink { export class RouteLink {
@Prop() url: string;
// The instance of the router @Prop() href: string;
@Prop() router: any;
render() {
return <a
href={this.href}
onClick={(ev) => openURL(this.href, ev)}><slot/></a>;
}
} }

View File

@ -29,6 +29,11 @@ string
boolean boolean
## Methods
#### pushURL()
---------------------------------------------- ----------------------------------------------

View File

@ -1,8 +1,8 @@
import { Component, Element, Listen, Prop } from '@stencil/core'; import { Component, Element, Listen, Method, Prop } from '@stencil/core';
import { Config, DomController } from '../../index'; import { Config, DomController } from '../../index';
import { flattenRouterTree, readRoutes } from './utils/parser'; import { flattenRouterTree, readRoutes } from './utils/parser';
import { readNavState, writeNavState } from './utils/dom'; import { readNavState, writeNavState } from './utils/dom';
import { chainToPath, readPath, writePath } from './utils/path'; import { chainToPath, parsePath, readPath, writePath } from './utils/path';
import { RouteChain } from './utils/interfaces'; import { RouteChain } from './utils/interfaces';
import { routerIDsToChain, routerPathToChain } from './utils/matching'; import { routerIDsToChain, routerPathToChain } from './utils/matching';
@ -42,11 +42,8 @@ export class Router {
this.state++; this.state++;
window.history.replaceState(this.state, document.title, document.location.href); window.history.replaceState(this.state, document.title, document.location.href);
} }
if (!this.busy) {
console.debug('[OUT] hash changed -> write nav state');
this.writeNavStateRoot(); this.writeNavStateRoot();
} }
}
@Listen('body:ionNavChanged') @Listen('body:ionNavChanged')
protected onNavChanged(ev: CustomEvent) { protected onNavChanged(ev: CustomEvent) {
@ -63,21 +60,34 @@ export class Router {
} }
const isPop = ev.detail.isPop === true; const isPop = ev.detail.isPop === true;
this.writePath(chain, isPop); const path = chainToPath(chain);
this.writePath(path, isPop);
}
@Method()
pushURL(url: string) {
this.writePath(parsePath(url), false);
return this.writeNavStateRoot();
} }
private writeNavStateRoot(): Promise<any> { private writeNavStateRoot(): Promise<any> {
const node = document.querySelector('ion-app'); if (this.busy) {
return Promise.resolve();
}
const currentPath = this.readPath(); const currentPath = this.readPath();
if (!currentPath) {
return Promise.resolve();
}
const direction = window.history.state >= this.state ? 1 : -1; const direction = window.history.state >= this.state ? 1 : -1;
if (currentPath) { const node = document.querySelector('ion-app');
const {chain} = routerPathToChain(currentPath, this.routes); const {chain} = routerPathToChain(currentPath, this.routes);
return this.writeNavState(node, chain, direction); return this.writeNavState(node, chain, direction);
} }
return Promise.resolve();
}
private writeNavState(node: any, chain: RouteChain, direction: number): Promise<any> { private writeNavState(node: any, chain: RouteChain, direction: number): Promise<any> {
if (this.busy) {
return Promise.resolve();
}
this.busy = true; this.busy = true;
return writeNavState(node, chain, 0, direction) return writeNavState(node, chain, 0, direction)
.catch(err => console.error(err)) .catch(err => console.error(err))
@ -89,8 +99,7 @@ export class Router {
return readNavState(root); return readNavState(root);
} }
private writePath(chain: RouteChain, isPop: boolean) { private writePath(path: string[], isPop: boolean) {
const path = chainToPath(chain);
this.state = writePath(window.history, this.base, this.useHash, path, isPop, this.state); this.state = writePath(window.history, this.base, this.useHash, path, isPop, this.state);
} }

View File

@ -62,3 +62,14 @@ export function getClassMap(classes: string | undefined): CssClassMap {
return map; return map;
} }
export function openURL(url: string, ev: Event) {
if (url && url.indexOf('://') === -1) {
const router = document.querySelector('ion-router');
if (router) {
ev && ev.preventDefault();
return router.componentOnReady().then(() => router.pushURL(url));
}
}
return Promise.resolve();
}