SUBMARINE-706. [web] Refactor workbench experiment page

### What is this PR for?

The original functionality can still work fine now. I refactored the code and made these major changes:
1. Split complex components into smaller ones. In that way, it becomes easier to maintain the code. Furthermore, different pages can use the same components easily and do not need to re-write code.
2. Replace dirty trick with a more elegant method. For example, [this bug](https://github.com/apache/submarine/pull/355/files) can be fixed by a shared service between parent and child component rather than checking reload manually.

![Experiment Architecture](https://user-images.githubusercontent.com/24364830/104095135-2c9b9100-52d0-11eb-87b6-cf95e9f1761f.png)

### What type of PR is it?
[Refactoring]

### What is the Jira issue?
https://issues.apache.org/jira/browse/SUBMARINE-706

### How should this be tested?

### Questions:
* Does the licenses files need update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No

Author: Byron <byronhsu1230@gmail.com>

Closes #488 from ByronHsu/SUBMARINE-706 and squashes the following commits:

ab0a8bc [Byron] change delete title
36bd9bc [Byron] change delete title
ec9444a [Byron] fix license typo
a5b3ca0 [Byron] fix license
2c5e0ee [Byron] fix format
23aa3eb [Byron] refactor experiment page
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-customized-form/experiment-customized-form.component.html b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.html
similarity index 100%
rename from submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-customized-form/experiment-customized-form.component.html
rename to submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.html
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-customized-form/experiment-customized-form.component.scss b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.scss
similarity index 100%
rename from submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-customized-form/experiment-customized-form.component.scss
rename to submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.scss
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-customized-form/experiment-customized-form.component.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.ts
similarity index 100%
rename from submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-customized-form/experiment-customized-form.component.ts
rename to submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component.ts
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-form.component.html b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-form.component.html
new file mode 100644
index 0000000..132e253
--- /dev/null
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-form.component.html
@@ -0,0 +1,63 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<nz-modal
+  [(nzVisible)]="modalProps.isVisible"
+  nzTitle="Create Experiment"
+  (nzOnCancel)="closeModal()"
+  [nzWidth]="1000"
+  [nzContent]="modalContent"
+  [nzFooter]="modalFooter"
+>
+  <ng-template #modalContent>
+    <nz-button-group id="form-type-container" *ngIf="!modalProps.formType">
+      <button nz-button nzType="primary" id="customized" (click)="modalProps.formType = 'customized'">
+        Define your experiment
+      </button>
+      <button nz-button nzType="primary" id="pre" (click)="modalProps.formType = 'predefined'">
+        From predefined experiment library
+      </button>
+    </nz-button-group>
+    <submarine-experiment-customized-form
+      [mode]="mode"
+      [targetId]="targetId"
+      [targetSpec]="targetSpec"
+      *ngIf="modalProps.formType === 'customized'"
+    ></submarine-experiment-customized-form>
+    <submarine-experiment-predefined-form
+      *ngIf="modalProps.formType === 'predefined'"
+    ></submarine-experiment-predefined-form>
+  </ng-template>
+  <ng-template #modalFooter>
+    <button nz-button nzType="default" (click)="closeModal()">Cancel</button>
+    <button
+      id="go"
+      nz-button
+      nzType="primary"
+      *ngIf="modalProps.formType"
+      [disabled]="nextBtnDisable"
+      (click)="proceedForm()"
+    >
+      {{ modalProps.okText }}
+    </button>
+    <button *ngIf="modalProps.currentStep > 0" nz-button nzType="default" style="float: left" (click)="prevForm()">
+      Prev Step
+    </button>
+  </ng-template>
+</nz-modal>
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-form.component.scss b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-form.component.scss
new file mode 100644
index 0000000..918683c
--- /dev/null
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-form.component.scss
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#form-type-container {
+  display: grid;
+  grid-auto-rows: 5rem;
+  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
+  column-gap: 3rem;
+  & button {
+    height: 100%;
+  }
+}
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-form.component.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-form.component.ts
new file mode 100644
index 0000000..cd6e637
--- /dev/null
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-form.component.ts
@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { ExperimentSpec } from '@submarine/interfaces/experiment-spec';
+import { ModalProps } from '@submarine/interfaces/modal-props';
+import { ExperimentFormService } from '@submarine/services/experiment.form.service';
+
+@Component({
+  selector: 'submarine-experiment-form',
+  templateUrl: './experiment-form.component.html',
+  styleUrls: ['./experiment-form.component.scss'],
+})
+export class ExperimentFormComponent implements OnInit {
+  // About form management
+  modalProps: ModalProps = {
+    okText: 'Next step',
+    isVisible: false,
+    currentStep: 0,
+    formType: null,
+  };
+  nextBtnDisable: boolean = true;
+
+  // About update and clone
+  mode: 'create' | 'update' | 'clone' = 'create';
+  targetId: string = null;
+  targetSpec: ExperimentSpec = null;
+
+  constructor(private experimentFormService: ExperimentFormService) {}
+
+  ngOnInit() {
+    this.experimentFormService.btnStatusService.subscribe((status) => {
+      this.nextBtnDisable = status;
+    });
+    this.experimentFormService.modalPropsService.subscribe((props) => {
+      this.modalProps = { ...this.modalProps, ...props };
+    });
+  }
+
+  initModal(
+    initMode: 'create' | 'update' | 'clone',
+    initFormType = null,
+    id: string = null,
+    spec: ExperimentSpec = null
+  ) {
+    this.mode = initMode;
+    this.modalProps.isVisible = true;
+    this.modalProps.formType = initFormType;
+
+    if (initMode === 'update' || initMode === 'clone') {
+      // Keep id for later request
+      this.targetId = id;
+      this.targetSpec = spec;
+    }
+  }
+
+  closeModal() {
+    this.experimentFormService.modalPropsClear();
+  }
+
+  proceedForm() {
+    this.experimentFormService.stepChange(1);
+  }
+
+  prevForm() {
+    this.experimentFormService.stepChange(-1);
+  }
+}
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-predefined-form/experiment-predefined-form.component.html b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-predefined-form/experiment-predefined-form.component.html
similarity index 100%
rename from submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-predefined-form/experiment-predefined-form.component.html
rename to submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-predefined-form/experiment-predefined-form.component.html
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-predefined-form/experiment-predefined-form.component.scss b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-predefined-form/experiment-predefined-form.component.scss
similarity index 100%
rename from submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-predefined-form/experiment-predefined-form.component.scss
rename to submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-predefined-form/experiment-predefined-form.component.scss
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-predefined-form/experiment-predefined-form.component.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-predefined-form/experiment-predefined-form.component.ts
similarity index 95%
rename from submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-predefined-form/experiment-predefined-form.component.ts
rename to submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-predefined-form/experiment-predefined-form.component.ts
index 0bedc75..fe6a16f 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-predefined-form/experiment-predefined-form.component.ts
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-form/experiment-predefined-form/experiment-predefined-form.component.ts
@@ -22,7 +22,7 @@
 import { ExperimentTemplate } from '@submarine/interfaces/experiment-template';
 import { ExperimentFormService } from '@submarine/services/experiment.form.service';
 import { ExperimentService } from '@submarine/services/experiment.service';
-import { interval, Subscription } from 'rxjs';
+import { Subscription } from 'rxjs';
 import { ExperimentTemplateSubmit } from '@submarine/interfaces/experiment-template-submit';
 import { NzMessageService } from 'ng-zorro-antd';
 
@@ -73,7 +73,6 @@
         // default: switch to first template
         const defaultTemplate = Object.keys(this.templates)[0];
         this.predefinedForm.get('templateName').setValue(defaultTemplate);
-        console.log(this.predefinedForm.get('templateName').value);
         this.onTemplateChange();
       }
     });
