MOBILE-2338 compile: Monitor jsData changes
parent
c626bee407
commit
d53a7acda5
|
@ -18,6 +18,7 @@ import {
|
|||
} from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
|
||||
/**
|
||||
* Component to create another component dynamically.
|
||||
|
@ -68,7 +69,9 @@ export class CoreDynamicComponent implements OnInit, OnChanges, DoCheck {
|
|||
protected differ: any; // To detect changes in the data input.
|
||||
|
||||
constructor(logger: CoreLoggerProvider, protected factoryResolver: ComponentFactoryResolver, differs: KeyValueDiffers,
|
||||
@Optional() protected navCtrl: NavController, protected cdr: ChangeDetectorRef, protected element: ElementRef) {
|
||||
@Optional() protected navCtrl: NavController, protected cdr: ChangeDetectorRef, protected element: ElementRef,
|
||||
protected domUtils: CoreDomUtilsProvider) {
|
||||
|
||||
this.logger = logger.getInstance('CoreDynamicComponent');
|
||||
this.differ = differs.find([]).create();
|
||||
}
|
||||
|
@ -99,7 +102,7 @@ export class CoreDynamicComponent implements OnInit, OnChanges, DoCheck {
|
|||
if (changes) {
|
||||
this.setInputData();
|
||||
if (this.instance.ngOnChanges) {
|
||||
this.instance.ngOnChanges(this.createChangesForComponent(changes));
|
||||
this.instance.ngOnChanges(this.domUtils.createChangesFromKeyValueDiff(changes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,29 +173,4 @@ export class CoreDynamicComponent implements OnInit, OnChanges, DoCheck {
|
|||
this.instance[name] = this.data[name];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the changes on the data input, create the changes object for the component.
|
||||
*
|
||||
* @param {any} changes Changes in the data input (detected by KeyValueDiffer).
|
||||
* @return {{[name: string]: SimpleChange}} List of changes for the component.
|
||||
*/
|
||||
protected createChangesForComponent(changes: any): { [name: string]: SimpleChange } {
|
||||
const newChanges: { [name: string]: SimpleChange } = {};
|
||||
|
||||
// Added items are considered first change.
|
||||
changes.forEachAddedItem((item) => {
|
||||
newChanges[item.key] = new SimpleChange(item.previousValue, item.currentValue, true);
|
||||
});
|
||||
|
||||
// Changed or removed items aren't first change.
|
||||
changes.forEachChangedItem((item) => {
|
||||
newChanges[item.key] = new SimpleChange(item.previousValue, item.currentValue, false);
|
||||
});
|
||||
changes.forEachRemovedItem((item) => {
|
||||
newChanges[item.key] = new SimpleChange(item.previousValue, item.currentValue, true);
|
||||
});
|
||||
|
||||
return newChanges;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,11 @@
|
|||
|
||||
import {
|
||||
Component, Input, OnInit, OnChanges, OnDestroy, ViewContainerRef, ViewChild, ComponentRef, SimpleChange, ChangeDetectorRef,
|
||||
ElementRef, Optional, Output, EventEmitter
|
||||
ElementRef, Optional, Output, EventEmitter, DoCheck, KeyValueDiffers
|
||||
} from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreCompileProvider } from '../../providers/compile';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
|
||||
/**
|
||||
* This component has a behaviour similar to $compile for AngularJS. Given an HTML code, it will compile it so all its
|
||||
|
@ -38,7 +39,7 @@ import { CoreCompileProvider } from '../../providers/compile';
|
|||
selector: 'core-compile-html',
|
||||
template: '<ng-container #dynamicComponent></ng-container>'
|
||||
})
|
||||
export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
||||
export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
|
||||
@Input() text: string; // The HTML text to display.
|
||||
@Input() javascript: string; // The Javascript to execute in the component.
|
||||
@Input() jsData: any; // Data to pass to the fake component.
|
||||
|
@ -50,11 +51,30 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
|||
@ViewChild('dynamicComponent', { read: ViewContainerRef }) container: ViewContainerRef;
|
||||
|
||||
protected componentRef: ComponentRef<any>;
|
||||
protected componentInstance: any;
|
||||
protected element;
|
||||
protected differ: any; // To detect changes in the jsData input.
|
||||
|
||||
constructor(protected compileProvider: CoreCompileProvider, protected cdr: ChangeDetectorRef, element: ElementRef,
|
||||
@Optional() protected navCtrl: NavController) {
|
||||
@Optional() protected navCtrl: NavController, differs: KeyValueDiffers, protected domUtils: CoreDomUtilsProvider) {
|
||||
this.element = element.nativeElement;
|
||||
this.differ = differs.find([]).create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect and act upon changes that Angular can’t or won’t detect on its own (objects and arrays).
|
||||
*/
|
||||
ngDoCheck(): void {
|
||||
if (this.componentInstance) {
|
||||
// Check if there's any change in the jsData object.
|
||||
const changes = this.differ.diff(this.jsData);
|
||||
if (changes) {
|
||||
this.setInputData();
|
||||
if (this.componentInstance.ngOnChanges) {
|
||||
this.componentInstance.ngOnChanges(this.domUtils.createChangesFromKeyValueDiff(changes));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,6 +116,9 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
|||
// Create the component, using the text as the template.
|
||||
return class CoreCompileHtmlFakeComponent implements OnInit {
|
||||
constructor() {
|
||||
// Store this instance so it can be accessed by the outer component.
|
||||
compileInstance.componentInstance = this;
|
||||
|
||||
// If there is some javascript to run, prepare the instance.
|
||||
if (compileInstance.javascript) {
|
||||
compileInstance.compileProvider.injectLibraries(this, compileInstance.extraProviders);
|
||||
|
@ -107,9 +130,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
|||
this['componentContainer'] = compileInstance.element;
|
||||
|
||||
// Add the data passed to the component.
|
||||
for (const name in compileInstance.jsData) {
|
||||
this[name] = compileInstance.jsData[name];
|
||||
}
|
||||
compileInstance.setInputData();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@ -120,4 +141,15 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JS data as input data of the component instance.
|
||||
*/
|
||||
protected setInputData(): void {
|
||||
if (this.componentInstance) {
|
||||
for (const name in this.jsData) {
|
||||
this.componentInstance[name] = this.jsData[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, SimpleChange } from '@angular/core';
|
||||
import {
|
||||
LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform, Content,
|
||||
ModalController
|
||||
|
@ -148,6 +148,32 @@ export class CoreDomUtilsProvider {
|
|||
return {coreCanceled: true};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of changes for a component input detected by a KeyValueDiffers, create an object similar to the one
|
||||
* passed to the ngOnChanges functions.
|
||||
*
|
||||
* @param {any} changes Changes detected by KeyValueDiffer.
|
||||
* @return {{[name: string]: SimpleChange}} Changes in a format like ngOnChanges.
|
||||
*/
|
||||
createChangesFromKeyValueDiff(changes: any): { [name: string]: SimpleChange } {
|
||||
const newChanges: { [name: string]: SimpleChange } = {};
|
||||
|
||||
// Added items are considered first change.
|
||||
changes.forEachAddedItem((item) => {
|
||||
newChanges[item.key] = new SimpleChange(item.previousValue, item.currentValue, true);
|
||||
});
|
||||
|
||||
// Changed or removed items aren't first change.
|
||||
changes.forEachChangedItem((item) => {
|
||||
newChanges[item.key] = new SimpleChange(item.previousValue, item.currentValue, false);
|
||||
});
|
||||
changes.forEachRemovedItem((item) => {
|
||||
newChanges[item.key] = new SimpleChange(item.previousValue, item.currentValue, true);
|
||||
});
|
||||
|
||||
return newChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the downloadable URLs from an HTML code.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue