perf(toggle): events are not zoned

This commit is contained in:
Manuel Mtz-Almeida
2017-04-07 19:59:47 +02:00
parent c792ab69ae
commit bda624f870
5 changed files with 57 additions and 33 deletions

View File

@ -1,6 +1,6 @@
import { Toggle } from '../toggle';
import { mockConfig, mockPlatform, mockHaptic, mockElementRef, mockGestureController, mockRenderer, mockItem, mockForm, mockChangeDetectorRef } from '../../../util/mock-providers';
import { mockConfig, mockPlatform, mockHaptic, mockElementRef, mockGestureController, mockRenderer, mockItem, mockForm, mockChangeDetectorRef, mockZone } from '../../../util/mock-providers';
import { commonInputTest, BOOLEAN_CORPUS } from '../../../util/input-tester';
describe('Toggle', () => {
@ -16,7 +16,8 @@ describe('Toggle', () => {
const haptic = mockHaptic();
const cd = mockChangeDetectorRef();
const gesture = mockGestureController();
const toggle = new Toggle(form, config, platform, elementRef, renderer, haptic, item, gesture, null, cd);
const zone = mockZone();
const toggle = new Toggle(form, config, platform, elementRef, renderer, haptic, item, gesture, null, cd, zone);
commonInputTest(toggle, {
defaultValue: false,

View File

@ -20,7 +20,7 @@ export class ToggleGesture extends PanGesture {
plt,
toggle.getNativeElement(), {
threshold: 0,
zone: true,
zone: false,
domController: domCtrl,
gesture: gestureCtrl.createGesture({
name: GESTURE_TOGGLE,

View File

@ -61,11 +61,11 @@ $toggle-md-item-right-padding: 12px ($item-md-padding-right / 2) 12px
.toggle-md {
position: relative;
padding: $toggle-md-padding;
width: $toggle-md-track-width;
height: $toggle-md-track-height;
padding: $toggle-md-padding;
box-sizing: content-box;
}
@ -107,6 +107,10 @@ $toggle-md-item-right-padding: 12px ($item-md-padding-right / 2) 12px
transition-duration: $toggle-md-transition-duration;
transition-property: transform, background-color;
will-change: transform, background-color;
contain: strict;
}

View File

@ -1,4 +1,4 @@
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, forwardRef, HostListener, Input, OnDestroy, Optional, Renderer, ViewEncapsulation } from '@angular/core';
import { NgZone, AfterViewInit, ChangeDetectorRef, Component, ElementRef, forwardRef, HostListener, Input, OnDestroy, Optional, Renderer, ViewEncapsulation } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Config } from '../../config/config';
@ -13,7 +13,6 @@ import { KEY_ENTER, KEY_SPACE } from '../../platform/key';
import { Platform } from '../../platform/platform';
import { ToggleGesture } from './toggle-gesture';
export const TOGGLE_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => Toggle),
@ -109,7 +108,8 @@ export class Toggle extends BaseInput<boolean> implements IonicTapInput, AfterVi
@Optional() item: Item,
private _gestureCtrl: GestureController,
private _domCtrl: DomController,
private _cd: ChangeDetectorRef
private _cd: ChangeDetectorRef,
private _zone: NgZone,
) {
super(config, elementRef, renderer, 'toggle', false, form, item, null);
}
@ -142,9 +142,11 @@ export class Toggle extends BaseInput<boolean> implements IonicTapInput, AfterVi
assert(startX, 'startX must be valid');
console.debug('toggle, _onDragStart', startX);
this._startX = startX;
this._fireFocus();
this._activated = true;
this._zone.run(() => {
this._startX = startX;
this._fireFocus();
this._activated = true;
});
}
/**
@ -156,22 +158,32 @@ export class Toggle extends BaseInput<boolean> implements IonicTapInput, AfterVi
return;
}
console.debug('toggle, _onDragMove', currentX);
let dirty = false;
let value: boolean;
let activated: boolean;
if (this._value) {
if (currentX + 15 < this._startX) {
this.value = false;
this._haptic.selection();
this._startX = currentX;
this._activated = true;
dirty = true;
value = false;
activated = true;
}
} else if (currentX - 15 > this._startX) {
this.value = true;
this._haptic.selection();
this._startX = currentX;
this._activated = (currentX < this._startX + 5);
dirty = true;
value = true;
activated = (currentX < this._startX + 5);
}
if (dirty) {
this._zone.run(() => {
this.value = value;
this._startX = currentX;
this._activated = activated;
this._haptic.selection();
});
}
}
/**
@ -184,20 +196,22 @@ export class Toggle extends BaseInput<boolean> implements IonicTapInput, AfterVi
}
console.debug('toggle, _onDragEnd', endX);
if (this._value) {
if (this._startX + 4 > endX) {
this.value = false;
this._zone.run(() => {
if (this._value) {
if (this._startX + 4 > endX) {
this.value = false;
this._haptic.selection();
}
} else if (this._startX - 4 < endX) {
this.value = true;
this._haptic.selection();
}
} else if (this._startX - 4 < endX) {
this.value = true;
this._haptic.selection();
}
this._activated = false;
this._fireBlur();
this._startX = null;
this._activated = false;
this._fireBlur();
this._startX = null;
});
}
/**

View File

@ -1,4 +1,4 @@
import { ElementRef, EventEmitter, Input, Output, Renderer } from '@angular/core';
import { ElementRef, EventEmitter, Input, NgZone, Output, Renderer } from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';
import { NgControl } from '@angular/forms';
@ -130,6 +130,8 @@ export class BaseInput<T> extends Ion implements CommonInput<T> {
* @hidden
*/
_writeValue(val: any): boolean {
assert(NgZone.isInAngularZone(), 'callback should be zoned');
if (isUndefined(val)) {
return false;
}
@ -154,7 +156,10 @@ export class BaseInput<T> extends Ion implements CommonInput<T> {
*/
_fireIonChange() {
if (this._init) {
this._debouncer.debounce(() => this.ionChange.emit(this));
this._debouncer.debounce(() => {
assert(NgZone.isInAngularZone(), 'callback should be zoned');
this.ionChange.emit(this);
});
}
}