@@ -95,11 +94,8 @@
       // handle submit
       this.onSubmit();
     });
-    const sub2 = interval(1000).subscribe(() => {
-      console.log(this.templates);
-    });
+
     this.subs.push(sub);
-    this.subs.push(sub2);
   }
   ngOnDestroy() {
     this.subs.forEach((sub) => sub.unsubscribe());
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
index 2581d72..309279a 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
@@ -7,7 +7,7 @@
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at
 
-   http://www.apache.org/licenses/LICENSE-2.0
+ http://www.apache.org/licenses/LICENSE-2.0
 
  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
@@ -17,5 +17,54 @@
  under the License.
 -->
 
-<!-- <p>experiment-home works!</p> -->
-<!-- TODO: should split home page from experiment root components -->
+<div style="margin: 15px; padding: 15px; background-color: white">
+  <div align="right">
+    <nz-radio-group>
+      <label nz-radio-button nzValue="All">All</label>
+      <label nz-radio-button nzValue="Own">Owned By Me</label>
+      <label nz-radio-button nzValue="Access">Accessible By Me</label>
+    </nz-radio-group>
+    <nz-input-group
+      nzSearch
+      style="width: 300px; margin-top: 15px; margin-left: 10px; margin-right: 5px"
+      [nzAddOnAfter]="suffixIconButton"
+    >
+      <input type="text" nz-input placeholder="input search text" />
+    </nz-input-group>
+    <ng-template #suffixIconButton>
+      <button nz-button nzType="primary" nzSearch><i nz-icon nzType="search"></i></button>
+    </ng-template>
+
+    <button
+      nz-button
+      id="openExperiment"
+      nzType="primary"
+      style="margin-right: 5px; margin-bottom: 15px; margin-top: 15px"
+      (click)="form.initModal('create')"
+    >
+      <i nz-icon nzType="plus"></i>
+      New Experiment
+    </button>
+    <button
+      nz-button
+      nzType="primary"
+      style="margin-bottom: 15px; margin-top: 15px"
+      nz-popconfirm
+      nzTitle="Confirm to delete?"
+      nzCancelText="Cancel"
+      nzOkText="Ok"
+      (nzOnConfirm)="deleteExperiments()"
+    >
+      Delete
+    </button>
+  </div>
+  <submarine-experiment-list
+    [experimentList]="experimentList"
+    [checkedList]="checkedList"
+    [isLoading]="isLoading"
+    (deleteExperiment)="onDeleteExperiment($event, true)"
+    (initModal)="onInitModal($event)"
+    [(selectAllChecked)]="selectAllChecked"
+  ></submarine-experiment-list>
+  <submarine-experiment-form #form></submarine-experiment-form>
+</div>
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.scss b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.scss
index 042f3ce..624ee4a 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.scss
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.scss
@@ -1,4 +1,4 @@
-/*
+/**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -7,7 +7,7 @@
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
- *   http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
index 4f46d91..7c656d6 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
@@ -1,4 +1,4 @@
-/*
+/**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -7,7 +7,7 @@
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
- *   http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
@@ -17,7 +17,12 @@
  * under the License.
  */
 
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { ExperimentInfo } from '@submarine/interfaces/experiment-info';
+import { ExperimentFormService } from '@submarine/services/experiment.form.service';
+import { ExperimentService } from '@submarine/services/experiment.service';
+import { NzMessageService } from 'ng-zorro-antd';
+import { ExperimentFormComponent } from './experiment-form/experiment-form.component';
 
 @Component({
   selector: 'app-experiment-home',
@@ -25,7 +30,88 @@
   styleUrls: ['./experiment-home.component.scss'],
 })
 export class ExperimentHomeComponent implements OnInit {
-  constructor() {}
+  /*
+  experiment-list property:
+    p.s. CheckedList does not need eventListener to update,
+    because when we modify the array in child component,
+    the modification will be sync to parent.
+  */
+  experimentList: ExperimentInfo[];
+  isLoading: boolean = true;
+  checkedList: boolean[];
+  selectAllChecked: boolean = false;
 
-  ngOnInit() {}
+  @ViewChild('form', { static: true }) form: ExperimentFormComponent;
+
+  constructor(
+    private experimentService: ExperimentService,
+    private experimentFormService: ExperimentFormService,
+    private nzMessageService: NzMessageService
+  ) {}
+
+  ngOnInit() {
+    this.experimentFormService.fetchListService.subscribe(() => {
+      this.fetchExperimentList();
+    });
+
+    this.experimentService.emitInfo(null);
+  }
+
+  fetchExperimentList() {
+    this.experimentService.fetchExperimentList().subscribe(
+      (list) => {
+        this.isLoading = false;
+        this.experimentList = list;
+        const currentTime = new Date();
+        this.experimentList.forEach((item) => {
+          if (item.status === 'Succeeded') {
+            const finTime = new Date(item.finishedTime);
+            const runTime = new Date(item.runningTime);
+            const result = (finTime.getTime() - runTime.getTime()) / 1000;
+            item.duration = this.experimentService.durationHandle(result);
+          } else if (item.runningTime) {
+            const runTime = new Date(item.runningTime);
+            const result = (currentTime.getTime() - runTime.getTime()) / 1000;
+            item.duration = this.experimentService.durationHandle(result);
+          }
+        });
+        this.checkedList = [];
+        for (let i = 0; i < this.experimentList.length; i++) {
+          this.checkedList.push(false);
+        }
+      },
+      (error) => {
+        console.error(error);
+      }
+    );
+  }
+
+  onDeleteExperiment(id: string, onMessage: boolean) {
+    this.experimentService.deleteExperiment(id).subscribe(
+      () => {
+        if (onMessage === true) {
+          this.nzMessageService.success('Delete Experiment Successfully!');
+        }
+        this.fetchExperimentList();
+      },
+      (err) => {
+        if (onMessage === true) {
+          this.nzMessageService.error(err.message);
+        }
+      }
+    );
+  }
+
+  deleteExperiments() {
+    for (let i = this.checkedList.length - 1; i >= 0; i--) {
+      if (this.checkedList[i] === true) {
+        this.onDeleteExperiment(this.experimentList[i].experimentId, false);
+      }
+    }
+    this.selectAllChecked = false;
+  }
+
+  onInitModal(obj) {
+    this.form.initModal(obj.initMode, obj.initFormType, obj.id, obj.spec);
+  }
 }
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-list/experiment-list.component.html b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-list/experiment-list.component.html
new file mode 100644
index 0000000..f79dc1a
--- /dev/null
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-list/experiment-list.component.html
@@ -0,0 +1,88 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<nz-table
+  id="releaseTable"
+  nzBordered
+  #basicTable
+  [nzData]="experimentList"
+  [nzNoResult]="'No data'"
+  [nzLoading]="isLoading"
+  nzSize="small"
+>
+  <thead>
+    <tr>
+      <th>
+        <label nz-checkbox [ngModel]="selectAllChecked" (ngModelChange)="onSelectAllClick($event)"></label>
+      </th>
+      <th>Experiment Name</th>
+      <th>Experiment ID</th>
+      <th>Status</th>
+      <th>Finished Time</th>
+      <th>Created Time</th>
+      <th>Running Time</th>
+      <th>Duration</th>
+      <th>Action</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr *ngFor="let data of basicTable.data; let i = index">
+      <td>
+        <label nz-checkbox [(ngModel)]="checkedList[i]"></label>
+      </td>
+      <td>{{ data.name }}</td>
+      <td>
+        <a [routerLink]="['info', data.experimentId]">
+          {{ data.experimentId }}
+        </a>
+      </td>
+      <td>
+        <nz-tag [nzColor]="statusColor[data.status]">{{ data.status }}</nz-tag>
+      </td>
+      <td>{{ data.finishedTime | date: 'M/d/yyyy, h:mm a' }}</td>
+      <td>{{ data.createdTime | date: 'M/d/yyyy, h:mm a' }}</td>
+      <td>{{ data.runningTime | date: 'M/d/yyyy, h:mm a' }}</td>
+      <td>{{ data.duration }}</td>
+      <td class="td-action">
+        <a (click)="initModal.emit({ initMode: 'clone', initFormType: 'customized', id: null, spec: data.spec })">
+          Clone
+        </a>
+        <nz-divider nzType="vertical"></nz-divider>
+        <a
+          (click)="
+            initModal.emit({ initMode: 'update', initFormType: 'customized', id: data.experimentId, spec: data.spec })
+          "
+        >
+          Update
+        </a>
+        <nz-divider nzType="vertical"></nz-divider>
+        <a
+          nz-popconfirm
+          nzPlacement="left"
+          nzTitle="Are you sure you want to delete?"
+          nzCancelText="Cancel"
+          nzOkText="Ok"
+          (nzOnConfirm)="onDeleteExperiment(data.experimentId)"
+        >
+          Delete
+        </a>
+      </td>
+    </tr>
+  </tbody>
+</nz-table>
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-list/experiment-list.component.scss b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-list/experiment-list.component.scss
new file mode 100644
index 0000000..624ee4a
--- /dev/null
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-list/experiment-list.component.scss
@@ -0,0 +1,18 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-list/experiment-list.component.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-list/experiment-list.component.ts
new file mode 100644
index 0000000..324b29d
--- /dev/null
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-list/experiment-list.component.ts
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { ExperimentInfo } from '@submarine/interfaces/experiment-info';
+
+@Component({
+  selector: 'submarine-experiment-list',
+  templateUrl: './experiment-list.component.html',
+  styleUrls: ['./experiment-list.component.scss'],
+})
+export class ExperimentListComponent implements OnInit {
+  // property
+  @Input() experimentList: ExperimentInfo[];
+  @Input() isLoading: boolean;
+  @Input() checkedList: boolean[];
+
+  // event emitter
+  @Output() deleteExperiment = new EventEmitter<number>();
+  @Output() initModal = new EventEmitter<any>();
+
+  // two-way binding: https://angular.io/guide/two-way-binding
+  @Input() selectAllChecked: boolean;
+  @Output() selectAllCheckedChange = new EventEmitter<boolean>();
+
+  statusColor: { [key: string]: string } = {
+    Accepted: 'gold',
+    Created: 'white',
+    Running: 'green',
+    Succeeded: 'blue',
+  };
+
+  constructor() {}
+
+  ngOnInit() {}
+
+  onSelectAllClick() {
+    for (let i = 0; i < this.checkedList.length; i++) {
+      this.checkedList[i] = !this.selectAllChecked;
+    }
+    this.selectAllCheckedChange.emit(!this.selectAllChecked);
+  }
+
+  onDeleteExperiment(id: number) {
+    this.deleteExperiment.emit(id);
+  }
+}
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
index 781ca67..478017c 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
@@ -17,107 +17,109 @@
   ~ under the License.
   -->
 
-<nz-table
-  *ngIf="!isLoading"
-  style="margin-top: 10px;"
-  id="experimentTable"
-  #basicTable
-  [nzData]="[experimentInfo]"
-  [nzShowPagination]="false"
-  nzSize="small"
->
-  <thead>
-    <tr>
-      <th>Experiment Name</th>
-      <th>Experiment ID</th>
-      <th>Created Time</th>
-      <th>Running Time</th>
-      <th>Finished Time</th>
-      <th>Duration</th>
-      <th>Status</th>
-      <th>Action</th>
-    </tr>
-  </thead>
-  <tbody>
-    <tr>
-      <td>{{ experimentInfo.name }}</td>
-      <td>{{ experimentInfo.experimentId }}</td>
-      <td>{{ experimentInfo.createdTime | date: 'M/d/yyyy, h:mm a' }}</td>
-      <td>{{ experimentInfo.runningTime | date: 'M/d/yyyy, h:mm a' }}</td>
-      <td>{{ experimentInfo.finishedTime | date: 'M/d/yyyy, h:mm a' }}</td>
-      <td>{{ experimentInfo.duration }}</td>
-      <td>
-        <nz-tag [nzColor]="statusColor[experimentInfo.status]">{{ experimentInfo.status }}</nz-tag>
-      </td>
-      <td class="td-action">
-        <a (click)="startExperiment()">Start</a>
-        <nz-divider nzType="vertical"></nz-divider>
-        <a nz-dropdown [nzDropdownMenu]="more">
-          More
-          <i nz-icon nzType="down"></i>
-        </a>
-        <nz-dropdown-menu #more="nzDropdownMenu">
-          <ul nz-menu nzSelectable>
-            <li nz-menu-item (click)="editExperiment()">Edit</li>
-            <li
-              nz-menu-item
-              nz-popconfirm
-              nzPlacement="left"
-              nzTitle="Confirm to delete?"
-              nzCancelText="Cancel"
-              nzOkText="Ok"
-              (nzOnConfirm)="onDeleteExperiment()"
-            >
-              Delete
-            </li>
-          </ul>
-        </nz-dropdown-menu>
-      </td>
-    </tr>
-  </tbody>
-</nz-table>
-<nz-spin *ngIf="isLoading"></nz-spin>
-<div style="background-color: white;">
-  <nz-select id="nzSelect_selectPod" [(ngModel)]="selectedPod">
-    <nz-option *ngFor="let pod of podNameArr" [nzValue]="pod" [nzLabel]="pod"></nz-option>
-  </nz-select>
-</div>
-<nz-layout>
-  <nz-sider id="experimentInfo_sider">
-    <ul nz-menu>
-      <li nz-menu-item nzSelected (click)="currentState = 0">
-        <i nz-icon nzType="bar-chart" nzTheme="outline"></i>
-        Charts
-      </li>
-      <li nz-menu-item (click)="currentState = 1">
-        <i nz-icon nzType="bars" nzTheme="outline"></i>
-        Parameters
-      </li>
-      <li nz-menu-item (click)="currentState = 2">
-        <i nz-icon nzType="appstore" nzTheme="outline"></i>
-        Metrics
-      </li>
-      <li nz-menu-item (click)="currentState = 3">
-        <i nz-icon nzType="desktop" nzTheme="outline"></i>
-        Outputs
-      </li>
-    </ul>
-  </nz-sider>
+<div style="margin: 15px; padding: 15px; background-color: white">
+  <nz-table
+    *ngIf="!isLoading"
+    style="margin-top: 10px"
+    id="experimentTable"
+    #basicTable
+    [nzData]="[experimentInfo]"
+    [nzShowPagination]="false"
+    nzSize="small"
+  >
+    <thead>
+      <tr>
+        <th>Experiment Name</th>
+        <th>Experiment ID</th>
+        <th>Created Time</th>
+        <th>Running Time</th>
+        <th>Finished Time</th>
+        <th>Duration</th>
+        <th>Status</th>
+        <th>Action</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td>{{ experimentInfo.name }}</td>
+        <td>{{ experimentInfo.experimentId }}</td>
+        <td>{{ experimentInfo.createdTime | date: 'M/d/yyyy, h:mm a' }}</td>
+        <td>{{ experimentInfo.runningTime | date: 'M/d/yyyy, h:mm a' }}</td>
+        <td>{{ experimentInfo.finishedTime | date: 'M/d/yyyy, h:mm a' }}</td>
+        <td>{{ experimentInfo.duration }}</td>
+        <td>
+          <nz-tag [nzColor]="statusColor[experimentInfo.status]">{{ experimentInfo.status }}</nz-tag>
+        </td>
+        <td class="td-action">
+          <a (click)="startExperiment()">Start</a>
+          <nz-divider nzType="vertical"></nz-divider>
+          <a nz-dropdown [nzDropdownMenu]="more">
+            More
+            <i nz-icon nzType="down"></i>
+          </a>
+          <nz-dropdown-menu #more="nzDropdownMenu">
+            <ul nz-menu nzSelectable>
+              <li nz-menu-item (click)="editExperiment()">Edit</li>
+              <li
+                nz-menu-item
+                nz-popconfirm
+                nzPlacement="left"
+                nzTitle="Are you sure you want to delete?"
+                nzCancelText="Cancel"
+                nzOkText="Ok"
+                (nzOnConfirm)="onDeleteExperiment()"
+              >
+                Delete
+              </li>
+            </ul>
+          </nz-dropdown-menu>
+        </td>
+      </tr>
+    </tbody>
+  </nz-table>
+  <nz-spin *ngIf="isLoading"></nz-spin>
+  <div style="background-color: white">
+    <nz-select id="nzSelect_selectPod" [(ngModel)]="selectedPod">
+      <nz-option *ngFor="let pod of podNameArr" [nzValue]="pod" [nzLabel]="pod"></nz-option>
+    </nz-select>
+  </div>
   <nz-layout>
-    <div [ngSwitch]="currentState">
-      <submarine-charts *ngSwitchCase="0" [workerIndex]="selectedPod" [metricData]="metricData"></submarine-charts>
-      <submarine-hyper-params
-        *ngSwitchCase="1"
-        [workerIndex]="selectedPod"
-        [paramData]="paramData"
-      ></submarine-hyper-params>
-      <submarine-metrics *ngSwitchCase="2" [workerIndex]="selectedPod" [metricData]="metricData"></submarine-metrics>
-      <submarine-outputs
-        *ngSwitchCase="3"
-        [podName]="selectedPod"
-        [experimentID]="experimentID"
-        [podLogArr]="podLogArr"
-      ></submarine-outputs>
-    </div>
+    <nz-sider id="experimentInfo_sider">
+      <ul nz-menu>
+        <li nz-menu-item nzSelected (click)="currentState = 0">
+          <i nz-icon nzType="bar-chart" nzTheme="outline"></i>
+          Charts
+        </li>
+        <li nz-menu-item (click)="currentState = 1">
+          <i nz-icon nzType="bars" nzTheme="outline"></i>
+          Parameters
+        </li>
+        <li nz-menu-item (click)="currentState = 2">
+          <i nz-icon nzType="appstore" nzTheme="outline"></i>
+          Metrics
+        </li>
+        <li nz-menu-item (click)="currentState = 3">
+          <i nz-icon nzType="desktop" nzTheme="outline"></i>
+          Outputs
+        </li>
+      </ul>
+    </nz-sider>
+    <nz-layout>
+      <div [ngSwitch]="currentState">
+        <submarine-charts *ngSwitchCase="0" [workerIndex]="selectedPod" [metricData]="metricData"></submarine-charts>
+        <submarine-hyper-params
+          *ngSwitchCase="1"
+          [workerIndex]="selectedPod"
+          [paramData]="paramData"
+        ></submarine-hyper-params>
+        <submarine-metrics *ngSwitchCase="2" [workerIndex]="selectedPod" [metricData]="metricData"></submarine-metrics>
+        <submarine-outputs
+          *ngSwitchCase="3"
+          [podName]="selectedPod"
+          [experimentID]="experimentID"
+          [podLogArr]="podLogArr"
+        ></submarine-outputs>
+      </div>
+    </nz-layout>
   </nz-layout>
-</nz-layout>
+</div>
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
index c00b2ee..8e1bf8f 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
@@ -26,7 +26,7 @@
 @Component({
   selector: 'submarine-experiment-info',
   templateUrl: './experiment-info.component.html',
-  styleUrls: ['./experiment-info.component.scss']
+  styleUrls: ['./experiment-info.component.scss'],
 })
 export class ExperimentInfoComponent implements OnInit {
   isLoading = true;
@@ -50,7 +50,7 @@
     Accepted: 'gold',
     Created: 'white',
     Running: 'green',
-    Succeeded: 'blue'
+    Succeeded: 'blue',
   };
 
   ngOnInit() {
@@ -78,6 +78,7 @@
     );
 
     this.getExperimentPod();
+    this.experimentService.emitInfo(this.experimentID);
   }
 
   getExperimentPod() {
@@ -95,7 +96,7 @@
 
     this.experimentService
       .getExperimentParam({
-        id: this.experimentID
+        id: this.experimentID,
       })
       .subscribe(
         (result) => {
@@ -109,7 +110,7 @@
 
     this.experimentService
       .getExperimentMetric({
-        id: this.experimentID
+        id: this.experimentID,
       })
       .subscribe(
         (result) => {
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-routing.module.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-routing.module.ts
index 7fc2287..0a83f7c 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-routing.module.ts
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-routing.module.ts
@@ -40,7 +40,6 @@
     ],
   },
 ];
-
 @NgModule({
   imports: [RouterModule.forChild(routes)],
   exports: [RouterModule],
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.html b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.html
index 82a2b1b..b22a6f8 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.html
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.html
@@ -18,21 +18,20 @@
   -->
 
 <nz-layout style="margin: -24px -24px 16px">
-  <nz-layout class="inner-layout">
-    <div id="experimentOuter">
+  <nz-layout>
+    <div style="background-color: white; padding-left: 30px; padding-top: 20px">
       <nz-breadcrumb>
         <nz-breadcrumb-item>
-          <!--<a [routerLink]="['/', 'workbench', 'home']">Home</a>-->
           <a>Home</a>
         </nz-breadcrumb-item>
         <nz-breadcrumb-item>
-          <a [routerLink]="['/', 'workbench', 'experiment']" (click)="isInfo = false">experiment</a>
+          <a [routerLink]="['/', 'workbench', 'experiment']">experiment</a>
         </nz-breadcrumb-item>
-        <nz-breadcrumb-item *ngIf="isInfo == true">
+        <nz-breadcrumb-item *ngIf="experimentID != null">
           {{ experimentID }}
         </nz-breadcrumb-item>
       </nz-breadcrumb>
-      <div *ngIf="isInfo == false">
+      <div *ngIf="experimentID == null">
         <br />
         <h2>Experiment</h2>
         <nz-content>A experiment is a way of running a adhoc, pre-defined or pipeline on a scheduled basis.</nz-content>
@@ -40,149 +39,6 @@
       <br />
     </div>
   </nz-layout>
-  <div id="experimentData">
-    <div *ngIf="isInfo == false">
-      <div align="right">
-        <nz-radio-group [(ngModel)]="showExperiment" (ngModelChange)="showChange()">
-          <label nz-radio-button nzValue="All">All</label>
-          <label nz-radio-button nzValue="Own">Owned By Me</label>
-          <label nz-radio-button nzValue="Access">Accessible By Me</label>
-        </nz-radio-group>
-        <nz-input-group
-          nzSearch
-          style="width: 300px; margin-top: 15px; margin-left: 10px; margin-right: 5px"
-          [nzAddOnAfter]="suffixIconButton"
-        >
-          <input type="text" nz-input placeholder="input search text" />
-        </nz-input-group>
-        <ng-template #suffixIconButton>
-          <button nz-button nzType="primary" nzSearch><i nz-icon nzType="search"></i></button>
-        </ng-template>
 
-        <button
-          nz-button
-          id="openExperiment"
-          nzType="primary"
-          style="margin-right: 5px; margin-bottom: 15px; margin-top: 15px"
-          (click)="initModal('create')"
-        >
-          <i nz-icon nzType="plus"></i>
-          New Experiment
-        </button>
-        <button
-          nz-button
-          nzType="primary"
-          style="margin-bottom: 15px; margin-top: 15px"
-          nz-popconfirm
-          nzTitle="Confirm to delete?"
-          nzCancelText="Cancel"
-          nzOkText="Ok"
-          (nzOnConfirm)="deleteExperiments()"
-        >
-          Delete
-        </button>
-      </div>
-      <nz-table
-        id="releaseTable"
-        nzBordered
-        #basicTable
-        [nzData]="experimentList"
-        [nzNoResult]="'No data'"
-        nzSize="small"
-      >
-        <thead>
-          <tr>
-            <th>
-              <label nz-checkbox [(ngModel)]="selectAllChecked" (ngModelChange)="selectAll()"></label>
-            </th>
-            <th>Experiment Name</th>
-            <th>Experiment ID</th>
-            <th>Status</th>
-            <th>Finished Time</th>
-            <th>Created Time</th>
-            <th>Running Time</th>
-            <th>Duration</th>
-            <th>Action</th>
-          </tr>
-        </thead>
-        <tbody>
-          <tr *ngFor="let data of basicTable.data; let i = index">
-            <td>
-              <label nz-checkbox [(ngModel)]="checkedList[i]"></label>
-            </td>
-            <td>{{ data.name }}</td>
-            <td>
-              <a [routerLink]="['info', data.experimentId]" (click)="experimentID = data.experimentId; isInfo = true">
-                {{ data.experimentId }}
-              </a>
-            </td>
-            <td>
-              <nz-tag [nzColor]="statusColor[data.status]">{{ data.status }}</nz-tag>
-            </td>
-            <td>{{ data.finishedTime | date: 'M/d/yyyy, h:mm a' }}</td>
-            <td>{{ data.createdTime | date: 'M/d/yyyy, h:mm a' }}</td>
-            <td>{{ data.runningTime | date: 'M/d/yyyy, h:mm a' }}</td>
-            <td>{{ data.duration }}</td>
-            <td class="td-action">
-              <a (click)="initModal('clone', 'customized', null, data.spec)">Clone</a>
-              <nz-divider nzType="vertical"></nz-divider>
-              <a (click)="initModal('update', 'customized', data.experimentId, data.spec)">Update</a>
-              <nz-divider nzType="vertical"></nz-divider>
-              <a
-                nz-popconfirm
-                nzPlacement="left"
-                nzTitle="Confirm to delete?"
-                nzCancelText="Cancel"
-                nzOkText="Ok"
-                (nzOnConfirm)="onDeleteExperiment(data.experimentId, true)"
-              >
-                Delete
-              </a>
-            </td>
-          </tr>
-        </tbody>
-      </nz-table>
-    </div>
-    <router-outlet></router-outlet>
-  </div>
-  <nz-modal
-    [(nzVisible)]="modalProps.isVisible"
-    nzTitle="Create Experiment"
-    (nzOnCancel)="closeModal()"
-    [nzWidth]="1000"
-  >
-    <nz-button-group id="form-type-container" *ngIf="!modalProps.formType">
-      <button nz-button nzType="primary" id="customized" (click)="modalProps.formType = 'customized'">
-        Define your experiment
-      </button>
-      <button nz-button nzType="primary" id="pre" (click)="modalProps.formType = 'predefined'">
-        From predefined experiment library
-      </button>
-    </nz-button-group>
-    <div *nzModalFooter>
-      <button nz-button nzType="default" (click)="closeModal()">Cancel</button>
-      <button
-        id="go"
-        nz-button
-        nzType="primary"
-        *ngIf="modalProps.formType"
-        [disabled]="nextBtnDisable"
-        (click)="proceedForm()"
-      >
-        {{ modalProps.okText }}
-      </button>
-      <button *ngIf="modalProps.currentStep > 0" nz-button nzType="default" style="float: left" (click)="prevForm()">
-        Prev Step
-      </button>
-    </div>
-    <submarine-experiment-customized-form
-      [mode]="mode"
-      [targetId]="targetId"
-      [targetSpec]="targetSpec"
-      *ngIf="this.modalProps.formType === 'customized'"
-    ></submarine-experiment-customized-form>
-    <submarine-experiment-predefined-form
-      *ngIf="this.modalProps.formType === 'predefined'"
-    ></submarine-experiment-predefined-form>
-  </nz-modal>
+  <router-outlet></router-outlet>
 </nz-layout>
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.scss b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.scss
index ba2f168..c1bfad9 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.scss
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.scss
@@ -17,35 +17,20 @@
  * under the License.
  */
 
- #experimentOuter{
-    background-color: white;
-    padding-left: 30px;
-    padding-top: 20px;
- }
+#form-type-container {
+  display: grid;
+  grid-auto-rows: 5rem;
+  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
+  column-gap: 3rem;
+  & button {
+    height: 100%;
+  }
+}
 
- #experimentData{
-    margin-top: 16px;
-    margin-left: 25px;
-    margin-right: 25px;
-    background-color:white;
-    padding-left: 10px;
-    padding-right: 10px;
- }
+input.ng-invalid.ng-touched {
+  border: 1px solid red;
+}
 
- #form-type-container {
-    display: grid;
-    grid-auto-rows: 5rem;
-    grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
-    column-gap: 3rem;
-    & button {
-      height: 100%;
-    }
- }
-
- input.ng-invalid.ng-touched {
-   border: 1px solid red;
- }
-
- textarea.ng-invalid.ng-touched {
-   border: 1px solid red;
+textarea.ng-invalid.ng-touched {
+  border: 1px solid red;
 }
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.ts
index 46cac01..c9fc42e 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.ts
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.component.ts
@@ -17,14 +17,9 @@
  * under the License.
  */
 
-import { Component, OnChanges, OnInit } from '@angular/core';
-import { ActivatedRoute, NavigationStart, Router } from '@angular/router';
-import { ExperimentInfo } from '@submarine/interfaces/experiment-info';
-import { ExperimentSpec } from '@submarine/interfaces/experiment-spec';
-import { ModalProps } from '@submarine/interfaces/modal-props';
-import { ExperimentFormService } from '@submarine/services/experiment.form.service';
+import { AfterViewInit, Component, OnInit } from '@angular/core';
 import { ExperimentService } from '@submarine/services/experiment.service';
-import { NzMessageService } from 'ng-zorro-antd';
+import { delay } from 'rxjs/operators';
 
 @Component({
   selector: 'submarine-experiment',
@@ -32,184 +27,11 @@
   styleUrls: ['./experiment.component.scss'],
 })
 export class ExperimentComponent implements OnInit {
-  experimentList: ExperimentInfo[] = [];
-  checkedList: boolean[] = [];
-  selectAllChecked: boolean = false;
+  experimentID: string = null;
 
-  // About experiment information
-  isInfo = false;
-  experimentID: string;
-
-  // About show existing experiments
-  showExperiment = 'All';
-  searchText = '';
-
-  // About form management
-  modalProps: ModalProps = {
-    okText: 'Next step',
-    isVisible: false,
-    currentStep: 0,
-    formType: null,
-  };
-  nextBtnDisable: boolean = true;
-
-  // About update and clone
-  mode: 'create' | 'update' | 'clone' = 'create';
-  targetId: string = null;
-  targetSpec: ExperimentSpec = null;
-
-  statusColor: { [key: string]: string } = {
-    Accepted: 'gold',
-    Created: 'white',
-    Running: 'green',
-    Succeeded: 'blue',
-  };
-
-  constructor(
-    private nzMessageService: NzMessageService,
-    private route: ActivatedRoute,
-    private router: Router,
-    private experimentService: ExperimentService,
-    private experimentFormService: ExperimentFormService
-  ) {}
+  constructor(private experimentService: ExperimentService) {}
 
   ngOnInit() {
-    this.fetchExperimentList();
-    this.isInfo = this.router.url !== '/workbench/experiment';
-    this.experimentID = this.route.snapshot.params.id;
-
-    this.router.events.subscribe((val) => {
-      if (val instanceof NavigationStart) {
-        console.log(val.url);
-        if (val.url === '/workbench/experiment') {
-          this.isInfo = false;
-          this.fetchExperimentList();
-        } else {
-          this.isInfo = true;
-        }
-      }
-    });
-
-    // Subscriptions to experimentFormService
-    this.experimentFormService.fetchListService.subscribe(() => {
-      this.fetchExperimentList();
-    });
-    this.experimentFormService.btnStatusService.subscribe((status) => {
-      this.nextBtnDisable = status;
-    });
-    this.experimentFormService.modalPropsService.subscribe((props) => {
-      this.modalProps = { ...this.modalProps, ...props };
-    });
-
-    this.reloadCheck();
-  }
-
-  initModal(
-    initMode: 'create' | 'update' | 'clone',
-    initFormType = null,
-    id: string = null,
-    spec: ExperimentSpec = null
-  ) {
-    this.mode = initMode;
-    this.modalProps.isVisible = true;
-    this.modalProps.formType = initFormType;
-
-    if (initMode === 'update' || initMode === 'clone') {
-      // Keep id for later request
-      this.targetId = id;
-      this.targetSpec = spec;
-    }
-  }
-
-  closeModal() {
-    this.experimentFormService.modalPropsClear();
-  }
-
-  proceedForm() {
-    this.experimentFormService.stepChange(1);
-  }
-
-  prevForm() {
-    this.experimentFormService.stepChange(-1);
-  }
-
-  fetchExperimentList() {
-    this.experimentService.fetchExperimentList().subscribe((list) => {
-      this.experimentList = list;
-      const currentTime = new Date();
-      this.experimentList.forEach((item) => {
-        if (item.status === 'Succeeded') {
-          const finTime = new Date(item.finishedTime);
-          const runTime = new Date(item.runningTime);
-          const result = (finTime.getTime() - runTime.getTime()) / 1000;
-          item.duration = this.experimentService.durationHandle(result);
-        } else if (item.runningTime) {
-          const runTime = new Date(item.runningTime);
-          const result = (currentTime.getTime() - runTime.getTime()) / 1000;
-          item.duration = this.experimentService.durationHandle(result);
-        }
-      });
-      this.checkedList = [];
-      for (let i = 0; i < this.experimentList.length; i++) {
-        this.checkedList.push(false);
-      }
-    });
-  }
-
-  onDeleteExperiment(id: string, onMessage: boolean) {
-    this.experimentService.deleteExperiment(id).subscribe(
-      () => {
-        if (onMessage === true) {
-          this.nzMessageService.success('Delete Experiment Successfully!');
-        }
-        this.fetchExperimentList();
-      },
-      (err) => {
-        if (onMessage === true) {
-          this.nzMessageService.error(err.message);
-        }
-      }
-    );
-  }
-
-  reloadCheck() {
-    /*
-      When reload in info page, ths experimentId will turn into undefined, it will cause breadcrumb miss experimentId.
-      Location.pathname -> /workbench/experiment/info/{experimentID}
-      So slice out experimentId string from location.pathname to reassign experimentId.
-      */
-    if (location.pathname !== '/workbench/experiment') {
-      const sliceString = String('/workbench/experiment/info');
-      this.experimentID = location.pathname.slice(sliceString.length + 1);
-    }
-  }
-
-  deleteExperiments() {
-    for (let i = this.checkedList.length - 1; i >= 0; i--) {
-      if (this.checkedList[i] === true) {
-        this.onDeleteExperiment(this.experimentList[i].experimentId, false);
-      }
-    }
-
-    this.selectAllChecked = false;
-  }
-
-  selectAll() {
-    for (let i = 0; i < this.checkedList.length; i++) {
-      this.checkedList[i] = this.selectAllChecked;
-    }
-  }
-
-  // TODO(jasoonn): Filter experiment list
-  filter(event) {
-    console.log(this.searchText + event.key);
-  }
-  // TODO(jasoonn): Perform part of list
-  showChange() {
-    console.log('Change to ' + this.showExperiment);
-  }
-  // TODO(jasoonn): Start experiment
-  startExperiment(Experiment) {
-    console.log(Experiment);
+    this.experimentService.infoEmitted$.pipe(delay(0)).subscribe((id) => (this.experimentID = id));
   }
 }
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
index 06b2eb7..d6bd0da 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
@@ -1,20 +1,3 @@
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
-import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { RouterModule } from '@angular/router';
-import { PipeSharedModule } from '@submarine/pipe/pipe-shared.module';
-import { NgxChartsModule } from '@swimlane/ngx-charts';
-import { NgZorroAntdModule } from 'ng-zorro-antd';
-import { ExperimentCustomizedFormComponent } from './experiment-customized-form/experiment-customized-form.component';
-import { ChartsComponent } from './experiment-info/charts/charts.component';
-import { ExperimentInfoComponent } from './experiment-info/experiment-info.component';
-import { HyperParamsComponent } from './experiment-info/hyper-params/hyper-params.component';
-import { MetricsComponent } from './experiment-info/metrics/metrics.component';
-import { OutputsComponent } from './experiment-info/outputs/outputs.component';
-import { ExperimentComponent } from './experiment.component';
-import { ExperimentRoutingModule } from './experiment-routing.module';
-import { ExperimentHomeComponent } from './experiment-home/experiment-home.component';
-import { ExperimentPredefinedFormComponent } from './experiment-predefined-form/experiment-predefined-form.component';
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -34,6 +17,27 @@
  * under the License.
  */
 
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
+import { PipeSharedModule } from '@submarine/pipe/pipe-shared.module';
+import { NgxChartsModule } from '@swimlane/ngx-charts';
+import { NgZorroAntdModule } from 'ng-zorro-antd';
+import { ExperimentComponent } from './experiment.component';
+import { ExperimentListComponent } from './experiment-home/experiment-list/experiment-list.component';
+import { ExperimentRoutingModule } from './experiment-routing.module';
+import { ExperimentInfoComponent } from './experiment-info/experiment-info.component';
+import { HyperParamsComponent } from './experiment-info/hyper-params/hyper-params.component';
+import { MetricsComponent } from './experiment-info/metrics/metrics.component';
+import { ChartsComponent } from './experiment-info/charts/charts.component';
+import { OutputsComponent } from './experiment-info/outputs/outputs.component';
+import { ExperimentHomeComponent } from './experiment-home/experiment-home.component';
+import { ExperimentService } from '@submarine/services/experiment.service';
+import { ExperimentFormComponent } from './experiment-home/experiment-form/experiment-form.component';
+import { ExperimentPredefinedFormComponent } from './experiment-home/experiment-form/experiment-predefined-form/experiment-predefined-form.component';
+import { ExperimentCustomizedFormComponent } from './experiment-home/experiment-form/experiment-customized-form/experiment-customized-form.component';
+
 @NgModule({
   exports: [ExperimentComponent],
   imports: [
@@ -44,18 +48,21 @@
     NgxChartsModule,
     RouterModule,
     PipeSharedModule,
-    ExperimentRoutingModule
+    ExperimentRoutingModule,
   ],
+  providers: [ExperimentService],
   declarations: [
     ExperimentComponent,
+    ExperimentListComponent,
     ExperimentInfoComponent,
     HyperParamsComponent,
     MetricsComponent,
     ChartsComponent,
     OutputsComponent,
-    ExperimentCustomizedFormComponent,
     ExperimentHomeComponent,
-    ExperimentPredefinedFormComponent
-  ]
+    ExperimentFormComponent,
+    ExperimentPredefinedFormComponent,
+    ExperimentCustomizedFormComponent,
+  ],
 })
 export class ExperimentModule {}
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/workbench-routing.module.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/workbench-routing.module.ts
index c7c7313..bc838b1 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/workbench-routing.module.ts
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/workbench-routing.module.ts
@@ -20,10 +20,8 @@
 import { NgModule } from '@angular/core';
 import { ActivatedRouteSnapshot, RouterModule, RouterStateSnapshot, Routes } from '@angular/router';
 import { EnvironmentComponent } from '@submarine/pages/workbench/environment/environment.component';
