0

I'm trying to use the dynamic component provided by @GünterZöchbauer here Angular 2 dynamic tabs with user-click chosen components to create rows and columns. So far I got successfully the rows added but still can't get the columns created inside the rows.

Here is my code:

DesignerModule

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MaterializeModule } from '../../shared/materialize/materialize.module';
import { DesignerComponent } from './designer.component';
import { RowComponent } from './designer.component';
import { ColumnComponent } from './designer.component';
import { DynWrapperComponent } from './dyn-wrapper.component';
@NgModule({
 imports: [
 CommonModule,
 MaterializeModule,
 ],
 declarations: [
 DesignerComponent,
 DynWrapperComponent,
 RowComponent,
 ColumnComponent,
 ],
 entryComponents: [
 RowComponent,
 ColumnComponent,
 ],
 providers: [
 ]
})
export class DesignerModule {}

DynWrapperComponent

import { Component, Compiler, ViewContainerRef, ViewChild, Input, ElementRef,
 ComponentRef, ComponentFactory, ComponentFactoryResolver} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
// Helper component to add dynamic components
@Component({
 moduleId: module.id,
 selector: 'dcl-wrapper',
 template: `<div #target></div>`
})
export class DynWrapperComponent {
 @ViewChild('target', {read: ViewContainerRef}) target: any;
 @Input() type: any;
 cmpRef:ComponentRef<any>;
 private isViewInitialized:boolean = false;
 constructor(private componentFactoryResolver: ComponentFactoryResolver,
 private compiler: Compiler,
 private el: ElementRef) {}
 updateComponent() {
 if(!this.isViewInitialized) {
 return;
 }
 if(this.cmpRef) {
 this.cmpRef.destroy();
 }
 let factory = this.componentFactoryResolver.resolveComponentFactory(this.type);
 //this.resolver.resolveComponent(this.type).then((factory:ComponentFactory<any>) => {
 this.cmpRef = this.target.createComponent(factory)
 }
 ngOnChanges() {
 this.updateComponent();
 }
 ngAfterViewInit() {
 this.isViewInitialized = true;
 this.updateComponent(); 
 }
 ngOnDestroy() {
 if(this.cmpRef) {
 this.cmpRef.destroy();
 }
 }
}

DesignerComponent

import { Component, ViewChild, ElementRef, ContentChildren } from '@angular/core';
@Component({
 moduleId: module.id,
 selector: 'my-row',
 templateUrl: 'row.component.html',
 styles: [
 `.row:hover {
 border: 3px dashed #880e4f ;
 }
 `
 ]
})
export class RowComponent {
 colIndex: number = 0;
 colList: Object[] = [];
 addColumn() {
 this.colList.splice(this.colIndex, 0, ColumnComponent);
 this.colIndex++;
 }
 removeColumn(colIdx: number) {
 this.colList.splice(colIdx, 1);
 }
}
@Component({
 moduleId: module.id,
 selector: 'my-column',
 templateUrl: 'column.component.html',
 styles: [
 `.col:hover {
 border: 3px solid #304ffe;
 }
 `
 ]
})
export class ColumnComponent {
}
@Component({
 moduleId: module.id,
 selector: 'my-designer',
 templateUrl: 'designer.component.html',
})
export class DesignerComponent {
 @ViewChild('builder') builder:ElementRef;
 elementIndex: number = 0;
 list: Object[] = [];
 ngAfterViewInit() {
 }
 addRow() {
 this.list.splice(this.elementIndex, 0, RowComponent);
 this.elementIndex++;
 }
 remove(idx: number) {
 this.list.splice(idx, 1);
 }
}

DesignerComponent.html

<div #builder class="row">
 <div class="s1 teal lighten-2">
 <p class="flow-text">teste do html builder</p>
 <div *ngFor="let row of list; let idx = index" >
 <p class="flow-text">Linha {{idx}}</p>
 <dcl-wrapper [type]="row"></dcl-wrapper>
 <a class="btn-floating btn-small waves-effect waves-light purple" (click)="remove(idx)"><i class="material-icons">remove</i></a>
 </div>
 </div>
</div>
<a class="btn-floating btn-large waves-effect waves-light red" (click)="addRow()"><i class="material-icons">add</i></a>

RowComponent.html

<div #row class="row">
 <div class="s12 teal lighten-2">
 <p class="flow-text">adicionando linha no html builder</p>
 </div>
 <div *ngFor="let col of colList; let colIndex = index">
 <p>Column</p>
 <dcl-wrapper [type]="col"></dcl-wrapper>
 </div>
 <a class="btn-floating btn-small waves-effect waves-light waves-teal" (click)="addColumn()"><i class="material-icons">view_column</i></a>
</div>

ColumnComponent.html

<div class="col s1 purple lighten-2">
 <p class="flow-text">column added ....</p>
</div>

This approach is generating the following error:

Expression has changed after it was checked. Previous value: 'CD_INIT_VALUE'. Current value:

Did it anyone get this working as nested elements?

Thanks very much for the help!

asked Sep 30, 2016 at 14:43

1 Answer 1

2

Try to use ngAfterContentInit hook instead of ngAfterViewInit in your DynWrapperComponent:

dyn-wrapper.component.ts

ngAfterContentInit() {
 this.isViewInitialized = true;
 this.updateComponent(); 
}
answered Sep 30, 2016 at 15:08
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.