Repository: vmware-tanzu/octant
Pull request #2214 (2021-03-24 16:33:15)

Revert dynamic component update change 
Reverting the dynamic component update change introduced in #2212 because further testing showed it was causing unwanted screen updates. 

The original problem that change was trying to fix ([missing heptagon indicators](https://github.com/vmware-tanzu/octant/issues/2215)) will be addressed in 0.19.  

Signed-off-by: Milan Klanjsek mklanjsek@pivotal.io



Patch:
diff --git a/changelogs/unreleased/2017-lenriquez b/changelogs/unreleased/2017-lenriquez
deleted file mode 100644
index 3cf51030..00000000
--- a/changelogs/unreleased/2017-lenriquez
+++ /dev/null
@@ -1,1 +0,0 @@
-Allow UI validators to set constraints on Forms 
\ No newline at end of file
diff --git a/pkg/view/component/base.go b/pkg/view/component/base.go
index d77912b3..3eb199de 100644
--- a/pkg/view/component/base.go
+++ b/pkg/view/component/base.go
@@ -86,8 +86,6 @@ const (
 	TypeTimestamp = "timestamp"
 	// TypeYAML is a YAML component.
 	TypeYAML = "yaml"
-	// TypeIcon is a Icon component.
-	TypeIcon = "icon"
 )
 
 // Base is an abstract base for components..
diff --git a/pkg/view/component/form.go b/pkg/view/component/form.go
index 327de8ba..01c132b3 100644
--- a/pkg/view/component/form.go
+++ b/pkg/view/component/form.go
@@ -24,20 +24,6 @@ const (
 	FieldTypeHidden   = "hidden"
 )
 
-type FormValidator string
-
-const (
-	FormValidatorMin           FormValidator = "min"
-	FormValidatorMax           FormValidator = "max"
-	FormValidatorRequired      FormValidator = "required"
-	FormValidatorRequiredTrue  FormValidator = "requiredTrue"
-	FormValidatorEmail         FormValidator = "email"
-	FormValidatorMinLength     FormValidator = "minLength"
-	FormValidatorMaxLength     FormValidator = "maxLength"
-	FormValidatorPattern       FormValidator = "pattern"
-	FormValidatorNullValidator FormValidator = "nullValidator"
-)
-
 type InputChoice struct {
 	Label   string `json:"label"`
 	Value   string `json:"value"`
@@ -50,7 +36,7 @@ type BaseFormField struct {
 	fieldType    string
 	placeholder  string
 	errorMessage string
-	validators   map[FormValidator]interface{}
+	validators   []string
 }
 
 func newBaseFormField(label, name, fieldType string) *BaseFormField {
@@ -81,7 +67,7 @@ func (bff *BaseFormField) Error() string {
 	return bff.errorMessage
 }
 
-func (bff *BaseFormField) Validators() map[FormValidator]interface{} {
+func (bff *BaseFormField) Validators() []string {
 	return bff.validators
 }
 
@@ -95,7 +81,7 @@ type FormField interface {
 	Value() interface{}
 	Placeholder() string
 	Error() string
-	Validators() map[FormValidator]interface{}
+	Validators() []string
 
 	MarshalJSON() ([]byte, error)
 	UnmarshalJSON([]byte) error
@@ -154,18 +140,18 @@ func (ff *FormFieldCheckBox) Value() interface{} {
 }
 
 // AddValidator adds validator(s)
-func (ff *FormFieldCheckBox) AddValidator(errorMessage string, validators map[FormValidator]interface{}) {
+func (ff *FormFieldCheckBox) AddValidator(errorMessage string, validators []string) {
 	ff.errorMessage = errorMessage
 	ff.validators = validators
 }
 
 func (ff *FormFieldCheckBox) UnmarshalJSON(data []byte) error {
 	x := struct {
-		Label         string                        `json:"label"`
-		Name          string                        `json:"name"`
-		Type          string                        `json:"type"`
-		Error         string                        `json:"error"`
-		Validators    map[FormValidator]interface{} `json:"validators"`
+		Label         string   `json:"label"`
+		Name          string   `json:"name"`
+		Type          string   `json:"type"`
+		Error         string   `json:"error"`
+		Validators    []string `json:"validators"`
 		Configuration struct {
 			Choices []InputChoice
 		} `json:"configuration"`
@@ -221,18 +207,18 @@ func (ff *FormFieldRadio) Value() interface{} {
 }
 
 // AddValidator adds validator(s)
-func (ff *FormFieldRadio) AddValidator(errorMessage string, validators map[FormValidator]interface{}) {
+func (ff *FormFieldRadio) AddValidator(errorMessage string, validators []string) {
 	ff.errorMessage = errorMessage
 	ff.validators = validators
 }
 
 func (ff *FormFieldRadio) UnmarshalJSON(data []byte) error {
 	x := struct {
-		Label         string                        `json:"label"`
-		Name          string                        `json:"name"`
-		Type          string                        `json:"type"`
-		Error         string                        `json:"error"`
-		Validators    map[FormValidator]interface{} `json:"validators"`
+		Label         string   `json:"label"`
+		Name          string   `json:"name"`
+		Type          string   `json:"type"`
+		Error         string   `json:"error"`
+		Validators    []string `json:"validators"`
 		Configuration struct {
 			Choices []InputChoice
 		} `json:"configuration"`
@@ -282,7 +268,7 @@ func (ff *FormFieldText) MarshalJSON() ([]byte, error) {
 }
 
 // AddValidator adds validator(s)
-func (ff *FormFieldText) AddValidator(placeholder string, errorMessage string, validators map[FormValidator]interface{}) {
+func (ff *FormFieldText) AddValidator(placeholder string, errorMessage string, validators []string) {
 	ff.placeholder = placeholder
 	ff.errorMessage = errorMessage
 	ff.validators = validators
@@ -290,14 +276,14 @@ func (ff *FormFieldText) AddValidator(placeholder string, errorMessage string, v
 
 func (ff *FormFieldText) UnmarshalJSON(data []byte) error {
 	x := struct {
-		Label         string                        `json:"label"`
-		Name          string                        `json:"name"`
-		Type          string                        `json:"type"`
-		Configuration map[string]interface{}        `json:"configuration"`
-		Value         string                        `json:"value"`
-		Placeholder   string                        `json:"placeholder"`
-		Error         string                        `json:"error"`
-		Validators    map[FormValidator]interface{} `json:"validators"`
+		Label         string                 `json:"label"`
+		Name          string                 `json:"name"`
+		Type          string                 `json:"type"`
+		Configuration map[string]interface{} `json:"configuration"`
+		Value         string                 `json:"value"`
+		Placeholder   string                 `json:"placeholder"`
+		Error         string                 `json:"error"`
+		Validators    []string               `json:"validators"`
 	}{}
 
 	if err := json.Unmarshal(data, &x); err != nil {
@@ -338,7 +324,7 @@ func (ff *FormFieldPassword) Value() interface{} {
 }
 
 // AddValidator adds validator(s)
-func (ff *FormFieldPassword) AddValidator(placeholder string, errorMessage string, validators map[FormValidator]interface{}) {
+func (ff *FormFieldPassword) AddValidator(placeholder string, errorMessage string, validators []string) {
 	ff.placeholder = placeholder
 	ff.errorMessage = errorMessage
 	ff.validators = validators
@@ -350,14 +336,14 @@ func (ff *FormFieldPassword) MarshalJSON() ([]byte, error) {
 
 func (ff *FormFieldPassword) UnmarshalJSON(data []byte) error {
 	x := struct {
-		Label         string                        `json:"label"`
-		Name          string                        `json:"name"`
-		Type          string                        `json:"type"`
-		Configuration map[string]interface{}        `json:"configuration"`
-		Value         string                        `json:"value"`
-		Placeholder   string                        `json:"placeholder"`
-		Error         string                        `json:"error"`
-		Validators    map[FormValidator]interface{} `json:"validators"`
+		Label         string                 `json:"label"`
+		Name          string                 `json:"name"`
+		Type          string                 `json:"type"`
+		Configuration map[string]interface{} `json:"configuration"`
+		Value         string                 `json:"value"`
+		Placeholder   string                 `json:"placeholder"`
+		Error         string                 `json:"error"`
+		Validators    []string               `json:"validators"`
 	}{}
 
 	if err := json.Unmarshal(data, &x); err != nil {
@@ -397,7 +383,7 @@ func (ff *FormFieldNumber) Value() interface{} {
 }
 
 // AddValidator adds validator(s)
-func (ff *FormFieldNumber) AddValidator(errorMessage string, validators map[FormValidator]interface{}) {
+func (ff *FormFieldNumber) AddValidator(errorMessage string, validators []string) {
 	ff.errorMessage = errorMessage
 	ff.validators = validators
 }
@@ -408,13 +394,13 @@ func (ff *FormFieldNumber) MarshalJSON() ([]byte, error) {
 
 func (ff *FormFieldNumber) UnmarshalJSON(data []byte) error {
 	x := struct {
-		Label         string                        `json:"label"`
-		Name          string                        `json:"name"`
-		Type          string                        `json:"type"`
-		Configuration map[string]interface{}        `json:"configuration"`
-		Value         string                        `json:"value"`
-		Error         string                        `json:"error"`
-		Validators    map[FormValidator]interface{} `json:"validators"`
+		Label         string                 `json:"label"`
+		Name          string                 `json:"name"`
+		Type          string                 `json:"type"`
+		Configuration map[string]interface{} `json:"configuration"`
+		Value         string                 `json:"value"`
+		Error         string                 `json:"error"`
+		Validators    []string               `json:"validators"`
 	}{}
 
 	if err := json.Unmarshal(data, &x); err != nil {
@@ -473,7 +459,7 @@ func (ff *FormFieldSelect) Value() interface{} {
 }
 
 // AddValidator adds validator(s)
-func (ff *FormFieldSelect) AddValidator(errorMessage string, validators map[FormValidator]interface{}) {
+func (ff *FormFieldSelect) AddValidator(errorMessage string, validators []string) {
 	ff.errorMessage = errorMessage
 	ff.validators = validators
 }
@@ -484,11 +470,11 @@ func (ff *FormFieldSelect) MarshalJSON() ([]byte, error) {
 
 func (ff *FormFieldSelect) UnmarshalJSON(data []byte) error {
 	x := struct {
-		Label         string                        `json:"label"`
-		Name          string                        `json:"name"`
-		Type          string                        `json:"type"`
-		Error         string                        `json:"error"`
-		Validators    map[FormValidator]interface{} `json:"validators"`
+		Label         string   `json:"label"`
+		Name          string   `json:"name"`
+		Type          string   `json:"type"`
+		Error         string   `json:"error"`
+		Validators    []string `json:"validators"`
 		Configuration struct {
 			Choices  []InputChoice `json:"choices"`
 			Multiple bool          `json:"multiple"`
@@ -532,7 +518,7 @@ func (ff *FormFieldTextarea) Value() interface{} {
 }
 
 // AddValidator adds validator(s)
-func (ff *FormFieldTextarea) AddValidator(placeholder string, errorMessage string, validators map[FormValidator]interface{}) {
+func (ff *FormFieldTextarea) AddValidator(placeholder string, errorMessage string, validators []string) {
 	ff.placeholder = placeholder
 	ff.errorMessage = errorMessage
 	ff.validators = validators
@@ -544,14 +530,14 @@ func (ff *FormFieldTextarea) MarshalJSON() ([]byte, error) {
 
 func (ff *FormFieldTextarea) UnmarshalJSON(data []byte) error {
 	x := struct {
-		Label         string                        `json:"label"`
-		Name          string                        `json:"name"`
-		Type          string                        `json:"type"`
-		Configuration map[string]interface{}        `json:"configuration"`
-		Value         string                        `json:"value"`
-		Placeholder   string                        `json:"placeholder"`
-		Error         string                        `json:"error"`
-		Validators    map[FormValidator]interface{} `json:"validators"`
+		Label         string                 `json:"label"`
+		Name          string                 `json:"name"`
+		Type          string                 `json:"type"`
+		Configuration map[string]interface{} `json:"configuration"`
+		Value         string                 `json:"value"`
+		Placeholder   string                 `json:"placeholder"`
+		Error         string                 `json:"error"`
+		Validators    []string               `json:"validators"`
 	}{}
 
 	if err := json.Unmarshal(data, &x); err != nil {
@@ -591,7 +577,7 @@ func (ff *FormFieldHidden) Value() interface{} {
 }
 
 // AddValidator adds validator(s)
-func (ff *FormFieldHidden) AddValidator(placeholder string, errorMessage string, validators map[FormValidator]interface{}) {
+func (ff *FormFieldHidden) AddValidator(placeholder string, errorMessage string, validators []string) {
 	ff.placeholder = placeholder
 	ff.errorMessage = errorMessage
 	ff.validators = validators
@@ -603,14 +589,14 @@ func (ff *FormFieldHidden) MarshalJSON() ([]byte, error) {
 
 func (ff *FormFieldHidden) UnmarshalJSON(data []byte) error {
 	x := struct {
-		Label         string                        `json:"label"`
-		Name          string                        `json:"name"`
-		Type          string                        `json:"type"`
-		Configuration map[string]interface{}        `json:"configuration"`
-		Value         string                        `json:"value"`
-		Placeholder   string                        `json:"placeholder"`
-		Error         string                        `json:"error"`
-		Validators    map[FormValidator]interface{} `json:"validators"`
+		Label         string                 `json:"label"`
+		Name          string                 `json:"name"`
+		Type          string                 `json:"type"`
+		Configuration map[string]interface{} `json:"configuration"`
+		Value         string                 `json:"value"`
+		Placeholder   string                 `json:"placeholder"`
+		Error         string                 `json:"error"`
+		Validators    []string               `json:"validators"`
 	}{}
 
 	if err := json.Unmarshal(data, &x); err != nil {
@@ -666,7 +652,7 @@ func (f *Form) UnmarshalJSON(data []byte) error {
 			Value         interface{}            `json:"value"`
 			Placeholder   string                 `json:"placeholder"`
 			Error         string                 `json:"error"`
-			Validators    map[string]interface{} `json:"validators"`
+			Validators    []string               `json:"validators"`
 		} `json:"fields"`
 		Action string `json:"action,omitempty"`
 	}{}
diff --git a/pkg/view/component/icon.go b/pkg/view/component/icon.go
deleted file mode 100644
index 8b80dfbf..00000000
--- a/pkg/view/component/icon.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package component
-
-import (
-	"github.com/vmware-tanzu/octant/internal/util/json"
-)
-
-// WARNING: This is using version on clarity 4.0.12 but
-// this is built using the API of version 5 is not expected to change the the version
-// but is good to know :)
-
-type Icon struct {
-	Base
-	Config IconConfig `json:"config"`
-}
-
-type IconConfig struct {
-	Shape     string    `json:"shape"`
-	Size      string    `json:"size"`
-	Direction Direction `json:"direction"`
-	Flip      Flip      `json:"flip"`
-	Solid     bool      `json:"solid"`
-	Status    Status    `json:"status"`
-	Inverse   bool      `json:"inverse"`
-	Badge     Badge     `json:"badge"`
-	Color     string    `json:"color"`
-}
-
-type Direction string
-
-const (
-	DirectionUp    Direction = "up"
-	DirectionDown  Direction = "down"
-	DirectionLeft  Direction = "left"
-	DirectionRight Direction = "right"
-)
-
-type Flip string
-
-const (
-	FlipHorizontal Flip = "horizontal"
-	FlipVertical   Flip = "vertical"
-)
-
-type Status string
-
-const (
-	StatusInfo    Status = "info"
-	StatusSuccess Status = "success"
-	StatusWarning Status = "warning"
-	StatusDanger  Status = "danger"
-)
-
-type Badge string
-
-const (
-	BadgeInfo            Badge = "info"
-	BadgeSuccess         Badge = "success"
-	BadgeWarningTriangle Badge = "warning-triangle"
-	BadgeDanger          Badge = "danger"
-	// BadgeWarning         Badge = "warning" just for clarity 5
-	// BadgeInherit         Badge = "inherit" just for clarity 5
-	// BadgeInheritTriangle Badge = "inherit-triangle" just for clarity 5
-)
-
-func NewIcon(shape string) *Icon {
-	return &Icon{
-		Base: newBase(TypeIcon, nil),
-		Config: IconConfig{
-			Shape: shape,
-		},
-	}
-}
-
-type iconMarshal Icon
-
-func (i *Icon) MarshalJSON() ([]byte, error) {
-	m := iconMarshal{
-		Base:   i.Base,
-		Config: i.Config,
-	}
-	m.Metadata.Type = TypeIcon
-
-	return json.Marshal(&m)
-}
diff --git a/pkg/view/component/unmarshal.go b/pkg/view/component/unmarshal.go
index c4969637..e2f17167 100644
--- a/pkg/view/component/unmarshal.go
+++ b/pkg/view/component/unmarshal.go
@@ -186,11 +186,7 @@ func unmarshal(to TypedObject) (Component, error) {
 		err = errors.Wrapf(json.Unmarshal(to.Config, &t.Config),
 			"unmarshal timestamp config")
 		o = t
-	case TypeIcon:
-		t := &Icon{Base: Base{Metadata: to.Metadata}}
-		err = errors.Wrapf(json.Unmarshal(to.Config, &t.Config),
-			"unmarshal timestamp config")
-		o = t
+
 	default:
 		return nil, errors.Errorf("unknown view component %q", to.Metadata.Type)
 	}
diff --git a/web/src/app/modules/shared/components/presentation/form/form.component.ts b/web/src/app/modules/shared/components/presentation/form/form.component.ts
index 61eb0cd0..ec389328 100644
--- a/web/src/app/modules/shared/components/presentation/form/form.component.ts
+++ b/web/src/app/modules/shared/components/presentation/form/form.component.ts
@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: Apache-2.0
 //
 
-import { Component, Input, OnInit } from '@angular/core';
+import { Component, Input, OnInit, Output } from '@angular/core';
 import { ActionField, ActionForm } from '../../../models/content';
 import {
   FormArray,
@@ -30,17 +30,7 @@ export class FormComponent implements OnInit {
 
   formGroup: FormGroup;
   formArray: FormArray;
-  needParams = {
-    min: true,
-    max: true,
-    minLength: true,
-    maxLength: true,
-    pattern: true,
-    require: false,
-    requireTrue: false,
-    email: false,
-    nullValidator: false,
-  };
+
   constructor(private formBuilder: FormBuilder) {}
 
   ngOnInit() {
@@ -78,31 +68,15 @@ export class FormComponent implements OnInit {
     }
   }
 
-  getValidators(validators: { string: any }): ValidatorFn[] {
-    if (!validators) {
-      return [];
-    }
-
-    const vFn: ValidatorFn[] = [];
-    const keys = Object.keys(validators);
-    for (const key of keys) {
-      const value = validators[key];
-
-      // Check if function is expected
-      if (this.needParams[key] === undefined) {
-        console.error('Unknown validation for form');
-        continue;
-      }
-
-      // Verify how many params needs
-      if (this.needParams[key]) {
-        vFn.push(Validators[key](value));
-      } else {
-        vFn.push(Validators[key]);
-      }
+  getValidators(validators: string[]): ValidatorFn[] {
+    if (validators) {
+      const vFn: ValidatorFn[] = [];
+      validators.forEach(v => {
+        vFn.push(Validators[v]);
+      });
+      return vFn;
     }
-
-    return vFn;
+    return [];
   }
 
   fieldChoices(field: ActionField) {
diff --git a/web/src/app/modules/shared/components/presentation/icon/icon.component.html b/web/src/app/modules/shared/components/presentation/icon/icon.component.html
deleted file mode 100644
index 70f1178b..00000000
--- a/web/src/app/modules/shared/components/presentation/icon/icon.component.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<clr-icon
-  [attr.shape]="shape"
-  [attr.style]="styleAttr"
-  [attr.class]="classAttr"
-  [attr.flip]="flip"
-  [attr.size]="size"
-></clr-icon>
-
diff --git a/web/src/app/modules/shared/components/presentation/icon/icon.component.scss b/web/src/app/modules/shared/components/presentation/icon/icon.component.scss
deleted file mode 100644
index e69de29b..00000000
diff --git a/web/src/app/modules/shared/components/presentation/icon/icon.component.spec.ts b/web/src/app/modules/shared/components/presentation/icon/icon.component.spec.ts
deleted file mode 100644
index a833e3a5..00000000
--- a/web/src/app/modules/shared/components/presentation/icon/icon.component.spec.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { IconComponent } from './icon.component';
-
-describe('IconComponent', () => {
-  let component: IconComponent;
-  let fixture: ComponentFixture<IconComponent>;
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [IconComponent],
-    }).compileComponents();
-  });
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(IconComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/web/src/app/modules/shared/components/presentation/icon/icon.component.ts b/web/src/app/modules/shared/components/presentation/icon/icon.component.ts
deleted file mode 100644
index aea9130c..00000000
--- a/web/src/app/modules/shared/components/presentation/icon/icon.component.ts
+++ /dev/null
@@ -1,115 +0,0 @@
-import {
-  ChangeDetectionStrategy,
-  ChangeDetectorRef,
-  Component,
-} from '@angular/core';
-import { AbstractViewComponent } from '../../abstract-view/abstract-view.component';
-import { IconView } from '../../../models/content';
-
-@Component({
-  selector: 'app-view-icon',
-  templateUrl: './icon.component.html',
-  styleUrls: ['./icon.component.scss'],
-  changeDetection: ChangeDetectionStrategy.OnPush,
-})
-export class IconComponent extends AbstractViewComponent<IconView> {
-  shape: string;
-  flip: string;
-  size: string;
-
-  styleAttr = '';
-  classAttr = '';
-
-  sizeHash = { sm: '16', md: '24', lg: '36"', xl: '48', xxl: '64' };
-  directionHash = {
-    up: 'transform: rotate(0deg);',
-    right: 'transform: rotate(90deg);',
-    down: 'transform: rotate(180deg);',
-    left: 'transform: rotate(270deg);',
-  };
-  statusHash = {
-    info: 'is-info ',
-    success: 'is-success ',
-    warning: 'is-warning ',
-    danger: 'is-error ',
-  };
-  badge = {
-    info: 'has-badge--info ',
-    success: 'has-badge--success ',
-    danger: 'has-badge ',
-    'warning-triangle': 'has-alert ',
-  };
-
-  constructor(private cdr: ChangeDetectorRef) {
-    super();
-  }
-
-  // This will work for version 5 of clarity but we are using
-  // version 4 so function are been added to map the differences
-  // dir needs to be change to direction on the template
-  protected update(): void {
-    const view = this.v;
-
-    // reset values to be re-calculated
-    this.styleAttr = '';
-    this.classAttr = '';
-
-    this.shape = view.config.shape;
-    this.flip = view.config.flip;
-    this.mapSize(view.config.size);
-    this.mapDirection(view.config.direction);
-    this.mapSolid(view.config.solid);
-    this.mapStatus(view.config.status);
-    this.mapInverse(view.config.inverse);
-    this.mapBadge(view.config.badge);
-    if (view.config.status === '' || !view.config.status) {
-      this.setColor(view.config.color);
-    }
-
-    this.cdr.markForCheck();
-  }
-
-  mapSize(size: string): string {
-    if (!size || size === '') {
-      return;
-    }
-    this.size = this.sizeHash[size] || size;
-  }
-
-  mapDirection(direction: string) {
-    if (!direction || direction === '') {
-      return;
-    }
-    this.styleAttr += this.directionHash[direction] || '';
-  }
-
-  mapSolid(isSolid: boolean) {
-    this.classAttr += isSolid ? 'is-solid ' : '';
-  }
-
-  mapStatus(status: string) {
-    if (!status || status === '') {
-      return;
-    }
-    this.classAttr += this.statusHash[status] || '';
-  }
-
-  mapInverse(inverse: boolean) {
-    this.classAttr += inverse ? 'is-inverse ' : '';
-  }
-
-  mapBadge(badge: string) {
-    if (!badge || badge === '') {
-      return;
-    }
-    this.classAttr += this.badge[badge] || '';
-  }
-
-  setColor(color: string) {
-    console.log('color', color);
-    if (!color || color === '') {
-      return;
-    }
-    this.styleAttr += `fill: ${color};`;
-  }
-}
diff --git a/web/src/app/modules/shared/components/presentation/stepper/stepper.component.ts b/web/src/app/modules/shared/components/presentation/stepper/stepper.component.ts
index e2508ccb..4ccae10a 100644
--- a/web/src/app/modules/shared/components/presentation/stepper/stepper.component.ts
+++ b/web/src/app/modules/shared/components/presentation/stepper/stepper.component.ts
@@ -1,4 +1,4 @@
-import { Component, EventEmitter, Output } from '@angular/core';
+import { Component, EventEmitter, isDevMode, Output } from '@angular/core';
 import { ActionField, StepItem, StepperView } from '../../../models/content';
 import {
   FormBuilder,
@@ -31,18 +31,6 @@ export class StepperComponent extends AbstractViewComponent<StepperView> {
   action: string;
   steps: StepItem[] = [];
 
-  needParams = {
-    min: true,
-    max: true,
-    minLength: true,
-    maxLength: true,
-    pattern: true,
-    required: false,
-    requiredTrue: false,
-    email: false,
-    nullValidator: false,
-  };
-
   constructor(
     private formBuilder: FormBuilder,
     private actionService: ActionService
@@ -97,31 +85,15 @@ export class StepperComponent extends AbstractViewComponent<StepperView> {
     return index;
   }
 
-  getValidators(validators: { string: any }): ValidatorFn[] {
-    if (!validators) {
-      return [];
-    }
-
-    const vFn: ValidatorFn[] = [];
-    const keys = Object.keys(validators);
-    for (const key of keys) {
-      const value = validators[key];
-
-      // Check if function is expected
-      if (this.needParams[key] === undefined) {
-        console.error(`Unknown validation function ${key} for form`);
-        continue;
-      }
-
-      // Verify how many params needs
-      if (this.needParams[key]) {
-        vFn.push(Validators[key](value));
-      } else {
-        vFn.push(Validators[key]);
-      }
+  getValidators(validators: string[]): ValidatorFn[] {
+    if (validators) {
+      const vFn: ValidatorFn[] = [];
+      validators.forEach(v => {
+        vFn.push(Validators[v]);
+      });
+      return vFn;
     }
-
-    return vFn;
+    return [];
   }
 
   fieldChoices(field: ActionField) {
diff --git a/web/src/app/modules/shared/components/view/view-container.component.ts b/web/src/app/modules/shared/components/view/view-container.component.ts
index 252da1d0..1961afd5 100644
--- a/web/src/app/modules/shared/components/view/view-container.component.ts
+++ b/web/src/app/modules/shared/components/view/view-container.component.ts
@@ -38,8 +38,6 @@ interface Viewer {
 })
 export class ViewContainerComponent implements OnInit, AfterViewInit {
   @ViewChild(ViewHostDirective, { static: true }) appView: ViewHostDirective;
-  lastViewType: string;
-
   @Input() set view(v: View) {
     if (v && v.metadata) {
       const cur = JSON.stringify(v);
@@ -81,7 +79,7 @@ export class ViewContainerComponent implements OnInit, AfterViewInit {
   }
 
   loadView(view: View) {
-    if (!this.componentRef || this.lastViewType !== view.metadata.type) {
+    if (!this.componentRef) {
       const viewType = view.metadata.type;
       let component: Type<any> = this.componentMappings[viewType];
       if (!component) {
diff --git a/web/src/app/modules/shared/dynamic-components.ts b/web/src/app/modules/shared/dynamic-components.ts
index 0731a5a7..f0d166b3 100644
--- a/web/src/app/modules/shared/dynamic-components.ts
+++ b/web/src/app/modules/shared/dynamic-components.ts
@@ -41,7 +41,6 @@ import { TimestampComponent } from './components/presentation/timestamp/timestam
 import { ContainersComponent } from './components/presentation/containers/containers.component';
 import { ModalComponent } from './components/presentation/modal/modal.component';
 import { DropdownComponent } from './components/presentation/dropdown/dropdown.component';
-import { IconComponent } from './components/presentation/icon/icon.component';
 
 export interface ComponentMapping {
   [key: string]: Type<any>;
@@ -85,7 +84,6 @@ const DynamicComponentMapping: ComponentMapping = {
   timeline: TimelineComponent,
   timestamp: TimestampComponent,
   yaml: YamlComponent,
-  icon: IconComponent,
 };
 
 export const DYNAMIC_COMPONENTS_MAPPING = new InjectionToken<ComponentMapping>(
diff --git a/web/src/app/modules/shared/models/content.ts b/web/src/app/modules/shared/models/content.ts
index a19b77eb..7140ecae 100644
--- a/web/src/app/modules/shared/models/content.ts
+++ b/web/src/app/modules/shared/models/content.ts
@@ -319,7 +319,7 @@ export interface ActionField {
   value: any;
   placeholder: string;
   error: string;
-  validators: { string: any };
+  validators: string[];
 }
 
 export interface ActionForm {
@@ -585,17 +585,3 @@ export interface StepperView extends View {
     steps: StepItem[];
   };
 }
-
-export interface IconView extends View {
-  config: {
-    shape: string;
-    size: string;
-    direction: string;
-    flip: string;
-    solid: boolean;
-    status: string;
-    inverse: boolean;
-    badge: string;
-    color: string;
-  };
-}
diff --git a/web/src/app/modules/shared/shared.module.ts b/web/src/app/modules/shared/shared.module.ts
index 814cb184..2ad88744 100644
--- a/web/src/app/modules/shared/shared.module.ts
+++ b/web/src/app/modules/shared/shared.module.ts
@@ -83,7 +83,6 @@ import { BottomPanelComponent } from './components/smart/bottom-panel/bottom-pan
 import { DataModule } from '../../data/data.module';
 import { OverlayscrollbarsModule } from 'overlayscrollbars-ngx';
 import { StringEscapePipe } from './pipes/stringEscape/string.escape.pipe';
-import { IconComponent } from './components/presentation/icon/icon.component';
 
 @NgModule({
   declarations: [
@@ -118,7 +117,6 @@ import { IconComponent } from './components/presentation/icon/icon.component';
     HeptagonLabelComponent,
     IFrameComponent,
     IndicatorComponent,
-    IconComponent,
     LabelsComponent,
     LabelSelectorComponent,
     LinkComponent,
diff --git a/web/src/stories/icon.stories.mdx b/web/src/stories/icon.stories.mdx
deleted file mode 100644
index bd35b965..00000000
--- a/web/src/stories/icon.stories.mdx
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Meta, Story, Canvas, ArgsTable } from '@storybook/addon-docs/blocks';
-import { object, withKnobs } from '@storybook/addon-knobs';
-import {IconComponent} from "../app/modules/shared/components/presentation/icon/icon.component";
-
-export const iconDocs= {source: {code: `c := component.NewIcon("user")
-c.Config.Inverse = true
-c.Config.Size = "22"
-c.Config.Direction = component.DirectionDown
-c.Config.Flip = component.FlipHorizontal
-c.Config.Badge = component.BadgeDanger
-`}}
-
-<h1>Icon Component</h1>
-<h2>Description</h2>
-<p>An Icon component is use to display icons use the API from <a href="https://clarity.design/foundation/icons/api/#icon-properties"> Clarity 5 </a>
-  and adapted to <a href="https://v4.clarity.design/icons/how-to-use">Clarity 4</a> </p>
-
-<h2>Example</h2>
-
-<Meta title="Components/Icon" component={IconComponent} />
-
-<Canvas withToolbar>
-  <Story name="Icon component" parameters={{ docs: iconDocs }} height="800px" >
-    {{
-      props: {
-        view: object('View', {
-          metadata: {
-            type: 'icon',
-          },
-          config: {
-            shape: "user",
-            size: "22",
-            direction: "down",
-            flip: "horizontal",
-            solid: true,
-            status: "danger",
-            inverse: false,
-            badge: "danger",
-            color: "#add8e6"
-          }
-        }),
-      },
-      component: IconComponent,
-    }}
-  </Story>
-</Canvas>
-
-<h2>Props</h2>
-<ArgsTable of={IconComponent} />
diff --git a/web/tsconfig.compodoc.json b/web/tsconfig.compodoc.json
index 05fa6a7e..a92d00c4 100644
--- a/web/tsconfig.compodoc.json
+++ b/web/tsconfig.compodoc.json
@@ -190,8 +190,6 @@
     "src//app/modules/shared/components/presentation/dropdown/dropdown.component.spec.ts",
     "src//app/modules/shared/components/presentation/timeline/timeline.component.ts",
     "src//app/modules/shared/components/presentation/timeline/timeline.component.spec.ts",
-    "src//app/modules/shared/components/presentation/icon/icon.component.ts",
-    "src//app/modules/shared/components/presentation/icon/icon.component.spec.ts",
     "src//app/modules/shared/shared.module.ts",
     "src//app/modules/shared/pod-logs/pod-logs.service.ts",
     "src//app/modules/shared/pod-logs/pod-logs.service.spec.ts",


Test patch:
diff --git a/pkg/view/component/form_test.go b/pkg/view/component/form_test.go
index e514de84..ca54a020 100644
--- a/pkg/view/component/form_test.go
+++ b/pkg/view/component/form_test.go
@@ -19,7 +19,7 @@ func TestFormFieldCheckBox_UnmarshalJSON(t *testing.T) {
 	}
 
 	expected := NewFormFieldCheckBox("label", "name", choices)
-	expected.AddValidator("error", map[FormValidator]interface{}{})
+	expected.AddValidator("error", []string{})
 
 	data, err := json.Marshal(&expected)
 	require.NoError(t, err)
@@ -39,7 +39,7 @@ func TestFormFieldRadio_UnmarshalJSON(t *testing.T) {
 	}
 
 	expected := NewFormFieldRadio("label", "name", choices)
-	expected.AddValidator("error", map[FormValidator]interface{}{})
+	expected.AddValidator("error", []string{})
 
 	data, err := json.Marshal(&expected)
 	require.NoError(t, err)
@@ -53,7 +53,7 @@ func TestFormFieldRadio_UnmarshalJSON(t *testing.T) {
 
 func TestFormFieldText_UnmarshalJSON(t *testing.T) {
 	expected := NewFormFieldText("label", "name", "text")
-	expected.AddValidator("placeholder", "error", map[FormValidator]interface{}{})
+	expected.AddValidator("placeholder", "error", []string{})
 
 	data, err := json.Marshal(&expected)
 	require.NoError(t, err)
@@ -67,7 +67,7 @@ func TestFormFieldText_UnmarshalJSON(t *testing.T) {
 
 func TestFormFieldPassword_UnmarshalJSON(t *testing.T) {
 	expected := NewFormFieldPassword("label", "name", "text")
-	expected.AddValidator("placeholder", "error", map[FormValidator]interface{}{})
+	expected.AddValidator("placeholder", "error", []string{})
 
 	data, err := json.Marshal(&expected)
 	require.NoError(t, err)
@@ -81,7 +81,7 @@ func TestFormFieldPassword_UnmarshalJSON(t *testing.T) {
 
 func TestFormFieldNumber_UnmarshalJSON(t *testing.T) {
 	expected := NewFormFieldNumber("label", "name", "999")
-	expected.AddValidator("error", map[FormValidator]interface{}{})
+	expected.AddValidator("error", []string{})
 
 	data, err := json.Marshal(&expected)
 	require.NoError(t, err)
@@ -101,7 +101,7 @@ func TestFormFieldSelect_UnmarshalJSON(t *testing.T) {
 	}
 
 	expected := NewFormFieldSelect("label", "name", choices, true)
-	expected.AddValidator("error", map[FormValidator]interface{}{})
+	expected.AddValidator("error", []string{})
 
 	data, err := json.Marshal(&expected)
 	require.NoError(t, err)
@@ -115,7 +115,7 @@ func TestFormFieldSelect_UnmarshalJSON(t *testing.T) {
 
 func TestFormFieldTextarea_UnmarshalJSON(t *testing.T) {
 	expected := NewFormFieldTextarea("label", "name", "999")
-	expected.AddValidator("placeholder", "error", map[FormValidator]interface{}{})
+	expected.AddValidator("placeholder", "error", []string{})
 
 	data, err := json.Marshal(&expected)
 	require.NoError(t, err)
@@ -129,7 +129,7 @@ func TestFormFieldTextarea_UnmarshalJSON(t *testing.T) {
 
 func TestFormFieldHidden_UnmarshalJSON(t *testing.T) {
 	expected := NewFormFieldHidden("label", "name")
-	expected.AddValidator("placeholder", "error", map[FormValidator]interface{}{})
+	expected.AddValidator("placeholder", "error", []string{})
 
 	data, err := json.Marshal(&expected)
 	require.NoError(t, err)
diff --git a/pkg/view/component/icon_test.go b/pkg/view/component/icon_test.go
deleted file mode 100644
index 865f6b67..00000000
--- a/pkg/view/component/icon_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package component
-
-import (
-	"fmt"
-	"io/ioutil"
-	"path"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-
-	"github.com/stretchr/testify/require"
-
-	"github.com/vmware-tanzu/octant/internal/util/json"
-)
-
-func Test_Icon_Marshal(t *testing.T) {
-	test := []struct {
-		name         string
-		input        Component
-		expectedPath string
-		isErr        bool
-	}{
-		{
-			name: "in general",
-			input: &Icon{
-				Base: newBase(TypeIcon, nil),
-				Config: IconConfig{
-					Shape:     "user",
-					Size:      "16",
-					Direction: DirectionDown,
-					Flip:      FlipHorizontal,
-					Solid:     true,
-					Status:    StatusDanger,
-					Inverse:   false,
-					Badge:     BadgeDanger,
-					Color:     "#add8e6",
-				},
-			},
-			expectedPath: "icon.json",
-			isErr:        false,
-		},
-	}
-	for _, tc := range test {
-		t.Run(tc.name, func(t *testing.T) {
-			actual, err := json.Marshal(tc.input)
-			isErr := err != nil
-			if isErr != tc.isErr {
-				t.Fatalf("UnExpected error: %v", err)
-			}
-
-			fmt.Println(string(actual))
-
-			expected, err := ioutil.ReadFile(path.Join("testdata", tc.expectedPath))
-			require.NoError(t, err)
-			assert.JSONEq(t, string(expected), string(actual))
-		})
-	}
-}
diff --git a/pkg/view/component/stepper_test.go b/pkg/view/component/stepper_test.go
index e9e20cda..eaa89cd7 100644
--- a/pkg/view/component/stepper_test.go
+++ b/pkg/view/component/stepper_test.go
@@ -13,7 +13,7 @@ import (
 
 func Test_stepper_Marshal(t *testing.T) {
 	fft := NewFormFieldText("test", "test", "test")
-	fft.AddValidator("placeholder", "error message", map[FormValidator]interface{}{"required": ""})
+	fft.AddValidator("placeholder", "error message", []string{"required"})
 	form := Form{}
 	form.Fields = append(form.Fields, fft)
 
diff --git a/pkg/view/component/testdata/icon.json b/pkg/view/component/testdata/icon.json
deleted file mode 100644
index 80894a3d..00000000
--- a/pkg/view/component/testdata/icon.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "metadata": {
-    "type": "icon"
-  },
-  "config": {
-    "shape": "user",
-    "size": "16",
-    "direction": "down",
-    "flip": "horizontal",
-    "solid": true,
-    "status": "danger",
-    "inverse": false,
-    "badge": "danger",
-    "color": "#add8e6"
-  }
-}
diff --git a/pkg/view/component/testdata/stepper.json b/pkg/view/component/testdata/stepper.json
index 5fef1d6d..2c7f8caf 100644
--- a/pkg/view/component/testdata/stepper.json
+++ b/pkg/view/component/testdata/stepper.json
@@ -20,9 +20,9 @@
             {
               "error": "error message",
               "placeholder": "placeholder",
-              "validators": {
-                "required": ""
-              },
+              "validators": [
+                "required"
+              ],
               "type": "text",
               "label": "test",
               "name": "test",
@@ -41,9 +41,9 @@
             {
               "error": "error message",
               "placeholder": "placeholder",
-              "validators": {
-                "required": ""
-              },
+              "validators": [
+                "required"
+              ],
               "type": "text",
               "label": "test",
               "name": "test",