-import { ExperimentComponent } from '@submarine/pages/workbench/experiment/experiment.component';
 import { WorkbenchComponent } from '@submarine/pages/workbench/workbench.component';
 import { DataComponent } from './data/data.component';
-import { ExperimentInfoComponent } from './experiment/experiment-info/experiment-info.component';
 import { HomeComponent } from './home/home.component';
 import { InterpreterComponent } from './interpreter/interpreter.component';
 import { ModelComponent } from './model/model.component';
@@ -38,42 +36,42 @@
       {
         path: '',
         pathMatch: 'full',
-        redirectTo: 'experiment'
+        redirectTo: 'experiment',
       },
       {
         path: 'home',
         component: HomeComponent,
-        canActivate: ['canActivatePage']
+        canActivate: ['canActivatePage'],
       },
       {
         path: 'workspace',
         component: WorkspaceComponent,
-        canActivate: ['canActivatePage']
+        canActivate: ['canActivatePage'],
       },
       {
         path: 'interpreter',
         component: InterpreterComponent,
-        canActivate: ['canActivatePage']
+        canActivate: ['canActivatePage'],
       },
       {
         path: 'experiment',
         loadChildren: () => import('./experiment/experiment.module').then((m) => m.ExperimentModule),
-        canActivate: ['canActivatePage']
+        canActivate: ['canActivatePage'],
       },
       {
         path: 'environment',
         component: EnvironmentComponent,
-        canActivate: ['canActivatePage']
+        canActivate: ['canActivatePage'],
       },
       {
         path: 'data',
         component: DataComponent,
-        canActivate: ['canActivatePage']
+        canActivate: ['canActivatePage'],
       },
       {
         path: 'model',
         component: ModelComponent,
-        canActivate: ['canActivatePage']
+        canActivate: ['canActivatePage'],
       },
       {
         path: 'notebook',
@@ -83,10 +81,10 @@
       {
         path: 'manager',
         loadChildren: () => import('./manager/manager.module').then((m) => m.ManagerModule),
-        canActivate: ['canActivatePage']
-      }
-    ]
-  }
+        canActivate: ['canActivatePage'],
+      },
+    ],
+  },
 ];
 
 @NgModule({
@@ -100,8 +98,8 @@
         console.log('currentPage', currentPage);
         if (disablePaths.includes(currentPage)) return false;
         else return true;
-      }
-    }
-  ]
+      },
+    },
+  ],
 })
