Skip to content

Commit

Permalink
fix(angular): tabs flickering
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Apr 3, 2018
1 parent 11cb42f commit 7e97006
Show file tree
Hide file tree
Showing 8 changed files with 11,989 additions and 22 deletions.
2 changes: 1 addition & 1 deletion angular/src/directives/navigation/href-delegate.ts
Expand Up @@ -22,7 +22,7 @@ export class HrefDelegate {
@HostListener('click', ['$event'])
onClick(ev: Event) {
const url = this.href;
if (this.router && url && url[0] !== '#' && url.indexOf('://') === -1) {
if (this.router && url != null && url[0] !== '#' && url.indexOf('://') === -1) {
ev.preventDefault();
this.router.navigateByUrl(url);
}
Expand Down
11 changes: 9 additions & 2 deletions angular/src/directives/navigation/ion-back-button.ts
@@ -1,4 +1,4 @@
import { Directive, HostListener, Input, Optional } from '@angular/core';
import { Directive, ElementRef, HostListener, Input, Optional } from '@angular/core';
import { IonRouterOutlet } from './ion-router-outlet';
import { Router } from '@angular/router';

Expand All @@ -7,11 +7,18 @@ import { Router } from '@angular/router';
})
export class IonBackButton {

@Input() defaultHref: string;
@Input()
set defaultHref(value: string) {
this.elementRef.nativeElement.defaultHref = value;
}
get defaultHref() {
return this.elementRef.nativeElement.defaultHref;
}

constructor(
@Optional() private router: Router,
@Optional() private routerOutlet: IonRouterOutlet,
private elementRef: ElementRef,
) {}

@HostListener('click')
Expand Down
1 change: 1 addition & 0 deletions angular/src/directives/navigation/router-controller.ts
Expand Up @@ -93,6 +93,7 @@ export class StackController {
await containerEl.commit(enteringEl, leavingEl, {
duration: direction === 0 ? 0 : undefined,
direction: direction === -1 ? NavDirection.Back : NavDirection.Forward,
deepWait: true,
showGoBack
});
}
Expand Down
14 changes: 7 additions & 7 deletions angular/src/directives/proxies.ts
Expand Up @@ -15,7 +15,7 @@ export function inputs(instance: any, el: ElementRef, props: string[]) {
});
}

