diff --git a/src/components/dynamic-component/dynamic-component.ts b/src/components/dynamic-component/dynamic-component.ts
index 1692b7663..5e232ce04 100644
--- a/src/components/dynamic-component/dynamic-component.ts
+++ b/src/components/dynamic-component/dynamic-component.ts
@@ -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;
- }
}
diff --git a/src/core/compile/components/compile-html/compile-html.ts b/src/core/compile/components/compile-html/compile-html.ts
index 8b7a7a218..3151f4d29 100644
--- a/src/core/compile/components/compile-html/compile-html.ts
+++ b/src/core/compile/components/compile-html/compile-html.ts
@@ -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: ''
})
-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;
+ 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];
+ }
+ }
+ }
}
diff --git a/src/providers/utils/dom.ts b/src/providers/utils/dom.ts
index c66f47855..510c7876d 100644
--- a/src/providers/utils/dom.ts
+++ b/src/providers/utils/dom.ts
@@ -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.
*