-export class WorkbenchRoutingModule { }
+export class WorkbenchRoutingModule {}
diff --git a/submarine-workbench/workbench-web/src/app/services/experiment.form.service.ts b/submarine-workbench/workbench-web/src/app/services/experiment.form.service.ts
index 9537879..2341365 100644
--- a/submarine-workbench/workbench-web/src/app/services/experiment.form.service.ts
+++ b/submarine-workbench/workbench-web/src/app/services/experiment.form.service.ts
@@ -18,16 +18,16 @@
  */
 
 import { Injectable } from '@angular/core';
-import { Subject } from 'rxjs';
 import { ModalProps } from '@submarine/interfaces/modal-props';
+import { BehaviorSubject, Subject } from 'rxjs';
 
 @Injectable({
-  providedIn: 'root'
+  providedIn: 'root',
 })
 export class ExperimentFormService {
   // Subject(observable source)
   private stepServiceSource = new Subject<number>();
-  private fetchListServiceSource = new Subject<boolean>();
+  private fetchListServiceSource = new BehaviorSubject<boolean>(true); // use behaviorSubject to immediately fetch for the first time
   private btnStatusServiceSource = new Subject<boolean>();
   private modalPropsServiceSource = new Subject<ModalProps>();
 
@@ -53,9 +53,10 @@
       okText: 'Next step',
       isVisible: false,
       currentStep: 0,
-      formType: null
+      formType: null,
     });
   }