const accept = 'accept', activated = 'activated', active = 'active', allowEmptySelection = 'allowEmptySelection', animated = 'animated', autoHide = 'autoHide', autocapitalize = 'autocapitalize', autocomplete = 'autocomplete', autocorrect = 'autocorrect', autofocus = 'autofocus', btnId = 'btnId', button = 'button', buttonType = 'buttonType', cancelButtonText = 'cancelButtonText', cancelText = 'cancelText', checked = 'checked', clearInput = 'clearInput', clearOnEdit = 'clearOnEdit', closeDuration = 'closeDuration', color = 'color', cols = 'cols', component = 'component', componentProps = 'componentProps', contentId = 'contentId', dayNames = 'dayNames', dayShortNames = 'dayShortNames', dayValues = 'dayValues', debounce = 'debounce', defaultHref = 'defaultHref', delegate = 'delegate', detail = 'detail', disabled = 'disabled', displayFormat = 'displayFormat', doneText = 'doneText', dualKnobs = 'dualKnobs', duration = 'duration', edge = 'edge', expand = 'expand', expandable = 'expandable', fill = 'fill', fixed = 'fixed', floating = 'floating', forceOverscroll = 'forceOverscroll', fullscreen = 'fullscreen', goBack = 'goBack', header = 'header', horizontal = 'horizontal', hourValues = 'hourValues', href = 'href', icon = 'icon', inputmode = 'inputmode', interfaceOptions = 'interfaceOptions', ionBlur = 'ionBlur', ionCancel = 'ionCancel', ionChange = 'ionChange', ionClear = 'ionClear', ionClick = 'ionClick', ionClose = 'ionClose', ionDrag = 'ionDrag', ionFocus = 'ionFocus', ionInfinite = 'ionInfinite', ionInput = 'ionInput', ionInputDidLoad = 'ionInputDidLoad', ionInputDidUnload = 'ionInputDidUnload', ionMenuChange = 'ionMenuChange', ionNavDidChange = 'ionNavDidChange', ionNavWillChange = 'ionNavWillChange', ionOpen = 'ionOpen', ionPull = 'ionPull', ionRadioDidLoad = 'ionRadioDidLoad', ionRadioDidUnload = 'ionRadioDidUnload', ionRefresh = 'ionRefresh', ionScroll = 'ionScroll', ionScrollEnd = 'ionScrollEnd', ionScrollStart = 'ionScrollStart', ionSelect = 'ionSelect', ionSelectOptionDidLoad = 'ionSelectOptionDidLoad', ionSelectOptionDidUnload = 'ionSelectOptionDidUnload', ionSlideDidChange = 'ionSlideDidChange', ionSlideDrag = 'ionSlideDrag', ionSlideNextEnd = 'ionSlideNextEnd', ionSlideNextStart = 'ionSlideNextStart', ionSlidePrevEnd = 'ionSlidePrevEnd', ionSlidePrevStart = 'ionSlidePrevStart', ionSlideReachEnd = 'ionSlideReachEnd', ionSlideReachStart = 'ionSlideReachStart', ionSlideTouchEnd = 'ionSlideTouchEnd', ionSlideTouchStart = 'ionSlideTouchStart', ionSlideTransitionEnd = 'ionSlideTransitionEnd', ionSlideTransitionStart = 'ionSlideTransitionStart', ionSlideWillChange = 'ionSlideWillChange', ionSplitPaneVisible = 'ionSplitPaneVisible', ionStart = 'ionStart', ionStyle = 'ionStyle', ionSwipe = 'ionSwipe', loadingSpinner = 'loadingSpinner', loadingText = 'loadingText', max = 'max', maxEdgeStart = 'maxEdgeStart', maxlength = 'maxlength', mediaQuery = 'mediaQuery', menu = 'menu', menuId = 'menuId', message = 'message', min = 'min', minlength = 'minlength', minuteValues = 'minuteValues', mode = 'mode', monthNames = 'monthNames', monthShortNames = 'monthShortNames', monthValues = 'monthValues', multiple = 'multiple', name = 'name', okText = 'okText', options = 'options', or = 'or', orientation = 'orientation', pager = 'pager', pattern = 'pattern', paused = 'paused', persistent = 'persistent', pickerFormat = 'pickerFormat', pickerOptions = 'pickerOptions', pin = 'pin', placeholder = 'placeholder', platform = 'platform', position = 'position', pullMax = 'pullMax', pullMin = 'pullMin', pullingIcon = 'pullingIcon', pullingText = 'pullingText', readonly = 'readonly', refreshingSpinner = 'refreshingSpinner', refreshingText = 'refreshingText', required = 'required', results = 'results', root = 'root', rootParams = 'rootParams', round = 'round', rows = 'rows', scrollEnabled = 'scrollEnabled', scrollEvents = 'scrollEvents', scrollable = 'scrollable', selected = 'selected', selectedText = 'selectedText', show = 'show', showCancelButton = 'showCancelButton', side = 'side', size = 'size', snapbackDuration = 'snapbackDuration', snaps = 'snaps', spellcheck = 'spellcheck', stacked = 'stacked', step = 'step', strong = 'strong', subHeader = 'subHeader', swipeBackEnabled = 'swipeBackEnabled', swipeEnabled = 'swipeEnabled', tabBadge = 'tabBadge', tabBadgeStyle = 'tabBadgeStyle', tabIcon = 'tabIcon', tabTitle = 'tabTitle', tabbarHidden = 'tabbarHidden', tabbarHighlight = 'tabbarHighlight', tabbarLayout = 'tabbarLayout', tabbarPlacement = 'tabbarPlacement', tabsHideOnSubPages = 'tabsHideOnSubPages', text = 'text', threshold = 'threshold', toggleActive = 'toggleActive', translucent = 'translucent', type = 'type', url = 'url', useRouter = 'useRouter', useTapClick = 'useTapClick', value = 'value', vertical = 'vertical', when = 'when', width = 'width', wrap = 'wrap', yearValues = 'yearValues';
const accept = 'accept', activated = 'activated', active = 'active', allowEmptySelection = 'allowEmptySelection', animated = 'animated', autoHide = 'autoHide', autocapitalize = 'autocapitalize', autocomplete = 'autocomplete', autocorrect = 'autocorrect', autofocus = 'autofocus', badge = 'badge', badgeStyle = 'badgeStyle', btnId = 'btnId', button = 'button', buttonType = 'buttonType', cancelButtonText = 'cancelButtonText', cancelText = 'cancelText', checked = 'checked', clearInput = 'clearInput', clearOnEdit = 'clearOnEdit', closeDuration = 'closeDuration', color = 'color', cols = 'cols', component = 'component', componentProps = 'componentProps', contentId = 'contentId', dayNames = 'dayNames', dayShortNames = 'dayShortNames', dayValues = 'dayValues', debounce = 'debounce', defaultHref = 'defaultHref', delegate = 'delegate', detail = 'detail', disabled = 'disabled', displayFormat = 'displayFormat', doneText = 'doneText', dualKnobs = 'dualKnobs', duration = 'duration', edge = 'edge', expand = 'expand', expandable = 'expandable', fill = 'fill', fixed = 'fixed', floating = 'floating', forceOverscroll = 'forceOverscroll', fullscreen = 'fullscreen', goBack = 'goBack', header = 'header', horizontal = 'horizontal', hourValues = 'hourValues', href = 'href', icon = 'icon', inputmode = 'inputmode', interfaceOptions = 'interfaceOptions', ionBlur = 'ionBlur', ionCancel = 'ionCancel', ionChange = 'ionChange', ionClear = 'ionClear', ionClick = 'ionClick', ionClose = 'ionClose', ionDrag = 'ionDrag', ionFocus = 'ionFocus', ionInfinite = 'ionInfinite', ionInput = 'ionInput', ionInputDidLoad = 'ionInputDidLoad', ionInputDidUnload = 'ionInputDidUnload', ionMenuChange = 'ionMenuChange', ionNavDidChange = 'ionNavDidChange', ionNavWillChange = 'ionNavWillChange', ionOpen = 'ionOpen', ionPull = 'ionPull', ionRadioDidLoad = 'ionRadioDidLoad', ionRadioDidUnload = 'ionRadioDidUnload', ionRefresh = 'ionRefresh', ionScroll = 'ionScroll', ionScrollEnd = 'ionScrollEnd', ionScrollStart = 'ionScrollStart', ionSelect = 'ionSelect', ionSelectOptionDidLoad = 'ionSelectOptionDidLoad', ionSelectOptionDidUnload = 'ionSelectOptionDidUnload', ionSlideDidChange = 'ionSlideDidChange', ionSlideDrag = 'ionSlideDrag', ionSlideNextEnd = 'ionSlideNextEnd', ionSlideNextStart = 'ionSlideNextStart', ionSlidePrevEnd = 'ionSlidePrevEnd', ionSlidePrevStart = 'ionSlidePrevStart', ionSlideReachEnd = 'ionSlideReachEnd', ionSlideReachStart = 'ionSlideReachStart', ionSlideTouchEnd = 'ionSlideTouchEnd', ionSlideTouchStart = 'ionSlideTouchStart', ionSlideTransitionEnd = 'ionSlideTransitionEnd', ionSlideTransitionStart = 'ionSlideTransitionStart', ionSlideWillChange = 'ionSlideWillChange', ionSplitPaneVisible = 'ionSplitPaneVisible', ionStart = 'ionStart', ionStyle = 'ionStyle', ionSwipe = 'ionSwipe', label = 'label', loadingSpinner = 'loadingSpinner', loadingText = 'loadingText', max = 'max', maxEdgeStart = 'maxEdgeStart', maxlength = 'maxlength', mediaQuery = 'mediaQuery', menu = 'menu', menuId = 'menuId', message = 'message', min = 'min', minlength = 'minlength', minuteValues = 'minuteValues', mode = 'mode', monthNames = 'monthNames', monthShortNames = 'monthShortNames', monthValues = 'monthValues', multiple = 'multiple', name = 'name', okText = 'okText', options = 'options', or = 'or', orientation = 'orientation', pager = 'pager', pattern = 'pattern', paused = 'paused', persistent = 'persistent', pickerFormat = 'pickerFormat', pickerOptions = 'pickerOptions', pin = 'pin', placeholder = 'placeholder', platform = 'platform', position = 'position', pullMax = 'pullMax', pullMin = 'pullMin', pullingIcon = 'pullingIcon', pullingText = 'pullingText', readonly = 'readonly', refreshingSpinner = 'refreshingSpinner', refreshingText = 'refreshingText', required = 'required', results = 'results', root = 'root', rootParams = 'rootParams', round = 'round', rows = 'rows', scrollEnabled = 'scrollEnabled', scrollEvents = 'scrollEvents', scrollable = 'scrollable', selected = 'selected', selectedText = 'selectedText', show = 'show', showCancelButton = 'showCancelButton', side = 'side', size = 'size', snapbackDuration = 'snapbackDuration', snaps = 'snaps', spellcheck = 'spellcheck', stacked = 'stacked', step = 'step', strong = 'strong', subHeader = 'subHeader', swipeBackEnabled = 'swipeBackEnabled', swipeEnabled = 'swipeEnabled', tabbarHidden = 'tabbarHidden', tabbarHighlight = 'tabbarHighlight', tabbarLayout = 'tabbarLayout', tabbarPlacement = 'tabbarPlacement', tabsHideOnSubPages = 'tabsHideOnSubPages', text = 'text', threshold = 'threshold', toggleActive = 'toggleActive', translucent = 'translucent', type = 'type', url = 'url', useRouter = 'useRouter', useTapClick = 'useTapClick', value = 'value', vertical = 'vertical', when = 'when', width = 'width', wrap = 'wrap', yearValues = 'yearValues';

@NgDirective({ selector: 'ion-app' })
export class App {
Expand All @@ -32,7 +32,7 @@ export class BackButton {
*/
@NgInput() mode: any;
/**
* The text property is used to provide custom text for the back button while using the default look-and-feel
* The text property is used to provide custom text for the back button while using the default look-and-feel.
*/
@NgInput() text: any;
@NgInput() icon: string;
Expand Down Expand Up @@ -1433,23 +1433,23 @@ export class Tab {
/**
* The title of the tab.
*/
@NgInput() tabTitle: string;
@NgInput() label: string;
/**
* The URL which will be used as the `href` within this tab's `<ion-tab-button>` anchor.
*/
@NgInput() href: string;
/**
* The icon for the tab.
*/
@NgInput() tabIcon: string;
@NgInput() icon: string;
/**
* The badge for the tab.
*/
@NgInput() tabBadge: string;
@NgInput() badge: string;
/**
* The badge color for the tab button.
*/
@NgInput() tabBadgeStyle: string;
@NgInput() badgeStyle: string;
/**
* The component to display inside of the tab.
*/
Expand All @@ -1476,7 +1476,7 @@ export class Tab {
@NgInput() tabsHideOnSubPages: boolean;
@NgOutput() ionSelect: NgEventEmitter<any>;
constructor(el: ElementRef) {
inputs(this, el, [active, btnId, delegate, tabTitle, href, tabIcon, tabBadge, tabBadgeStyle, component, name, disabled, selected, show, tabsHideOnSubPages]);
inputs(this, el, [active, btnId, delegate, label, href, icon, badge, badgeStyle, component, name, disabled, selected, show, tabsHideOnSubPages]);
outputs(this, [ionSelect]);
}
}
Expand Down
11,942 changes: 11,941 additions & 1 deletion core/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions core/src/components/router-outlet/route-outlet.tsx
Expand Up @@ -80,6 +80,7 @@ export class RouterOutlet implements NavOutlet {
direction: opts.direction,
duration: opts.duration,
easing: opts.easing,
deepWait: opts.deepWait,

animationCtrl: this.animationCtrl,
showGoBack: opts.showGoBack,
Expand Down Expand Up @@ -139,5 +140,6 @@ export interface RouterOutletOptions {
easing?: string;
showGoBack?: boolean;
direction?: NavDirection;
deepWait?: boolean;
mode?: 'md' | 'ios';
}
7 changes: 7 additions & 0 deletions core/src/components/tabs/tabs.tsx
Expand Up @@ -95,6 +95,13 @@ export class Tabs implements NavOutlet {
@Listen('ionTabbarClick')
protected tabChange(ev: CustomEvent) {
const selectedTab = ev.detail as HTMLIonTabElement;
if (this.useRouter && this.selectedTab.href != null) {
const router = document.querySelector('ion-router');
if (router) {
router.push(this.selectedTab.href);
}
return;
}
this.select(selectedTab);
}

Expand Down
32 changes: 21 additions & 11 deletions core/src/utils/transition.ts
Expand Up @@ -31,7 +31,7 @@ function beforeTransition(opts: AnimationOptions) {
}

async function animation(opts: AnimationOptions): Promise<Animation> {
await waitDeepReady(opts);
await waitForReady(opts, true);

const transition = await createTransition(opts);
fireWillEvents(opts.enteringEl, opts.leavingEl);
Expand All @@ -50,26 +50,24 @@ async function noAnimation(opts: AnimationOptions): Promise<null> {
enteringEl && enteringEl.classList.remove('hide-page');
leavingEl && leavingEl.classList.remove('hide-page');

await waitShallowReady(opts);
await waitForReady(opts, false);

fireWillEvents(enteringEl, leavingEl);
fireDidEvents(enteringEl, leavingEl);
return undefined;
}

async function waitDeepReady(opts: AnimationOptions) {
await Promise.all([
async function waitForReady(opts: AnimationOptions, defaultDeep: boolean) {
const deep = opts.deepWait != null ? opts.deepWait : defaultDeep;
const promises = deep ? [
deepReady(opts.enteringEl),
deepReady(opts.leavingEl)
]);
await notifyViewReady(opts.viewIsReady, opts.enteringEl);
}

async function waitShallowReady(opts: AnimationOptions) {
await Promise.all([
] : [
shallowReady(opts.enteringEl),
shallowReady(opts.leavingEl)
]);
];

await Promise.all(promises);
await notifyViewReady(opts.viewIsReady, opts.enteringEl);
}

Expand Down Expand Up @@ -142,6 +140,17 @@ function deepReady(el: Element): Promise<any> {
if (!el) {
return Promise.resolve();
}
if (customElements.get) {
if (customElements.get(el.tagName.toLowerCase())) {
return componentOnReady(el);
} else {
return Promise.all(Array.from(el.children).map(deepReady));
}
}
return componentOnReady(el);
}

function componentOnReady(el: Element) {
if ((el as any).componentOnReady) {
return (el as any).componentOnReady();
} else {
Expand Down Expand Up @@ -175,6 +184,7 @@ export interface AnimationOptions {
direction?: NavDirection;
duration?: number;
easing?: string;
deepWait?: boolean;
viewIsReady?: (enteringEl: HTMLElement) => Promise<any>;
showGoBack?: boolean;
progressAnimation?: Function;
Expand Down

0 comments on commit 7e97006

Please sign in to comment.