Dynamic Template URL - Loading with Template Errors


#1

I have an app I’m re-developing in ionic which I did in ionic-v1 a year or so ago. I have multiple template types which a user will pick from and I would like to make a dynamic component which loads its templateURL based off the user configuration value. So everything is working as far as loading the component and getting the right template except when I go to run the app, it gives template errors as though it doesn’t know ngModel is an angular attribute.
Here’s what I have:

	import { Compiler, Component, AfterViewInit, OnInit, Injector, ViewChild, NgModule, NgModuleRef, ViewContainerRef } from '@angular/core';
	import { NavController } from 'ionic-angular';
    import { ImageSliderComponent } from '../../app/components/image-slider/image-slider';

	import { SomeService } from '../../app/services/app.services';

	@Component({
		template: `<ng-container #dynamicvc></ng-container>`
	})
	export class DynamicHome implements OnInit {
		@ViewChild('dynamicvc', { read: ViewContainerRef }) container;
		ehi: any;
		sponsorGroups: any[];
		baseUrl: string;
		selectedSegment: string;

		constructor(private compiler: Compiler, private injector: Injector, private moduleRef: NgModuleRef<any>, private someSvc: SomeService, private navCtrl: NavController) {
			let vm = this;

			vm.selectedSegment = 'home';
		}

		ngAfterViewInit() {
			let vm = this;

			const MaterialCardsSpookyHomeComponent = Component({
				templateUrl: './materialcardsspooky/materialcardsspooky-home.html'
			})(class MaterialCardsSpookyHomeComponent { });
			const MaterialCardsSpookyHomeModule = NgModule({
				declarations: [
					MaterialCardsSpookyHomeComponent,
					ImageSliderComponent
				],
				imports: [
					IonicPageModule.forChild(MaterialCardsSpookyHomeComponent)
				]
			})(class MaterialCardsSpookyHomeModule { });

			let moduleToUse = null;
			switch (vm.someSvc.template.toLowerCase()) {
				case 'materialcardsspooky':
					moduleToUse = MaterialCardsSpookyHomeModule;
					break;
			}

			if (moduleToUse) {
				vm.compiler.compileModuleAndAllComponentsAsync(moduleToUse).then((factories) => {
					const f = factories.componentFactories[0];
					const cmpRef = f.create(vm.injector, [], null, vm.moduleRef);
					cmpRef.instance.ehi = vm.ehi;
					cmpRef.instance.sponsorGroups = vm.sponsorGroups;
					cmpRef.instance.baseUrl = vm.baseUrl;
					cmpRef.instance.selectedSegment = vm.selectedSegment;
					vm.container.insert(cmpRef.hostView);
				});
			}
		}

		ngOnInit() {
			let vm = this;

		}
	}

Here’s my template:

<ion-header>
	  <ion-toolbar no-border-top no-border-bottom>
		<ion-segment [(ngModel)]="selectedSegment">
		  <ion-segment-button value="home" no-border-bottom>
			<ion-icon name="home"></ion-icon>
		  </ion-segment-button>
		</ion-segment>
	  </ion-toolbar>
	</ion-header>
	<ion-content>
	  <div [ngSwitch]="selectedSegment">
		<div *ngSwitchCase="'home'">
			<image-slider [slides]="ehi?.images" [imagetype]="2"></image-slider>
			...
		</div>
	  </div>
	</ion-content>

Here’s my custom component:

import { Component, OnInit, Input, ViewChild } from '@angular/core';
	import { Slides } from 'ionic-angular';

	@Component({
		selector: 'image-slider',
		templateUrl: 'image-slider.html'
	})
	export class ImageSliderComponent implements OnInit {
		@Input() slides: any[];
		@Input() imagetype: string;
		imageSlides: any[] = [];

		@ViewChild(Slides) imgSlides: Slides;

		constructor() { }

		ngOnInit() {
			let vm = this;

			vm.slides.forEach((s) => {
				if (s.imageType === vm.imagetype.toString()) {
					if (s.imageUrl.indexOf(vm.ehmSvc.baseUrl) != 0) {
						s.imageUrl = vm.ehmSvc.baseUrl + s.imageUrl;
					}
					vm.imageSlides.push(s);
				}
			});

			//[pager]="true" [loop]="true" [effect]="fade" [centeredSlides]="true" [spaceBetween]="10"
			if (vm.imageSlides.length === 1) {
				vm.imgSlides.pager = false;
			} else {
				vm.imgSlides.pager = true;
			}

			vm.imgSlides.autoHeight = true;
		}
	}

And here are my errors in Chrome Dev Tools:

Can’t bind to ‘slides’ since it isn’t a known property of ‘image-slider’.

  1. If ‘image-slider’ is an Angular component and it has ‘slides’ input, then verify that it is part of this module.
  2. If ‘image-slider’ is a Web Component then add ‘CUSTOM_ELEMENTS_SCHEMA’ to the ‘@NgModule.schemas’ of this component
    to suppress this message.
  3. To allow any property add ‘NO_ERRORS_SCHEMA’ to the ‘@NgModule.schemas’ of this component. ("

Any ideas how or even if I can accomplish this? Also, using VS2017 and standard Ionic template with default build scripts, i.e. webpack.


#2

Got an answer on stack overflow:

imports: [ IonicPageModule.forChild(MaterialCardsSpookyHomeComponent) ]