+
   fetchList() {
     this.fetchListServiceSource.next(true);
   }
diff --git a/submarine-workbench/workbench-web/src/app/services/experiment.service.ts b/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
index 71f8d9c..8672ebd 100644
--- a/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
+++ b/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
@@ -25,21 +25,31 @@
 import { ExperimentTemplate } from '@submarine/interfaces/experiment-template';
 import { ExperimentTemplateSubmit } from '@submarine/interfaces/experiment-template-submit';
 import { BaseApiService } from '@submarine/services/base-api.service';
-import { of, throwError, Observable } from 'rxjs';
+import { of, throwError, Observable, Subject } from 'rxjs';
 import { catchError, map, switchMap } from 'rxjs/operators';
 
 @Injectable({
   providedIn: 'root',
 })
 export class ExperimentService {
+  /*
+    communicate between route-outlet and parent
+    send experiment-id from ExperimentInfo to ExperimentHome
+  */
+  private emitInfoSource = new Subject<string>();
+  infoEmitted$ = this.emitInfoSource.asObservable();
+
   constructor(private baseApi: BaseApiService, private httpClient: HttpClient) {}
 
+  emitInfo(id: string) {
+    this.emitInfoSource.next(id);
+  }
+
   fetchExperimentList(): Observable<ExperimentInfo[]> {
     const apiUrl = this.baseApi.getRestApi('/v1/experiment');
     return this.httpClient.get<Rest<ExperimentInfo[]>>(apiUrl).pipe(
       switchMap((res) => {
         if (res.success) {
-          console.log(res.result);
           return of(res.result);
         } else {
           throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 'get');
@@ -223,6 +233,6 @@
     } else {
       showSec = sec.toString();
     }
-    return showHr + ':' + showMin + ':' + showSec;
+    return `${showHr}:${showMin}:${showSec}`;
   }
 }