From 8146e563ca13c2817cda1cdb4c58889062eaf6b2 Mon Sep 17 00:00:00 2001
From: jojohoch <joachim.hoch@iqb.hu-berlin.de>
Date: Thu, 15 Jul 2021 10:23:58 +0200
Subject: [PATCH] Remove general inheritance from `FormElementComponent`

* Only elements which has to be registered by the player's form inherit
from `FormElementComponent`
* Element components use their specific `elementModel`
* Rename file for `FormElementComponent`
---
 projects/common/component-utils.ts                |  7 +++----
 .../common/element-components/audio.component.ts  |  7 ++++---
 .../common/element-components/button.component.ts |  8 +++++---
 .../element-components/checkbox.component.ts      |  9 ++++++---
 .../compound-components/correction.component.ts   | 12 ++++++++----
 .../element-components/dropdown.component.ts      |  9 ++++++---
 .../common/element-components/image.component.ts  |  8 +++++---
 .../radio-button-group.component.ts               | 11 +++++++----
 .../element-components/text-field.component.ts    | 15 +++++++++------
 .../common/element-components/text.component.ts   |  8 +++++---
 .../common/element-components/video.component.ts  |  8 +++++---
 ...ive.ts => form-element-component.directive.ts} |  4 ++--
 .../canvas/canvas-drag-overlay.component.ts       |  2 +-
 .../app/components/element-overlay.component.ts   | 15 ++++++++-------
 14 files changed, 74 insertions(+), 49 deletions(-)
 rename projects/common/{canvas-element-component.directive.ts => form-element-component.directive.ts} (93%)

diff --git a/projects/common/component-utils.ts b/projects/common/component-utils.ts
index 66ef178ba..535f412b0 100644
--- a/projects/common/component-utils.ts
+++ b/projects/common/component-utils.ts
@@ -1,5 +1,4 @@
 import { ComponentFactory, ComponentFactoryResolver } from '@angular/core';
-import { FormElementComponent } from './canvas-element-component.directive';
 import { TextComponent } from './element-components/text.component';
 import { ButtonComponent } from './element-components/button.component';
 import { TextFieldComponent } from './element-components/text-field.component';
