mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +08:00
fix(): ensure that bindings fore core are being loaded.
This commit is contained in:
124
src/bindings/angular/components/boolean-input.ts
Normal file
124
src/bindings/angular/components/boolean-input.ts
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from '@angular/core';
|
||||||
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
@Directive({
|
||||||
|
selector: 'ion-toggle',
|
||||||
|
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: BooleanInput, multi: true }],
|
||||||
|
})
|
||||||
|
export class BooleanInput {
|
||||||
|
id: string;
|
||||||
|
_labelId: string;
|
||||||
|
_chg: Function;
|
||||||
|
_tch: Function;
|
||||||
|
_dis: Function;
|
||||||
|
|
||||||
|
@Output() ionChange: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
@Output() ionFocus: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
@Output() ionBlur: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
|
||||||
|
constructor(public _el: ElementRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @input {boolean} If true, the element is selected.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
get checked(): boolean {
|
||||||
|
return this._el.nativeElement.checked;
|
||||||
|
}
|
||||||
|
set checked(val: boolean) {
|
||||||
|
this._el.nativeElement.checked = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @input {boolean} If true, the user cannot interact with this element.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
get disabled(): boolean {
|
||||||
|
return this._el.nativeElement.disabled;
|
||||||
|
}
|
||||||
|
set disabled(val: boolean) {
|
||||||
|
this._el.nativeElement.disabled = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @input {string}
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
get value(): string {
|
||||||
|
return this._el.nativeElement.value;
|
||||||
|
}
|
||||||
|
set value(val: string) {
|
||||||
|
this._el.nativeElement.value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
@HostListener('$ionChange', ['$event'])
|
||||||
|
_onChange(ev: any) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this._chg && this._chg(ev.detail.checked);
|
||||||
|
this._tch && this._tch();
|
||||||
|
this.ionChange.emit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
@HostListener('$ionFocus', ['$event'])
|
||||||
|
_onFocus(ev: any) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this.ionFocus.emit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
@HostListener('$ionBlur', ['$event'])
|
||||||
|
_onBlur(ev: any) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this.ionBlur.emit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
writeValue(val: any) {
|
||||||
|
if (this.checked !== val) {
|
||||||
|
this.checked = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
registerOnChange(fn: any) {
|
||||||
|
this._chg = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
registerOnTouched(fn: any) {
|
||||||
|
this._tch = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
registerOnDisabledChange(fn: any) {
|
||||||
|
this._dis = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
setDisabledState(isDisabled: boolean) {
|
||||||
|
this.disabled = isDisabled;
|
||||||
|
}
|
||||||
|
}
|
122
src/bindings/angular/providers/ionic-core.ts
Normal file
122
src/bindings/angular/providers/ionic-core.ts
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import { Config } from '../../../config/config';
|
||||||
|
import { DomController } from '../../../platform/dom-controller';
|
||||||
|
import { NgZone } from '@angular/core';
|
||||||
|
import { Platform } from '../../../platform/platform';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
export function setupCore(config: Config, plt: Platform, domCtrl: DomController, zone: NgZone) {
|
||||||
|
return function() {
|
||||||
|
const win: any = plt.win();
|
||||||
|
const doc = plt.doc();
|
||||||
|
|
||||||
|
const ionic: any = win['Ionic'];
|
||||||
|
|
||||||
|
if (!ionic || !ionic['staticDir']) {
|
||||||
|
// window.Ionic should already exist and
|
||||||
|
// window.Ionic.staticDir should have been added to the
|
||||||
|
// main bundle referencing the static www build directory
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// same controllers are used by ionic core
|
||||||
|
ionic['ConfigCtrl'] = config;
|
||||||
|
|
||||||
|
// keep core and angular dom reads/writes *nsync
|
||||||
|
ionic['DomCtrl'] = domCtrl;
|
||||||
|
|
||||||
|
// next tick controller created here so that it can
|
||||||
|
// be created to run outside of angular
|
||||||
|
ionic['QueueCtrl'] = getQueueController(win, zone);
|
||||||
|
|
||||||
|
// keep core and angular dom reads/writes *nsync
|
||||||
|
ionic['eventNameFn'] = function(eventName: string) {
|
||||||
|
return '$' + eventName;
|
||||||
|
};
|
||||||
|
|
||||||
|
// build up a path for the exact ionic core javascript file this browser needs
|
||||||
|
var pathItems: string[] = ['core'];
|
||||||
|
|
||||||
|
if (!('attachShadow' in Element.prototype)) {
|
||||||
|
// browser requires the shadow dom polyfill
|
||||||
|
pathItems.push('sd');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!win.customElements) {
|
||||||
|
// browser requires the custom elements polyfill
|
||||||
|
pathItems.push('ce');
|
||||||
|
}
|
||||||
|
|
||||||
|
// request the ionic core file this browser needs
|
||||||
|
var s = doc.createElement('script');
|
||||||
|
s.src = `${ionic['staticDir']}ionic.${pathItems.join('.')}.js`;
|
||||||
|
doc.head.appendChild(s);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getQueueController(win: any, zone: NgZone) {
|
||||||
|
const hostScheduleDefer: Function = win['requestIdleCallback'];
|
||||||
|
const callbacks: Function[] = [];
|
||||||
|
let pending = false;
|
||||||
|
|
||||||
|
function doWork(deadlineObj: any) {
|
||||||
|
// let's see if we've got time to take care of things
|
||||||
|
while (deadlineObj.timeRemaining() > 1 && callbacks.length > 0) {
|
||||||
|
// do some work while within the allowed time
|
||||||
|
// shift the array and fire off the callbacks from the beginning
|
||||||
|
// once we run out of time or callbacks we'll stop
|
||||||
|
callbacks.shift()();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to see if we still have work to do
|
||||||
|
if (pending = (callbacks.length > 0)) {
|
||||||
|
// everyone just settle down now
|
||||||
|
// we already don't have time to do anything in this callback
|
||||||
|
// let's throw the next one in a requestAnimationFrame
|
||||||
|
// so we can just simmer down for a bit
|
||||||
|
zone.runOutsideAngular(() => {
|
||||||
|
requestAnimationFrame(flush);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function flush() {
|
||||||
|
// always force a bunch of callbacks to run, but still have
|
||||||
|
// a throttle on how many can run in a certain time
|
||||||
|
const start = performance.now();
|
||||||
|
while (callbacks.length > 0 && (performance.now() - start < 4)) {
|
||||||
|
callbacks.shift()();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pending = (callbacks.length > 0)) {
|
||||||
|
// still more to do yet, but we've run out of time
|
||||||
|
// let's let thing cool off and try again after a raf
|
||||||
|
zone.runOutsideAngular(() => {
|
||||||
|
hostScheduleDefer(doWork);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function add(cb: Function) {
|
||||||
|
// add the work to the end of the callbacks
|
||||||
|
callbacks.push(cb);
|
||||||
|
|
||||||
|
if (!pending) {
|
||||||
|
// not already pending work to do, so let's tee it up
|
||||||
|
pending = true;
|
||||||
|
zone.runOutsideAngular(() => {
|
||||||
|
hostScheduleDefer(doWork);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
add: add,
|
||||||
|
flush: flush
|
||||||
|
};
|
||||||
|
}
|
@ -122,6 +122,7 @@ export { NavController } from './navigation/nav-controller';
|
|||||||
export { NavControllerBase } from './navigation/nav-controller-base';
|
export { NavControllerBase } from './navigation/nav-controller-base';
|
||||||
export { NavParams } from './navigation/nav-params';
|
export { NavParams } from './navigation/nav-params';
|
||||||
export { NavLink, NavOptions, DeepLinkConfig, DeepLinkMetadata, DeepLinkMetadataFactory } from './navigation/nav-util';
|
export { NavLink, NavOptions, DeepLinkConfig, DeepLinkMetadata, DeepLinkMetadataFactory } from './navigation/nav-util';
|
||||||
|
export { setupCore } from './bindings/angular/providers/ionic-core';
|
||||||
export { TapClick, setupTapClick, isActivatable } from './tap-click/tap-click';
|
export { TapClick, setupTapClick, isActivatable } from './tap-click/tap-click';
|
||||||
export { UrlSerializer, DeepLinkConfigToken } from './navigation/url-serializer';
|
export { UrlSerializer, DeepLinkConfigToken } from './navigation/url-serializer';
|
||||||
export { ViewController } from './navigation/view-controller';
|
export { ViewController } from './navigation/view-controller';
|
||||||
|
@ -31,6 +31,7 @@ import { ModuleLoader, provideModuleLoader, setupPreloading, LAZY_LOADED_TOKEN }
|
|||||||
import { NgModuleLoader } from './util/ng-module-loader';
|
import { NgModuleLoader } from './util/ng-module-loader';
|
||||||
import { Platform, setupPlatform } from './platform/platform';
|
import { Platform, setupPlatform } from './platform/platform';
|
||||||
import { PlatformConfigToken, providePlatformConfigs } from './platform/platform-registry';
|
import { PlatformConfigToken, providePlatformConfigs } from './platform/platform-registry';
|
||||||
|
import { setupCore } from './bindings/angular/providers/ionic-core';
|
||||||
import { TapClick, setupTapClick } from './tap-click/tap-click';
|
import { TapClick, setupTapClick } from './tap-click/tap-click';
|
||||||
import { registerModeConfigs } from './config/mode-registry';
|
import { registerModeConfigs } from './config/mode-registry';
|
||||||
import { TransitionController } from './transitions/transition-controller';
|
import { TransitionController } from './transitions/transition-controller';
|
||||||
@ -395,6 +396,7 @@ export class IonicModule {
|
|||||||
|
|
||||||
// useFactory: ionic app initializers
|
// useFactory: ionic app initializers
|
||||||
{ provide: APP_INITIALIZER, useFactory: registerModeConfigs, deps: [ Config ], multi: true },
|
{ provide: APP_INITIALIZER, useFactory: registerModeConfigs, deps: [ Config ], multi: true },
|
||||||
|
{ provide: APP_INITIALIZER, useFactory: setupCore, deps: [ Config, Platform, DomController, NgZone ], multi: true },
|
||||||
{ provide: APP_INITIALIZER, useFactory: setupProvideEvents, deps: [ Platform, DomController ], multi: true },
|
{ provide: APP_INITIALIZER, useFactory: setupProvideEvents, deps: [ Platform, DomController ], multi: true },
|
||||||
{ provide: APP_INITIALIZER, useFactory: setupTapClick, deps: [ Config, Platform, DomController, App, GestureController ], multi: true },
|
{ provide: APP_INITIALIZER, useFactory: setupTapClick, deps: [ Config, Platform, DomController, App, GestureController ], multi: true },
|
||||||
{ provide: APP_INITIALIZER, useFactory: setupPreloading, deps: [ Config, DeepLinkConfigToken, ModuleLoader, NgZone ], multi: true },
|
{ provide: APP_INITIALIZER, useFactory: setupPreloading, deps: [ Config, DeepLinkConfigToken, ModuleLoader, NgZone ], multi: true },
|
||||||
|
Reference in New Issue
Block a user