I have a modal. On that I can add ion-cards as components dynamically by button click and store it in firebase. When I have more then three components in a modal, to load the modal take up to a minute and interacting with the component is very slow.
What can I do? What did I do wrong?
Chrome Analyzer says this:
This is the code:
modal.html
<div *ngFor="let app of room.apps">
<app-content-generator></app-content-generator>
{{app.type.name}}
</div>
component.html
<ion-card style="background:white;margin:10px" id={{id}}>
<ion-item lines="full">
<ion-card-title>
<ion-input style="text-align:left" placeholder="Title"></ion-input>
</ion-card-title>
</ion-item>
<!--div style='position:absolute;height:2px;width:100%;z-index:20'>
<div id="inactive" style="float:left;background:var(--ion-color-medium);width:100%;height:2px"></div>
<div id="active" style="float:left;background:var(--ion-color-synyellow);width:0%;height:2px"></div>
<div id="complete" style="float:left;background:var(--ion-color-syngreen);width:0%;height:2px"></div>
</div-->
<ion-card-content style="padding:0">
<ion-list style="background:none" style="padding:0">
<form [formGroup]="orderForm" class="item-container" >
<div formArrayName="items" *ngFor="let item of orderForm.get('items').controls; let i = index;">
<ion-item [formGroupName]="i" [ngStyle]="{'display': item.value.itemStatus == 0 || item.value.itemStatus == 1 ? 'block':'none'}" lines="inset" id={{item.value.itemId}} (mouseenter)="activeFocus(item,true)" (mouseleave)="activeFocus(item,false)">
<form>
<ion-checkbox slot="start" *ngIf="item.value.itemStatus == 1" (click)="checkbox(orderForm,item,i)" color="medium" style="margin-right:16px" checked="false" indeterminate="true"></ion-checkbox>
<ion-checkbox slot="start" *ngIf="item.value.itemStatus == 2" (click)="checkbox(orderForm,item,i)" color="medium" style="margin-right:16px" checked="true" indeterminate="false"></ion-checkbox>
<ion-checkbox slot="start" *ngIf="item.value.itemStatus == 0" (click)="checkbox(orderForm,item,i)" style="margin-right:16px" color="medium" checked="false"></ion-checkbox>
</form>
<ion-textarea (ionFocus)="activeFocus(item,true)" (ionBlur)="activeFocus(item,false)" #appTextarea (click)="autoGrow()" auto-grow="true" rows="1" style="--background: none;margin-top:4px;margin-bottom:4px" type="text" formControlName="name" dragula="COPYABLE"></ion-textarea>
<ion-icon (click)="removeControl(i)" slot="end" *ngIf="this.isActive == item" name="close-circle"></ion-icon>
<ion-icon slot="end" *ngIf="this.isActive !== item"></ion-icon>
</ion-item>
</div>
<ion-item lines="none" (click)="addItem()">
<ion-icon name="add"></ion-icon>
</ion-item>
<ion-item-divider *ngIf="orderForm.value.completed !== 0" color="light" (click)="showCompleted(orderForm)" style="border:none;padding-right:16px">
<ion-icon *ngIf="!show(orderForm)" name="arrow-dropright" slot="end" color="medium"></ion-icon>
<ion-icon *ngIf="show(orderForm)" name="arrow-dropdown" slot="end" color="medium"></ion-icon>
<ion-label slot="start" color="medium" > {{orderForm.value.completed}} completed</ion-label>
</ion-item-divider>
<div formArrayName="items" *ngFor="let item of orderForm.get('items').controls; let i = index;">
<ion-item [attr.lines]="i !== orderForm.value.items.length ? 'inset' : 'none'" [formGroupName]="i" [ngStyle]="{'display': (item.value.itemStatus == 2 && show(orderForm)) ? 'block':'none'}" id={{item.value.itemId}} (mouseenter)="activeFocus(item,true)" (mouseleave)="activeFocus(item,false)">
<form>
<ion-checkbox slot="start" *ngIf="item.value.itemStatus == 1" (click)="checkbox(orderForm,item,i)" color="medium" style="margin-right:16px" checked="false" indeterminate="true"></ion-checkbox>
<ion-checkbox slot="start" *ngIf="item.value.itemStatus == 2" (click)="checkbox(orderForm,item,i)" color="medium" style="margin-right:16px" checked="true" indeterminate="false"></ion-checkbox>
<ion-checkbox slot="start" *ngIf="item.value.itemStatus == 0" (click)="checkbox(orderForm,item,i)" color="medium" style="margin-right:16px" checked="false"></ion-checkbox>
</form>
<ion-text style="opacity:0.3;--background: none;margin-top:4px;margin-bottom:4px">{{item.value.name}} </ion-text>
<ion-icon (click)="removeControl(i)" slot="end" *ngIf="this.isActive == item" name="close-circle"></ion-icon>
<ion-icon slot="end" *ngIf="this.isActive !== item"></ion-icon>
</ion-item>
</div>
<div style="background-color:#dedede;width:100%;height:1px;margin-top:-3px"></div>
</form>
</ion-list>
<ion-item style="--background: none" lines="none" dragula="COPYABLE">
<!--ion-icon slot="start"></ion-icon> Total: {{this.myFormLength - 1}} -->
</ion-item>
</ion-card-content>
</ion-card>
component.ts
import { OnChanges, SimpleChanges, EventEmitter, Input, Output, ElementRef, Component, OnInit, AfterViewInit, ViewChild, } from '@angular/core';
import { FormGroup, FormBuilder, FormControl, FormArray, Validators } from '@angular/forms';
import { IonContent, IonInput, IonTextarea } from '@ionic/angular'
import { AngularFirestore } from "@angular/fire/firestore"
//import { AppContent} from '../../models/appContent.interface'
import {
AppsService
} from "../../servicios/app.service";
@Component({
selector: 'app-content-generator',
templateUrl: './app-content-generator.component.html',
styleUrls: ['./app-content-generator.component.scss'],
inputs: ['id']
})
export class AppContentGeneratorComponent implements OnInit, AfterViewInit{
//@ViewChild (IonInput, {static:false }) ionInput : IonInput;
@ViewChild('appTextarea', {static:false}) ionAppTextarea: IonTextarea;
@ViewChild('appCompleteTextarea', {static:false}) ionAppCompleteTextarea: IonTextarea;
//@Input() appDetails : AppContent;
id: string;
orderForm: FormGroup;
items: FormArray;
actualStatus : number = 0;
//stateChange: EventEmitter<IonTextarea> = new EventEmitter<IonTextarea>();
isActive= false;
formName = 'name';
//private generatorTextArea : any;
//public itemStatus : Array<{ item: string, status: number }> = []
constructor(private formBuilder: FormBuilder,private appsService: AppsService, private fireStore: AngularFirestore) {
}
ngOnInit() {
// this.itemStatus.push({item: 'item1',status: 0})
this.orderForm = this.formBuilder.group({
completed: 0,
showCompleted: true,
items: this.formBuilder.array([this.createItem()])
});
}
createItem(): FormGroup {
var id = this.fireStore.createId();
return this.formBuilder.group({
name: '',
itemId: id,
itemStatus: 0
});
}
ngAfterViewInit(){
this.checkAppTextarea(this.ionAppTextarea)
}
checkAppTextarea(textarea){
if( textarea !== undefined){
textarea.getInputElement().then(element => {
if(element.style.height == '0px' ){
return element.style.height = 'auto'
} else {
setTimeout(()=> this.checkAppTextarea(textarea),100)
}
})
} else {
setTimeout(() => this.checkAppTextarea(textarea),100)
}
}
ionInput(id, item){
setTimeout(() => { item.value.name = document.getElementById(id).querySelector('textarea').innerHTML},1);
}
addItem(): void {
this.items = this.orderForm.get('items') as FormArray;
this.items.push(this.createItem());
setTimeout(() =>{
var temp = this.items.at(this.items.length-1);
document.getElementById(temp.value.itemId).querySelector('ion-textarea').setFocus()
} ,100) ;
}
moveDown(index: number) {
if(index < this.items.length-1){
var temp = this.items.at(index)
this.removeTemp(index);
this.items.insert(this.items.length, temp)
}
}
show(list){
if(list.showCompleted){
return true
}else{
return false
}
}
showCompleted(list){
//this.checkAppTextarea(this.ionAppCompleteTextarea)
list.showCompleted = !list.showCompleted;
}
removeTemp(index: number){
this.items.removeAt(index)
}
adjustGrowArea(){
//var temp = this.generatorTextArea['__zone_symbol__value']
//temp.style.height = "auto";
}
close(){
this.appsService.openedGenerator(false)
}
drop(){
}
colorStatus(itemStatus){
if(itemStatus.value == undefined){
return 'medium'
} else{
if(itemStatus.value == 1){
return 'synyellow'
} else if(itemStatus.value == 2){
return 'syngreen'
}
}
}
checkbox(form,name){
var newStatus = (name.value.itemStatus+1)%3;
name.patchValue({
itemStatus : newStatus
})
this.orderForm.patchValue({
completed: this.updateCompleteStatus(form)
})
// this.taskStatus()
}
updateCompleteStatus(form){
var count = 0;
form.value.items.forEach(function(entry) {
if(entry.itemStatus == 2){
count++
}},this );
return count;
}
/*taskStatus(){
var tempObj = this.itemStatus
//var length = this.itemStatus.length;
var prozent = 100/length;
var inactive = 0;
var active = 0;
var complete = 0;
tempObj.forEach(function(item){
if(item.status == 0 || undefined){
inactive++
} else if(item.status == 1){
active++
} else if (item.status == 2){
complete++
}
},this);
console.log('inactive:',inactive,'active:',active,'complete:',complete);
var inactiveProzent = 100 / (length/inactive) + '%'
document.getElementById('inactive').style.width = inactiveProzent
var activeProzent = 100 / (length/active) + '%'
document.getElementById('active').style.width = activeProzent
var completeProzent = 100 / (length/complete) + '%'
document.getElementById('complete').style.width = completeProzent
}*/
activeFocus(item, boolean){
if(boolean){
this.isActive = item;
} else {
this.isActive = null;
}
}
autoGrow(){
document.querySelector('ion-textarea').setAttribute('auto-grow','true');
}
removeControl(index: number){
this.items = this.orderForm.get('items') as FormArray;
this.items.removeAt(index);
setTimeout(() =>{
var temp = this.items.at(this.items.length-1);
document.getElementById(temp.value.itemId).querySelector('ion-textarea').setFocus()
} ,100) ;
}
setFocus(item){
item.focus
}
ngOnDestroy(){
}
}