@@ -12,9 +11,9 @@ import { VideoComponent } from './element-components/video.component';
 import { CorrectionComponent } from './element-components/compound-components/correction.component';
 
 export function getComponentFactory(
-  elementType: string,
-  componentFactoryResolver: ComponentFactoryResolver
-): ComponentFactory<FormElementComponent> {
+  elementType: string, componentFactoryResolver: ComponentFactoryResolver
+): ComponentFactory<any> {
+  // TODO: Find better solution than any
   switch (elementType) {
     case 'text':
       return componentFactoryResolver.resolveComponentFactory(TextComponent);
diff --git a/projects/common/element-components/audio.component.ts b/projects/common/element-components/audio.component.ts
index 74363e230..40673b54a 100644
--- a/projects/common/element-components/audio.component.ts
+++ b/projects/common/element-components/audio.component.ts
@@ -1,16 +1,17 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../canvas-element-component.directive';
+import { AudioElement } from '../unit';
 
 @Component({
   selector: 'app-audio',
   template: `
       <div>
-          <audio controls src="{{$any(elementModel).src}}"></audio>
+          <audio controls src="{{elementModel.src}}"></audio>
       </div>
   `,
   styles: [
     'div {display: inline-block; border: 5px solid; padding: 12px 9px 9px 9px;}'
   ]
 })
-export class AudioComponent extends FormElementComponent {
+export class AudioComponent {
+  elementModel!: AudioElement;
 }
diff --git a/projects/common/element-components/button.component.ts b/projects/common/element-components/button.component.ts
index 876e3e3a0..197fdd0ad 100644
--- a/projects/common/element-components/button.component.ts
+++ b/projects/common/element-components/button.component.ts
@@ -1,5 +1,5 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../canvas-element-component.directive';
+import { ButtonElement } from '../unit';
 
 @Component({
   selector: 'app-button',
@@ -14,8 +14,10 @@ import { FormElementComponent } from '../canvas-element-component.directive';
             [style.font-weight]="elementModel.bold ? 'bold' : ''"
             [style.font-style]="elementModel.italic ? 'italic' : ''"
             [style.text-decoration]="elementModel.underline ? 'underline' : ''">
-      {{$any(elementModel).label}}
+      {{elementModel.label}}
     </button>
   `
 })
-export class ButtonComponent extends FormElementComponent { }
+export class ButtonComponent {
+  elementModel!: ButtonElement;
+}
diff --git a/projects/common/element-components/checkbox.component.ts b/projects/common/element-components/checkbox.component.ts
index 552b07219..c68db4f50 100644
--- a/projects/common/element-components/checkbox.component.ts
+++ b/projects/common/element-components/checkbox.component.ts
@@ -1,5 +1,6 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../canvas-element-component.directive';
+import { CheckboxElement } from '../unit';
+import { FormElementComponent } from '../form-element-component.directive';
 
 @Component({
   selector: 'app-checkbox',
@@ -15,8 +16,10 @@ import { FormElementComponent } from '../canvas-element-component.directive';
                     [style.font-weight]="elementModel.bold ? 'bold' : ''"
                     [style.font-style]="elementModel.italic ? 'italic' : ''"
                     [style.text-decoration]="elementModel.underline ? 'underline' : ''">
-          {{$any(elementModel).label}}
+          {{elementModel.label}}
       </mat-checkbox>
   `
 })
-export class CheckboxComponent extends FormElementComponent { }
+export class CheckboxComponent extends FormElementComponent {
+  elementModel!: CheckboxElement;
+}
diff --git a/projects/common/element-components/compound-components/correction.component.ts b/projects/common/element-components/compound-components/correction.component.ts
index 7ff85ce43..a8743f85d 100644
--- a/projects/common/element-components/compound-components/correction.component.ts
+++ b/projects/common/element-components/compound-components/correction.component.ts
@@ -1,5 +1,6 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../../canvas-element-component.directive';
+import { CompoundElementCorrection } from '../../unit';
+import { FormElementComponent } from '../../form-element-component.directive';
 
 @Component({
   selector: 'app-correction',
@@ -8,13 +9,14 @@ import { FormElementComponent } from '../../canvas-element-component.directive';
       <p>
         {{$any(elementModel).text}}
       </p>
-      <div *ngFor="let sentence of $any(elementModel).sentences"
+      <div *ngFor="let sentence of elementModel.sentences"
            fxLayout="column">
         <div fxLayout="row">
           <div *ngFor="let word of sentence.split(' ');"
                fxLayout="column">
               <mat-form-field>
-              <input matInput type="text">
+              <input matInput type="text"
+                     [formControl]="formControl">
               </mat-form-field>
               <div>
                   {{word}}
@@ -28,4 +30,6 @@ import { FormElementComponent } from '../../canvas-element-component.directive';
     'mat-form-field {margin: 5px}'
   ]
 })
-export class CorrectionComponent extends FormElementComponent { }
+export class CorrectionComponent extends FormElementComponent {
+  elementModel!: CompoundElementCorrection;
+}
diff --git a/projects/common/element-components/dropdown.component.ts b/projects/common/element-components/dropdown.component.ts
index 7c56c4657..fa6a6544c 100644
--- a/projects/common/element-components/dropdown.component.ts
+++ b/projects/common/element-components/dropdown.component.ts
@@ -1,5 +1,6 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../canvas-element-component.directive';
+import { DropdownElement } from '../unit';
+import { FormElementComponent } from '../form-element-component.directive';
 
 @Component({
   selector: 'app-dropdown',
@@ -17,11 +18,13 @@ import { FormElementComponent } from '../canvas-element-component.directive';
             {{$any(elementModel).label}}
           </mat-label>
           <mat-select [formControl]="formControl">
-              <mat-option *ngFor="let option of $any(elementModel).options" [value]="option">
+              <mat-option *ngFor="let option of elementModel.options" [value]="option">
                   {{option}}
               </mat-option>
           </mat-select>
       </mat-form-field>
   `
 })
-export class DropdownComponent extends FormElementComponent { }
+export class DropdownComponent extends FormElementComponent {
+  elementModel!: DropdownElement;
+}
diff --git a/projects/common/element-components/image.component.ts b/projects/common/element-components/image.component.ts
index ca838ebf2..ead36c470 100644
--- a/projects/common/element-components/image.component.ts
+++ b/projects/common/element-components/image.component.ts
@@ -1,10 +1,12 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../canvas-element-component.directive';
+import { ImageElement } from '../unit';
 
 @Component({
   selector: 'app-image',
   template: `
-      <img src="{{$any(elementModel).src}}" alt="Image Placeholder">
+      <img src="{{elementModel.src}}" alt="Image Placeholder">
   `
 })
-export class ImageComponent extends FormElementComponent { }
+export class ImageComponent {
+  elementModel!: ImageElement;
+}
diff --git a/projects/common/element-components/radio-button-group.component.ts b/projects/common/element-components/radio-button-group.component.ts
index 88bf5c471..c63d43453 100644
--- a/projects/common/element-components/radio-button-group.component.ts
+++ b/projects/common/element-components/radio-button-group.component.ts
@@ -1,5 +1,6 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../canvas-element-component.directive';
+import { RadioButtonGroupElement } from '../unit';
+import { FormElementComponent } from '../form-element-component.directive';
 
 @Component({
   selector: 'app-radio-button-group',
@@ -13,14 +14,16 @@ import { FormElementComponent } from '../canvas-element-component.directive';
            [style.font-weight]="elementModel.bold ? 'bold' : ''"
            [style.font-style]="elementModel.italic ? 'italic' : ''"
            [style.text-decoration]="elementModel.underline ? 'underline' : ''">
-          <label id="radio-group-label">{{$any(elementModel).label}}</label>
+          <label id="radio-group-label">{{elementModel.text}}</label>
           <mat-radio-group aria-labelledby="radio-group-label" fxLayout="{{elementModel.alignment}}"
                            [formControl]="formControl">
-              <mat-radio-button *ngFor="let option of $any(elementModel).options" [value]="option">
+              <mat-radio-button *ngFor="let option of elementModel.options" [value]="option">
                   {{option}}
               </mat-radio-button>
           </mat-radio-group>
       </div>
   `
 })
-export class RadioButtonGroupComponent extends FormElementComponent { }
+export class RadioButtonGroupComponent extends FormElementComponent {
+  elementModel!: RadioButtonGroupElement;
+}
diff --git a/projects/common/element-components/text-field.component.ts b/projects/common/element-components/text-field.component.ts
index 7cb6d0617..3b4278920 100644
--- a/projects/common/element-components/text-field.component.ts
+++ b/projects/common/element-components/text-field.component.ts
@@ -1,14 +1,15 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../canvas-element-component.directive';
+import { TextFieldElement } from '../unit';
+import { FormElementComponent } from '../form-element-component.directive';
 
 @Component({
   selector: 'app-text-field',
   template: `
-    <input *ngIf="$any(elementModel).multiline === false" matInput
-           placeholder="{{$any(elementModel).placeholder}}"
+    <input *ngIf="elementModel.multiline === false" matInput
+           placeholder="{{elementModel.placeholder}}"
            [formControl]="formControl">
-    <textarea *ngIf="$any(elementModel).multiline === true" matInput
-              placeholder="{{$any(elementModel).placeholder}}"
+    <textarea *ngIf="elementModel.multiline === true" matInput
+              placeholder="{{elementModel.placeholder}}"
               [formControl]="formControl"
               [style.width.px]="elementModel.width"
               [style.height.px]="elementModel.height"
@@ -22,4 +23,6 @@ import { FormElementComponent } from '../canvas-element-component.directive';
     </textarea>
   `
 })
-export class TextFieldComponent extends FormElementComponent { }
+export class TextFieldComponent extends FormElementComponent {
+  elementModel!: TextFieldElement;
+}
diff --git a/projects/common/element-components/text.component.ts b/projects/common/element-components/text.component.ts
index 754ab8a4c..6f292e034 100644
--- a/projects/common/element-components/text.component.ts
+++ b/projects/common/element-components/text.component.ts
@@ -1,5 +1,5 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../canvas-element-component.directive';
+import { TextElement } from '../unit';
 
 @Component({
   selector: 'app-text',
@@ -14,8 +14,10 @@ import { FormElementComponent } from '../canvas-element-component.directive';
            [style.font-style]="elementModel.italic ? 'italic' : ''"
            [style.text-decoration]="elementModel.underline ? 'underline' : ''"
            [style.white-space]="'pre-wrap'">
-          {{$any(elementModel).text}}
+          {{elementModel.text}}
       </div>
   `
 })
-export class TextComponent extends FormElementComponent { }
+export class TextComponent {
+  elementModel!: TextElement;
+}
diff --git a/projects/common/element-components/video.component.ts b/projects/common/element-components/video.component.ts
index 6f3177424..4d41b60a5 100644
--- a/projects/common/element-components/video.component.ts
+++ b/projects/common/element-components/video.component.ts
@@ -1,15 +1,17 @@
 import { Component } from '@angular/core';
-import { FormElementComponent } from '../canvas-element-component.directive';
+import { VideoElement } from '../unit';
 
 @Component({
   selector: 'app-video',
   template: `
       <div>
-          <video controls src="{{$any(elementModel).src}}"></video>
+          <video controls src="{{elementModel.src}}"></video>
       </div>
   `,
   styles: [
     'div {display: inline-block;border: 5px solid; padding: 12px 9px 9px 9px}'
   ]
 })
-export class VideoComponent extends FormElementComponent { }
+export class VideoComponent {
+  elementModel!: VideoElement;
+}
diff --git a/projects/common/canvas-element-component.directive.ts b/projects/common/form-element-component.directive.ts
similarity index 93%
rename from projects/common/canvas-element-component.directive.ts
rename to projects/common/form-element-component.directive.ts
index e18b09032..3811b31dd 100644
--- a/projects/common/canvas-element-component.directive.ts
+++ b/projects/common/form-element-component.directive.ts
@@ -7,9 +7,8 @@ import { FormService } from './form.service';
 @Directive()
 export abstract class FormElementComponent implements OnInit {
   elementModel!: UnitUIElement;
-  formControl!: FormControl;
-  style!: Record<string, string>;
   parentForm!: FormGroup;
+  formControl: FormControl = new FormControl();
 
   constructor(private formService: FormService) { }
 
@@ -24,6 +23,7 @@ export abstract class FormElementComponent implements OnInit {
   }
 
   private getFormControl(id: string): FormControl {
+    // workaround for editor
     return (this.parentForm) ? this.parentForm.controls[id] as FormControl : new FormControl();
   }
 
diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-drag-overlay.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-drag-overlay.component.ts
index 1f6f8156d..a9b799c02 100644
--- a/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-drag-overlay.component.ts
+++ b/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-drag-overlay.component.ts
@@ -2,7 +2,7 @@ import {
   Component, OnInit, Input, Output, EventEmitter, ComponentFactoryResolver, ViewChild, ViewContainerRef
 } from '@angular/core';
 import { UnitUIElement } from '../../../../../../../common/unit';
-import { FormElementComponent } from '../../../../../../../common/canvas-element-component.directive';
+import { FormElementComponent } from '../../../../../../../common/form-element-component.directive';
 import * as ComponentUtils from '../../../../../../../common/component-utils';
 
 @Component({
diff --git a/projects/player/src/app/components/element-overlay.component.ts b/projects/player/src/app/components/element-overlay.component.ts
index 6698086ba..44f4e33b9 100644
--- a/projects/player/src/app/components/element-overlay.component.ts
+++ b/projects/player/src/app/components/element-overlay.component.ts
@@ -1,10 +1,10 @@
 import {
-  Component, ComponentFactory, ComponentFactoryResolver, Input, OnInit, ViewChild, ViewContainerRef
+  Component, ComponentFactoryResolver, Input, OnInit, ViewChild, ViewContainerRef
 } from '@angular/core';
 import { FormGroup } from '@angular/forms';
 import { UnitUIElement } from '../../../../common/unit';
-import { FormElementComponent } from '../../../../common/canvas-element-component.directive';
 import * as ComponentUtils from '../../../../common/component-utils';
+import { FormElementComponent } from '../../../../common/form-element-component.directive';
 
 @Component({
   selector: 'app-element-overlay',
@@ -24,11 +24,12 @@ export class ElementOverlayComponent implements OnInit {
   constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
 
   ngOnInit(): void {
-    const componentFactory: ComponentFactory<FormElementComponent> =
-      ComponentUtils.getComponentFactory(this.element.type, this.componentFactoryResolver);
-    const childComponent: FormElementComponent =
-      this.elementContainer.createComponent(componentFactory).instance;
+    const componentFactory = ComponentUtils.getComponentFactory(this.element.type, this.componentFactoryResolver);
+    const childComponent = this.elementContainer.createComponent(componentFactory).instance;
     childComponent.elementModel = this.element;
-    childComponent.parentForm = this.parentForm;
+
+    if (childComponent instanceof FormElementComponent) {
+      childComponent.parentForm = this.parentForm;
+    }
   }
 }
-- 
GitLab