[AMBARI-25028] [Log Search UI] Populate `Component Name` in validator (#67)

* MBARI-23456. Add cloud mode documentation (#66)

* [AMBARI-25028] [Log Search UI] Populate `Component Name` in validator
diff --git a/ambari-logsearch-web/src/app/modules/shared/components/dropdown-button/dropdown-button.component.html b/ambari-logsearch-web/src/app/modules/shared/components/dropdown-button/dropdown-button.component.html
index 52f97be..b24d15a 100644
--- a/ambari-logsearch-web/src/app/modules/shared/components/dropdown-button/dropdown-button.component.html
+++ b/ambari-logsearch-web/src/app/modules/shared/components/dropdown-button/dropdown-button.component.html
@@ -15,16 +15,18 @@
   limitations under the License.
 -->
 
-<div [ngClass]="{'dropup': isDropup, 'has-selection': hasSelection}">
-  <button [ngClass]="['btn', 'dropdown-toggle', buttonClass]" data-toggle="dropdown">
+<div [ngClass]="{ dropup: isDropup, 'has-selection': hasSelection }">
+  <button [ngClass]="['btn', 'dropdown-toggle', buttonClass]" [class.disabled]="disabled" data-toggle="dropdown">
     <span class="filter-label">
       <span *ngIf="iconClass || label" [class.plain]="!isMultipleChoice && !hideCaret && showSelectedValue">
         <span *ngIf="iconClass" [ngClass]="iconClass"></span>
-        <span *ngIf="label && (!hasSelection || isMultipleChoice || showCommonLabelWithSelection)"
-              [class.label-before-selection]="isSelectionDisplayable">
-          {{label}}
+        <span
+          *ngIf="label && (!hasSelection || isMultipleChoice || showCommonLabelWithSelection)"
+          [class.label-before-selection]="isSelectionDisplayable"
+        >
+          {{ label }}
         </span>
-        <span *ngIf="showTotalSelection && totalSelection" class="total-selection badge">{{totalSelection}}</span>
+        <span *ngIf="showTotalSelection && totalSelection" class="total-selection badge">{{ totalSelection }}</span>
       </span>
       <span *ngIf="isSelectionDisplayable">
         <span class="selected-item-label" *ngFor="let item of selectedItems">{{ item.label | translate }}</span>
@@ -32,8 +34,15 @@
       <span *ngIf="!hideCaret" class="caret"></span>
     </span>
   </button>
-  <ul data-component="dropdown-list" (selectedItemChange)="updateSelection($event)"
-    [ngClass]="{'dropdown-menu': true, 'dropdown-menu-right': isRightAlign}" [closeOnSelection]="closeOnSelection"
-    [items]="options" [actionArguments]="listItemArguments" [isMultipleChoice]="isMultipleChoice"
-    [useClearToDefaultSelection]="useClearToDefaultSelection" [useLocalFilter]="useDropDownLocalFilter"></ul>
+  <ul
+    data-component="dropdown-list"
+    (selectedItemChange)="updateSelection($event)"
+    [ngClass]="{ 'dropdown-menu': true, 'dropdown-menu-right': isRightAlign }"
+    [closeOnSelection]="closeOnSelection"
+    [items]="options"
+    [actionArguments]="listItemArguments"
+    [isMultipleChoice]="isMultipleChoice"
+    [useClearToDefaultSelection]="useClearToDefaultSelection"
+    [useLocalFilter]="useDropDownLocalFilter"
+  ></ul>
 </div>
diff --git a/ambari-logsearch-web/src/app/modules/shared/components/dropdown-button/dropdown-button.component.ts b/ambari-logsearch-web/src/app/modules/shared/components/dropdown-button/dropdown-button.component.ts
index 77ea8e1..fb8a981 100644
--- a/ambari-logsearch-web/src/app/modules/shared/components/dropdown-button/dropdown-button.component.ts
+++ b/ambari-logsearch-web/src/app/modules/shared/components/dropdown-button/dropdown-button.component.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { Component, Input, Output, EventEmitter } from '@angular/core';
+import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
 import { ListItem } from '@app/classes/list-item';
 import { UtilsService } from '@app/services/utils.service';
 
@@ -25,8 +25,7 @@
   templateUrl: './dropdown-button.component.html',
   styleUrls: ['./dropdown-button.component.less']
 })
-export class DropdownButtonComponent {
-
+export class DropdownButtonComponent implements OnChanges {
   @Input()
   label?: string;
 
@@ -76,6 +75,9 @@
   @Input()
   closeOnSelection = true;
 
+  @Input()
+  disabled = false;
+
   protected selectedItems: ListItem[] = [];
 
   get selection(): ListItem[] {
@@ -83,15 +85,19 @@
   }
 
   set selection(items: ListItem[]) {
-    this.selectedItems = <ListItem[]>(Array.isArray(items) ? items : (items || []));
+    this.selectedItems = <ListItem[]>(Array.isArray(items) ? items : items || []);
     if (this.selectedItems.length > 1 && !this.isMultipleChoice) {
       this.selectedItems = this.selectedItems.slice(0, 1);
     }
     if (this.isMultipleChoice && this.options) {
-      this.options.forEach((option: ListItem): void => {
-        const selectionItem = this.selectedItems.find((item: ListItem): boolean => this.utils.isEqual(item.value, option.value));
-        option.isChecked = !!selectionItem;
-      });
+      this.options.forEach(
+        (option: ListItem): void => {
+          const selectionItem = this.selectedItems.find(
+            (item: ListItem): boolean => this.utils.isEqual(item.value, option.value)
+          );
+          option.isChecked = !!selectionItem;
+        }
+      );
     }
   }
 
@@ -113,9 +119,22 @@
     return this.showSelectedValue && !this.isMultipleChoice && this.hasSelection;
   }
 
-  constructor(
-    protected utils: UtilsService
-  ) {}
+  get value(): any {
+    const values = this.selectedItems && this.selectedItems.length && this.selectedItems.map(item => item.value);
+    return this.isMultipleChoice ? values : values[0];
+  }
+
+  constructor(protected utils: UtilsService) {}
+
+  ngOnChanges(changes: SimpleChanges) {
+    if (changes.options) {
+      this.hanldeOptionsChange();
+    }
+  }
+
+  hanldeOptionsChange() {
+    this.filterAndSetSelection();
+  }
 
   clearSelection(silent: boolean = false) {
     let hasChange = false;
@@ -128,14 +147,16 @@
     }
   }
 
-  updateSelection(updates: ListItem | ListItem[], callOnChange: boolean = true): boolean {
+  updateSelection(updates: ListItem | ListItem[]): boolean {
     let hasChange = false;
     if (updates && (!Array.isArray(updates) || updates.length)) {
       const items: ListItem[] = Array.isArray(updates) ? updates : [updates];
       if (this.isMultipleChoice) {
         items.forEach((item: ListItem) => {
           if (this.options && this.options.length) {
-            const itemToUpdate: ListItem = this.options.find((option: ListItem) => this.utils.isEqual(option.value, item.value));
+            const itemToUpdate: ListItem = this.options.find((option: ListItem) =>
+              this.utils.isEqual(option.value, item.value)
+            );
             if (itemToUpdate) {
               hasChange = hasChange || itemToUpdate.isChecked !== item.isChecked;
               itemToUpdate.isChecked = item.isChecked;
@@ -151,15 +172,18 @@
         });
       }
     } else {
-      this.options.forEach((item: ListItem) => item.isChecked = false);
+      this.options.forEach((item: ListItem) => (item.isChecked = false));
     }
-    const checkedItems = this.options.filter((option: ListItem): boolean => option.isChecked);
-    this.selection = checkedItems;
+    this.filterAndSetSelection();
     if (hasChange) {
-      const selectedValues = checkedItems.map((option: ListItem): any => option.value);
+      const selectedValues = this.selection.map((option: ListItem): any => option.value);
       this.selectItem.emit(this.isMultipleChoice ? selectedValues : selectedValues.shift());
     }
     return hasChange;
   }
 
+  protected filterAndSetSelection() {
+    const checkedItems = this.options.filter((option: ListItem): boolean => option.isChecked);
+    this.selection = checkedItems;
+  }
 }
diff --git a/ambari-logsearch-web/src/app/modules/shared/components/filter-dropdown/filter-dropdown.component.spec.ts b/ambari-logsearch-web/src/app/modules/shared/components/filter-dropdown/filter-dropdown.component.spec.ts
index 4157333..a8aff3f 100644
--- a/ambari-logsearch-web/src/app/modules/shared/components/filter-dropdown/filter-dropdown.component.spec.ts
+++ b/ambari-logsearch-web/src/app/modules/shared/components/filter-dropdown/filter-dropdown.component.spec.ts
@@ -15,37 +15,41 @@
  * limitations under the License.
  */
 
-import {NO_ERRORS_SCHEMA} from '@angular/core';
-import {async, ComponentFixture, TestBed} from '@angular/core/testing';
-import {MockHttpRequestModules, TranslationModules} from '@app/test-config.spec';
-import {StoreModule} from '@ngrx/store';
-import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
-import {AppStateService, appState} from '@app/services/storage/app-state.service';
-import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
-import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
-import {AuditLogsGraphDataService, auditLogsGraphData} from '@app/services/storage/audit-logs-graph-data.service';
-import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
-import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
+import { NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockHttpRequestModules, TranslationModules } from '@app/test-config.spec';
+import { StoreModule } from '@ngrx/store';
+import { AppSettingsService, appSettings } from '@app/services/storage/app-settings.service';
+import { AppStateService, appState } from '@app/services/storage/app-state.service';
+import { AuditLogsService, auditLogs } from '@app/services/storage/audit-logs.service';
+import { AuditLogsFieldsService, auditLogsFields } from '@app/services/storage/audit-logs-fields.service';
+import { AuditLogsGraphDataService, auditLogsGraphData } from '@app/services/storage/audit-logs-graph-data.service';
+import { ServiceLogsService, serviceLogs } from '@app/services/storage/service-logs.service';
+import { ServiceLogsFieldsService, serviceLogsFields } from '@app/services/storage/service-logs-fields.service';
 import {
-  ServiceLogsHistogramDataService, serviceLogsHistogramData
+  ServiceLogsHistogramDataService,
+  serviceLogsHistogramData
 } from '@app/services/storage/service-logs-histogram-data.service';
-import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
-import {TabsService, tabs} from '@app/services/storage/tabs.service';
-import {ClustersService, clusters} from '@app/services/storage/clusters.service';
-import {ComponentsService, components} from '@app/services/storage/components.service';
-import {HostsService, hosts} from '@app/services/storage/hosts.service';
-import {UtilsService} from '@app/services/utils.service';
-import {LogsContainerService} from '@app/services/logs-container.service';
-import {AuthService} from '@app/services/auth.service';
+import {
+  ServiceLogsTruncatedService,
+  serviceLogsTruncated
+} from '@app/services/storage/service-logs-truncated.service';
+import { TabsService, tabs } from '@app/services/storage/tabs.service';
+import { ClustersService, clusters } from '@app/services/storage/clusters.service';
+import { ComponentsService, components } from '@app/services/storage/components.service';
+import { HostsService, hosts } from '@app/services/storage/hosts.service';
+import { UtilsService } from '@app/services/utils.service';
+import { LogsContainerService } from '@app/services/logs-container.service';
+import { AuthService } from '@app/services/auth.service';
 
-import {FilterDropdownComponent} from './filter-dropdown.component';
-import {ClusterSelectionService} from '@app/services/storage/cluster-selection.service';
-import {LogsStateService} from '@app/services/storage/logs-state.service';
-import {RoutingUtilsService} from '@app/services/routing-utils.service';
-import {LogsFilteringUtilsService} from '@app/services/logs-filtering-utils.service';
-import {RouterTestingModule} from '@angular/router/testing';
-import {NotificationService} from '@modules/shared/services/notification.service';
-import {NotificationsService} from 'angular2-notifications/src/notifications.service';
+import { FilterDropdownComponent } from './filter-dropdown.component';
+import { ClusterSelectionService } from '@app/services/storage/cluster-selection.service';
+import { LogsStateService } from '@app/services/storage/logs-state.service';
+import { RoutingUtilsService } from '@app/services/routing-utils.service';
+import { LogsFilteringUtilsService } from '@app/services/logs-filtering-utils.service';
+import { RouterTestingModule } from '@angular/router/testing';
+import { NotificationService } from '@modules/shared/services/notification.service';
+import { NotificationsService } from 'angular2-notifications/src/notifications.service';
 
 import * as auth from '@app/store/reducers/auth.reducers';
 import { EffectsModule } from '@ngrx/effects';
@@ -77,8 +81,7 @@
     const httpClient = {
       get: () => {
         return {
-          subscribe: () => {
-          }
+          subscribe: () => {}
         };
       }
     };
@@ -136,9 +139,8 @@
         NotificationsService,
         NotificationService
       ],
-      schemas: [NO_ERRORS_SCHEMA]
-    })
-    .compileComponents();
+      schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
@@ -150,5 +152,4 @@
   it('should create component', () => {
     expect(component).toBeTruthy();
   });
-
 });
diff --git a/ambari-logsearch-web/src/app/modules/shared/components/filter-dropdown/filter-dropdown.component.ts b/ambari-logsearch-web/src/app/modules/shared/components/filter-dropdown/filter-dropdown.component.ts
index b0c766e..2bcf4a2 100644
--- a/ambari-logsearch-web/src/app/modules/shared/components/filter-dropdown/filter-dropdown.component.ts
+++ b/ambari-logsearch-web/src/app/modules/shared/components/filter-dropdown/filter-dropdown.component.ts
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-import {Component, forwardRef} from '@angular/core';
-import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
-import {DropdownButtonComponent} from '@modules/shared/components/dropdown-button/dropdown-button.component';
-import {ListItem} from '@app/classes/list-item';
+import { Component, forwardRef, Input } from '@angular/core';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+import { DropdownButtonComponent } from '@modules/shared/components/dropdown-button/dropdown-button.component';
+import { ListItem } from '@app/classes/list-item';
 
 @Component({
   selector: 'filter-dropdown',
@@ -33,7 +33,6 @@
   ]
 })
 export class FilterDropdownComponent extends DropdownButtonComponent implements ControlValueAccessor {
-
   private onChange;
 
   private _onChange(value) {
@@ -42,6 +41,9 @@
     }
   }
 
+  @Input()
+  options: ListItem[] = [];
+
   updateSelection(updates: ListItem | ListItem[], callOnChange: boolean = true): boolean {
     const hasChange = super.updateSelection(updates);
     if (hasChange && callOnChange) {
@@ -50,15 +52,18 @@
     return hasChange;
   }
 
+  hanldeOptionsChange() {
+    super.hanldeOptionsChange();
+    this._onChange(this.selection);
+  }
+
   writeValue(items: ListItem[]) {
-    this.selection = items ? (Array.isArray(items) ? items : [items] ) : [];
+    this.selection = items ? (Array.isArray(items) ? items : [items]) : [];
   }
 
   registerOnChange(callback: any): void {
     this.onChange = callback;
   }
 
-  registerOnTouched() {
-  }
-
+  registerOnTouched() {}
 }
diff --git a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-configuration/shipper-configuration.component.spec.ts b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-configuration/shipper-configuration.component.spec.ts
index 0ec4f56..a8e2b1f 100644
--- a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-configuration/shipper-configuration.component.spec.ts
+++ b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-configuration/shipper-configuration.component.spec.ts
@@ -16,39 +16,45 @@
  * limitations under the License.
  */
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
-import {ShipperConfigurationComponent} from './shipper-configuration.component';
-import {StoreModule} from '@ngrx/store';
-import {auditLogs, AuditLogsService} from '@app/services/storage/audit-logs.service';
-import {serviceLogsTruncated, ServiceLogsTruncatedService} from '@app/services/storage/service-logs-truncated.service';
-import {components, ComponentsService} from '@app/services/storage/components.service';
-import {UtilsService} from '@app/services/utils.service';
-import {tabs, TabsService} from '@app/services/storage/tabs.service';
-import {serviceLogs, ServiceLogsService} from '@app/services/storage/service-logs.service';
-import {hosts, HostsService} from '@app/services/storage/hosts.service';
-import {MockHttpRequestModules, TranslationModules} from '@app/test-config.spec';
-import {ComponentGeneratorService} from '@app/services/component-generator.service';
-import {auditLogsGraphData, AuditLogsGraphDataService} from '@app/services/storage/audit-logs-graph-data.service';
-import {serviceLogsHistogramData, ServiceLogsHistogramDataService} from '@app/services/storage/service-logs-histogram-data.service';
-import {clusters, ClustersService} from '@app/services/storage/clusters.service';
-import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
-import {appSettings, AppSettingsService} from '@app/services/storage/app-settings.service';
-import {appState, AppStateService} from '@app/services/storage/app-state.service';
-import {ClusterSelectionService} from '@app/services/storage/cluster-selection.service';
-import {serviceLogsFields, ServiceLogsFieldsService} from '@app/services/storage/service-logs-fields.service';
-import {LogsContainerService} from '@app/services/logs-container.service';
-import {ShipperRoutingModule} from '@modules/shipper/shipper-routing.module';
-import {ShipperClusterServiceListComponent} from '@modules/shipper/components/shipper-cluster-service-list/shipper-cluster-service-list.component';
-import {ShipperServiceConfigurationFormComponent} from '@modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component';
-import {FormsModule, ReactiveFormsModule} from '@angular/forms';
-import {TypeaheadModule} from 'ngx-bootstrap';
-import {DisableControlDirective} from '@modules/shared/directives/disable-control.directive';
-import {ModalComponent} from '@modules/shared/components/modal/modal.component';
-import {RouterTestingModule} from '@angular/router/testing';
-import {ShipperClusterServiceListService} from '@modules/shipper/services/shipper-cluster-service-list.service';
-import {ShipperConfigurationService} from '@modules/shipper/services/shipper-configuration.service';
-import {NotificationService} from '@modules/shared/services/notification.service';
-import {NotificationsService} from 'angular2-notifications/src/notifications.service';
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { ShipperConfigurationComponent } from './shipper-configuration.component';
+import { StoreModule } from '@ngrx/store';
+import { auditLogs, AuditLogsService } from '@app/services/storage/audit-logs.service';
+import {
+  serviceLogsTruncated,
+  ServiceLogsTruncatedService
+} from '@app/services/storage/service-logs-truncated.service';
+import { components, ComponentsService } from '@app/services/storage/components.service';
+import { UtilsService } from '@app/services/utils.service';
+import { tabs, TabsService } from '@app/services/storage/tabs.service';
+import { serviceLogs, ServiceLogsService } from '@app/services/storage/service-logs.service';
+import { hosts, HostsService } from '@app/services/storage/hosts.service';
+import { MockHttpRequestModules, TranslationModules } from '@app/test-config.spec';
+import { ComponentGeneratorService } from '@app/services/component-generator.service';
+import { auditLogsGraphData, AuditLogsGraphDataService } from '@app/services/storage/audit-logs-graph-data.service';
+import {
+  serviceLogsHistogramData,
+  ServiceLogsHistogramDataService
+} from '@app/services/storage/service-logs-histogram-data.service';
+import { clusters, ClustersService } from '@app/services/storage/clusters.service';
+import { AuditLogsFieldsService, auditLogsFields } from '@app/services/storage/audit-logs-fields.service';
+import { appSettings, AppSettingsService } from '@app/services/storage/app-settings.service';
+import { appState, AppStateService } from '@app/services/storage/app-state.service';
+import { ClusterSelectionService } from '@app/services/storage/cluster-selection.service';
+import { serviceLogsFields, ServiceLogsFieldsService } from '@app/services/storage/service-logs-fields.service';
+import { LogsContainerService } from '@app/services/logs-container.service';
+import { ShipperRoutingModule } from '@modules/shipper/shipper-routing.module';
+import { ShipperClusterServiceListComponent } from '@modules/shipper/components/shipper-cluster-service-list/shipper-cluster-service-list.component';
+import { ShipperServiceConfigurationFormComponent } from '@modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { TypeaheadModule } from 'ngx-bootstrap';
+import { DisableControlDirective } from '@modules/shared/directives/disable-control.directive';
+import { ModalComponent } from '@modules/shared/components/modal/modal.component';
+import { RouterTestingModule } from '@angular/router/testing';
+import { ShipperClusterServiceListService } from '@modules/shipper/services/shipper-cluster-service-list.service';
+import { ShipperConfigurationService } from '@modules/shipper/services/shipper-configuration.service';
+import { NotificationService } from '@modules/shared/services/notification.service';
+import { NotificationsService } from 'angular2-notifications/src/notifications.service';
 
 describe('ShipperConfigurationComponent', () => {
   let component: ShipperConfigurationComponent;
@@ -110,9 +116,9 @@
         ShipperServiceConfigurationFormComponent,
         DisableControlDirective,
         ModalComponent
-      ]
-    })
-    .compileComponents();
+      ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
diff --git a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-configuration/shipper-configuration.component.ts b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-configuration/shipper-configuration.component.ts
index d8fccbd..82ae869 100644
--- a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-configuration/shipper-configuration.component.ts
+++ b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-configuration/shipper-configuration.component.ts
@@ -15,25 +15,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {Component, Input, OnDestroy, OnInit, ViewChild} from '@angular/core';
-import {ActivatedRoute, Router} from '@angular/router';
-import {Response} from '@angular/http';
-import {Observable} from 'rxjs/Observable';
+import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { Response } from '@angular/http';
+import { Observable } from 'rxjs/Observable';
 import 'rxjs/add/operator/skipWhile';
 
-import {NotificationService, NotificationType} from '@modules/shared/services/notification.service';
-import {CanComponentDeactivate} from '@modules/shared/services/can-deactivate-guard.service';
+import { NotificationService, NotificationType } from '@modules/shared/services/notification.service';
+import { CanComponentDeactivate } from '@modules/shared/services/can-deactivate-guard.service';
 
-import {ShipperCluster} from '../../models/shipper-cluster.type';
-import {ShipperClusterService} from '../../models/shipper-cluster-service.type';
-import {ShipperConfigurationService} from '../../services/shipper-configuration.service';
-import {ShipperClusterServiceListService} from '../../services/shipper-cluster-service-list.service';
-import {
-  ShipperServiceConfigurationFormComponent
-} from '@modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component';
-import {TranslateService} from '@ngx-translate/core';
-import {ClusterSelectionService} from '@app/services/storage/cluster-selection.service';
-import {Subscription} from 'rxjs/Subscription';
+import { ShipperCluster } from '../../models/shipper-cluster.type';
+import { ShipperClusterService } from '../../models/shipper-cluster-service.type';
+import { ShipperConfigurationService } from '../../services/shipper-configuration.service';
+import { ShipperClusterServiceListService } from '../../services/shipper-cluster-service-list.service';
+import { ShipperServiceConfigurationFormComponent } from '@modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component';
+import { TranslateService } from '@ngx-translate/core';
+import { ClusterSelectionService } from '@app/services/storage/cluster-selection.service';
+import { Subscription } from 'rxjs/Subscription';
 import { BehaviorSubject } from 'rxjs/BehaviorSubject';
 import { FormGroup } from '@angular/forms';
 
@@ -43,7 +41,6 @@
   styleUrls: ['./shipper-configuration.component.less']
 })
 export class ShipperConfigurationComponent implements CanComponentDeactivate, OnInit, OnDestroy {
-
   static clusterSelectionStoreKey = 'shipper';
 
   @Input()
@@ -57,21 +54,25 @@
   private clusterName$: Observable<ShipperClusterService> = this.activatedRoute.params.map(params => params.cluster);
   private serviceName$: Observable<ShipperClusterService> = this.activatedRoute.params.map(params => params.service);
 
-  private serviceNamesList$: Observable<ShipperClusterService[]> = this.clusterName$.switchMap((cluster: ShipperCluster) => {
-    return cluster ? this.shipperClusterServiceListService.getServicesForCluster(cluster) : Observable.of(undefined);
-  });
+  private serviceNamesList$: Observable<ShipperClusterService[]> = this.clusterName$.switchMap(
+    (cluster: ShipperCluster) => {
+      return cluster ? this.shipperClusterServiceListService.getServicesForCluster(cluster) : Observable.of(undefined);
+    }
+  );
 
-  private configuration$: Observable<{[key: string]: any}> = Observable.combineLatest(
-      this.clusterName$,
-      this.serviceName$
-    ).switchMap(([clusterName, serviceName]: [ShipperCluster, ShipperClusterService]) => {
-      return clusterName && serviceName ?
-        this.shipperConfigurationService.loadConfiguration(clusterName, serviceName) : Observable.of(undefined);
-    });
+  private configuration$: Observable<{
+    [key: string]: any;
+  }> = Observable.combineLatest(this.clusterName$, this.serviceName$).switchMap(
+    ([clusterName, serviceName]: [ShipperCluster, ShipperClusterService]) => {
+      return clusterName && serviceName
+        ? this.shipperConfigurationService.loadConfiguration(clusterName, serviceName)
+        : Observable.of(undefined);
+    }
+  );
 
   private subscriptions: Subscription[] = [];
 
-  validationResponse: {[key: string]: any};
+  validationResponse: { [key: string]: any };
 
   constructor(
     private router: Router,
@@ -81,7 +82,7 @@
     private notificationService: NotificationService,
     private translate: TranslateService,
     private clusterSelectionStoreService: ClusterSelectionService
-  ) { }
+  ) {}
 
   ngOnInit() {
     this.subscriptions.push(
@@ -98,7 +99,8 @@
   }
 
   private getPathMapForClusterFirstService(cluster: ShipperCluster): Observable<string[]> {
-    return this.shipperClusterServiceListService.getServicesForCluster(cluster)
+    return this.shipperClusterServiceListService
+      .getServicesForCluster(cluster)
       .switchMap((serviceNamesList: ShipperClusterService[]) => {
         return Observable.of(this.getRouterLink([cluster, serviceNamesList[0]]));
       });
@@ -112,26 +114,42 @@
     if (clusterName) {
       this.clusterName$.first().subscribe((currentClusterName: ShipperCluster) => {
         if (currentClusterName !== clusterName) {
-          this.getPathMapForClusterFirstService(clusterName).first().subscribe((path: string[]) => this.router.navigate(path));
+          this.getPathMapForClusterFirstService(clusterName)
+            .first()
+            .subscribe((path: string[]) => this.router.navigate(path));
         }
       });
     }
-  }
+  };
 
   private getRouterLink(path: string | string[]): string[] {
     return [...this.routerPath, ...(Array.isArray(path) ? path : [path])];
   }
 
-  getResponseHandler(cmd: string, type: string, form?: FormGroup) {
-    const msgVariables = form.getRawValue();
+  getResponseHandler(cmd: string, type: string, msgVariables: any = {}, form?: FormGroup) {
     return (response: Response) => {
       const result = response.json();
       // @ToDo change the backend response status to some error code if the configuration is not valid and don't use the .message prop
-      const resultType = response ? (response.ok && !result.errorMessage ? NotificationType.SUCCESS : NotificationType.ERROR) : type;
-      const translateParams = {errorMessage: (result && result.message) || '', ...msgVariables, ...result};
+      const resultType = response
+        ? response.ok && !result.errorMessage
+          ? NotificationType.SUCCESS
+          : NotificationType.ERROR
+        : type;
+      const translateParams = {
+        errorMessage: (result && result.message) || '',
+        ...msgVariables,
+        ...result
+      };
       const title = this.translate.instant(`shipperConfiguration.action.${cmd}.title`, translateParams);
-      const message = this.translate.instant(`shipperConfiguration.action.${cmd}.${resultType}.message`, translateParams);
-      this.notificationService.addNotification({type: resultType, title, message});
+      const message = this.translate.instant(
+        `shipperConfiguration.action.${cmd}.${resultType}.message`,
+        translateParams
+      );
+      this.notificationService.addNotification({
+        type: resultType,
+        title,
+        message
+      });
       if (resultType !== NotificationType.ERROR) {
         form.markAsPristine();
       }
@@ -149,23 +167,24 @@
         service: rawValue.serviceName,
         configuration: JSON.parse(rawValue.configuration)
       }).subscribe(
-        this.getResponseHandler(cmd, NotificationType.SUCCESS, configurationForm),
-        this.getResponseHandler(cmd, NotificationType.ERROR, configurationForm)
+        this.getResponseHandler(cmd, NotificationType.SUCCESS, rawValue, configurationForm),
+        this.getResponseHandler(cmd, NotificationType.ERROR, rawValue, configurationForm)
       );
     });
   }
 
-  private setValidationResult = (result: {[key: string]: any}) => {
+  private setValidationResult = (result: { [key: string]: any }) => {
     this.validationResponse = result;
-  }
+  };
 
   onValidationFormSubmit(validationForm: FormGroup): void {
     this.validationResponse = null;
     const rawValue = validationForm.getRawValue();
+    rawValue.componentName = rawValue.componentName[0].value;
     const request$: Observable<Response> = this.shipperConfigurationService.testConfiguration(rawValue);
     request$.subscribe(
-      this.getResponseHandler('validate', NotificationType.SUCCESS, validationForm),
-      this.getResponseHandler('validate', NotificationType.ERROR, validationForm)
+      this.getResponseHandler('validate', NotificationType.SUCCESS, rawValue, validationForm),
+      this.getResponseHandler('validate', NotificationType.ERROR, rawValue, validationForm)
     );
     request$
       .filter((response: Response): boolean => response.ok)
@@ -178,5 +197,4 @@
   canDeactivate() {
     return this.configurationFormRef.canDeactivate();
   }
-
 }
diff --git a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.html b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.html
index 7e91137..742eb1d 100644
--- a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.html
+++ b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.html
@@ -14,52 +14,78 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<ng-template #typeAheadTpl let-item="item">
-  {{item | translate}}
-</ng-template>
+<ng-template #typeAheadTpl let-item="item"> {{ item | translate }} </ng-template>
 <div class="container-fluid">
   <div class="row">
     <div class="shipper-form-configuration col-md-6">
       <form [formGroup]="configurationForm" (ngSubmit)="onConfigurationSubmit($event)">
         <fieldset [disabled]="disabled">
-          <h2>{{(serviceName ? 'shipperConfiguration.form.titleEdit' : 'shipperConfiguration.form.titleAdd') | translate}}</h2>
-          <div [ngClass]="{'has-error': serviceNameField.invalid, 'form-group': true}">
+          <h2>
+            {{
+              (serviceName ? 'shipperConfiguration.form.titleEdit' : 'shipperConfiguration.form.titleAdd') | translate
+            }}
+          </h2>
+          <div
+            [ngClass]="{
+              'has-error': serviceNameField.invalid && configurationForm.touched,
+              'form-group': true
+            }"
+          >
             <label>
-              {{'shipperConfiguration.form.serviceLabel' | translate}}
-              <span *ngIf="serviceNameField.errors && serviceNameField.errors.serviceNameExists"
-                    class="help-block validation-block pull-right">
-                {{'shipperConfiguration.form.errors.serviceName.exists' | translate}}
+              {{ 'shipperConfiguration.form.serviceLabel' | translate }}
+              <span
+                *ngIf="serviceNameField.errors && serviceNameField.errors.serviceNameExists"
+                class="help-block validation-block pull-right"
+              >
+                {{ 'shipperConfiguration.form.errors.serviceName.exists' | translate }}
               </span>
-              <span *ngIf="serviceNameField.errors && serviceNameField.errors.required"
-                    class="help-block validation-block pull-right">
-                {{'common.form.errors.required' | translate}}
+              <span
+                *ngIf="serviceNameField.errors && serviceNameField.errors.required"
+                class="help-block validation-block pull-right"
+              >
+                {{ 'common.form.errors.required' | translate }}
               </span>
             </label>
-            <input *ngIf="!serviceName" formControlName="serviceName" class="form-control">
+            <input *ngIf="!serviceName" formControlName="serviceName" class="form-control" />
             <ng-container *ngIf="serviceName">
-              <div class="shipper-configuration-service-name">{{serviceName}}</div>
-              <input type="hidden" name="serviceName" formControlName="serviceName">
+              <div class="shipper-configuration-service-name">{{ serviceName }}</div>
+              <input type="hidden" name="serviceName" formControlName="serviceName" />
             </ng-container>
           </div>
-          <input type="hidden" name="clusterName" formControlName="clusterName">
-          <div [ngClass]="{'has-error': configurationField.invalid, 'form-group': true}">
+          <input type="hidden" name="clusterName" formControlName="clusterName" />
+          <div
+            [ngClass]="{
+              'has-error': configurationField.invalid,
+              'form-group': true
+            }"
+          >
             <label>
-              {{'shipperConfiguration.form.configurationJSONLabel' | translate}}
-              <span *ngIf="configurationField.errors && configurationField.errors.invalidJSON"
-                    class="help-block validation-block pull-right">
-                {{'shipperConfiguration.form.errors.configuration.invalidJSON' | translate}}
+              {{ 'shipperConfiguration.form.configurationJSONLabel' | translate }}
+              <span
+                *ngIf="configurationField.errors && configurationField.errors.invalidJSON"
+                class="help-block validation-block pull-right"
+              >
+                {{ 'shipperConfiguration.form.errors.configuration.invalidJSON' | translate }}
               </span>
-              <span *ngIf="configurationField.errors && configurationField.errors.required"
-                    class="help-block validation-block pull-right">
-                {{'common.form.errors.required' | translate}}
+              <span
+                *ngIf="configurationField.errors && configurationField.errors.required"
+                class="help-block validation-block pull-right"
+              >
+                {{ 'common.form.errors.required' | translate }}
               </span>
             </label>
-            <textarea class="form-control configuration" name="configuration"
-              formControlName="configuration"></textarea>
+            <textarea
+              class="form-control configuration"
+              name="configuration"
+              formControlName="configuration"
+            ></textarea>
           </div>
-          <button class="btn btn-primary pull-right" type="submit"
-                  [disabled]="(!configurationForm.valid || configurationForm.pristine)">
-            {{'shipperConfiguration.form.saveBtn.label' | translate}}
+          <button
+            class="btn btn-primary pull-right"
+            type="submit"
+            [disabled]="!configurationForm.valid || configurationForm.pristine"
+          >
+            {{ 'shipperConfiguration.form.saveBtn.label' | translate }}
           </button>
         </fieldset>
       </form>
@@ -68,47 +94,67 @@
       <div class="container-fluid">
         <div class="row">
           <form [formGroup]="validatorForm" (ngSubmit)="onValidationSubmit($event)">
-            <h2>{{'shipperConfiguration.validator.title' | translate}}</h2>
-            <input type="hidden" name="clusterName" formControlName="clusterName">
+            <h2>{{ 'shipperConfiguration.validator.title' | translate }}</h2>
+            <input type="hidden" name="clusterName" formControlName="clusterName" />
             <div class="form-group" [class.has-warning]="componentNameField.invalid">
               <label>
-                {{'shipperConfiguration.validator.componentNameLabel' | translate}}
-                <span [class.hide]="!componentNameField.errors || !componentNameField.errors.required"
-                      class="help-block validation-block pull-right">
-                  {{'common.form.errors.required' | translate}}
+                <span
+                  [class.hide]="
+                    !componentNameField.errors || !componentNameField.errors.required || configurationForm.invalid
+                  "
+                  class="help-block validation-block pull-right"
+                >
+                  {{ 'common.form.errors.required' | translate }}
                 </span>
-                <span [class.hide]="!componentNameField.value || !componentNameField.errors || !componentNameField.errors.serviceNameDoesNotExistInConfiguration"
-                      class="help-block validation-block pull-right">
-                  {{'shipperConfiguration.form.errors.componentNameField.serviceNameDoesNotExistInConfiguration' | translate}}
+                <span
+                  [class.hide]="
+                    !componentNameField.value ||
+                    !componentNameField.errors ||
+                    !componentNameField.errors.serviceNameDoesNotExistInConfiguration
+                  "
+                  class="help-block validation-block pull-right"
+                >
+                  {{
+                    'shipperConfiguration.form.errors.componentNameField.serviceNameDoesNotExistInConfiguration'
+                      | translate
+                  }}
                 </span>
               </label>
-              <input class="form-control component-name" name="componentName" formControlName="componentName"
-                     [typeahead]="configurationComponents$ | async"
-                     [typeaheadItemTemplate]="typeAheadTpl"
-                     [typeaheadMinLength]="0"
-                     [disableControl]="configurationForm.invalid"
-                     autocomplete="off">
+              <filter-dropdown
+                [options]="configurationComponentsList$ | async"
+                formControlName="componentName"
+                [label]="'shipperConfiguration.validator.componentNameLabel' | translate"
+                [showCommonLabelWithSelection]="true"
+                [disabled]="configurationForm.invalid || !(configurationComponentsList$ | async).length"
+              ></filter-dropdown>
             </div>
             <div class="form-group" [class.has-warning]="sampleDataField.invalid">
               <label>
-                {{'shipperConfiguration.validator.sampleDataLabel' | translate}}
-                <span [class.hide]="!sampleDataField.errors || !sampleDataField.errors.required"
-                      class="help-block validation-block pull-right">
-                  {{'common.form.errors.required' | translate}}
+                {{ 'shipperConfiguration.validator.sampleDataLabel' | translate }}
+                <span
+                  [class.hide]="!sampleDataField.errors || !sampleDataField.errors.required"
+                  class="help-block validation-block pull-right"
+                >
+                  {{ 'common.form.errors.required' | translate }}
                 </span>
               </label>
-              <textarea class="form-control sample-data" name="sampleData" formControlName="sampleData"
-                        [disableControl]="configurationForm.invalid"></textarea>
+              <textarea
+                class="form-control sample-data"
+                name="sampleData"
+                formControlName="sampleData"
+                [disableControl]="configurationForm.invalid"
+              ></textarea>
             </div>
             <div *ngIf="validationResponse" class="form-group">
-              <label>
-                {{'shipperConfiguration.validator.result' | translate}}
-              </label>
-              <pre>{{validationResponse | json}}</pre>
+              <label> {{ 'shipperConfiguration.validator.result' | translate }} </label>
+              <pre>{{ validationResponse | json }}</pre>
             </div>
-            <button class="btn btn-default pull-right" type="submit"
-                    [disabled]="(!validatorForm.valid)">
-              <i class="fa fa-table" aria-hidden="true"></i> {{'shipperConfiguration.form.testBtn.label' | translate}}
+            <button
+              class="btn btn-default pull-right"
+              type="submit"
+              [disabled]="validatorForm.invalid || configurationForm.invalid"
+            >
+              <i class="fa fa-table" aria-hidden="true"></i> {{ 'shipperConfiguration.form.testBtn.label' | translate }}
             </button>
           </form>
         </div>
@@ -116,8 +162,14 @@
     </div>
   </div>
 </div>
-<modal *ngIf="isLeavingDirtyForm" (submit)="leaveDirtyFormConfirmed()" (cancel)="leaveDirtyFormCancelled()"
-       (close)="leaveDirtyFormCancelled()" showCloseButton="false" isSmallModal="true"
-       title="{{'shipperConfiguration.form.leavingDirty.title' | translate}}"
-       bodyText="{{'shipperConfiguration.form.leavingDirty.message' | translate}}">
+<modal
+  *ngIf="isLeavingDirtyForm"
+  (submit)="leaveDirtyFormConfirmed()"
+  (cancel)="leaveDirtyFormCancelled()"
+  (close)="leaveDirtyFormCancelled()"
+  showCloseButton="false"
+  isSmallModal="true"
+  title="{{ 'shipperConfiguration.form.leavingDirty.title' | translate }}"
+  bodyText="{{ 'shipperConfiguration.form.leavingDirty.message' | translate }}"
+>
 </modal>
diff --git a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.less b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.less
index f6f3713..0fa195c 100644
--- a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.less
+++ b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.less
@@ -16,39 +16,51 @@
  * limitations under the License.
  */
 
-@import "../../../shared/forms";
-
-textarea {
-  @extend input.form-control
-  min-height: 5em;
-  resize: vertical;
-  width: 100%;
-  &.validation-result,
-  &.configuration {
-    min-height: 30em;
+@import '../../../shared/forms';
+:host {
+  textarea {
+    &:extend(input.form-control);
+    min-height: 5em;
+    resize: vertical;
+    width: 100%;
+    &.validation-result,
+    &.configuration {
+      min-height: 30em;
+    }
+    &.sample-data {
+      min-height: 8em;
+    }
   }
-  &.sample-data {
-    min-height: 8em;
+  label {
+    width: 100%;
   }
-}
-label {
-  width: 100%;
-}
-.help-block.validation-block {
-  display: none;
-  font-size: .9em;
-  margin: 0;
-  opacity: 0;
-  transition: all 1s ease-in;
-}
-.has-error, .has-warning {
   .help-block.validation-block {
-    display: inline-block;
-    opacity: 1;
+    display: none;
+    font-size: 0.9em;
+    margin: 0;
+    opacity: 0;
+    transition: all 1s ease-in;
   }
-}
+  .has-error,
+  .has-warning {
+    .help-block.validation-block {
+      display: inline-block;
+      opacity: 1;
+    }
+  }
 
-.shipper-form-configuration {
-  background-color: @main-background-color;
-  padding-bottom: 4em;
+  .shipper-form-configuration {
+    background-color: @main-background-color;
+    padding-bottom: 4em;
+  }
+
+  /deep/ filter-dropdown {
+    button,
+    button:focus {
+      padding: 0;
+      .label-before-selection {
+        font-weight: bold;
+      }
+    }
+  }
 }
diff --git a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.ts b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.ts
index b41b941..d3d319c 100644
--- a/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.ts
+++ b/ambari-logsearch-web/src/app/modules/shipper/components/shipper-service-configuration-form/shipper-service-configuration-form.component.ts
@@ -16,23 +16,34 @@
  * limitations under the License.
  */
 
-import {ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges} from '@angular/core';
-import {AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators} from '@angular/forms';
-import {Observable} from 'rxjs/Observable';
-import {Subject} from 'rxjs/Subject';
-import {Observer} from 'rxjs/Observer';
+import {
+  ChangeDetectorRef,
+  Component,
+  EventEmitter,
+  Input,
+  OnChanges,
+  OnDestroy,
+  OnInit,
+  Output,
+  SimpleChanges
+} from '@angular/core';
+import { AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms';
+import { Observable } from 'rxjs/Observable';
+import { Subject } from 'rxjs/Subject';
+import { Observer } from 'rxjs/Observer';
 import 'rxjs/add/operator/startWith';
 
-import {CanComponentDeactivate} from '@modules/shared/services/can-deactivate-guard.service';
+import { CanComponentDeactivate } from '@modules/shared/services/can-deactivate-guard.service';
 
-import {ShipperCluster} from '../../models/shipper-cluster.type';
-import {ShipperClusterService} from '../../models/shipper-cluster-service.type';
-import {ShipperClusterServiceConfigurationInterface} from '../../models/shipper-cluster-service-configuration.interface';
-import {ShipperConfigurationModel} from '../../models/shipper-configuration.model';
+import { ShipperCluster } from '../../models/shipper-cluster.type';
+import { ShipperClusterService } from '../../models/shipper-cluster-service.type';
+import { ShipperClusterServiceConfigurationInterface } from '../../models/shipper-cluster-service-configuration.interface';
+import { ShipperConfigurationModel } from '../../models/shipper-configuration.model';
 import * as formValidators from '../../directives/validator.directive';
-import {BehaviorSubject} from 'rxjs/BehaviorSubject';
-import {Subscription} from 'rxjs/Subscription';
-import {ActivatedRoute} from '@angular/router';
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+import { Subscription } from 'rxjs/Subscription';
+import { ActivatedRoute } from '@angular/router';
+import { ListItem } from '@app/classes/list-item';
 
 @Component({
   selector: 'shipper-configuration-form',
@@ -40,7 +51,6 @@
   styleUrls: ['./shipper-service-configuration-form.component.less']
 })
 export class ShipperServiceConfigurationFormComponent implements OnInit, OnDestroy, OnChanges, CanComponentDeactivate {
-
   private configurationForm: FormGroup;
   private validatorForm: FormGroup;
 
@@ -57,7 +67,7 @@
   existingServiceNames: Observable<ShipperClusterService[]> | ShipperClusterService[];
 
   @Input()
-  validationResponse: {[key: string]: any};
+  validationResponse: { [key: string]: any };
 
   @Input()
   disabled = false;
@@ -69,6 +79,7 @@
   validationSubmit: EventEmitter<FormGroup> = new EventEmitter<FormGroup>();
 
   private configurationComponents$: Observable<string[]>;
+  private configurationComponentsList$: Observable<ListItem[]>;
 
   private isLeavingDirtyForm = false;
 
@@ -94,18 +105,20 @@
 
   private canDeactivateModalResult: Subject<boolean> = new Subject<boolean>();
 
-  private canDeactivateObservable$: Observable<boolean> = Observable.create((observer: Observer<boolean>)  => {
-    this.subscriptions.push(
-      this.canDeactivateModalResult.subscribe((result: boolean) => {
-        observer.next(result);
-      })
-    );
+  private canDeactivateObservable$: Observable<boolean> = Observable.create((observer: Observer<boolean>) => {
+    this.canDeactivateModalResult.takeUntil(this.destroyed$).subscribe((result: boolean) => {
+      observer.next(result);
+    });
   });
 
-  private serviceNamesListSubject: BehaviorSubject<ShipperClusterService[]> = new BehaviorSubject<ShipperClusterService[]>([]);
+  private serviceNamesListSubject: BehaviorSubject<ShipperClusterService[]> = new BehaviorSubject<
+    ShipperClusterService[]
+  >([]);
 
   private subscriptions: Subscription[] = [];
 
+  private destroyed$ = new Subject();
+
   constructor(
     private formBuilder: FormBuilder,
     private activatedRoute: ActivatedRoute,
@@ -118,33 +131,52 @@
 
   ngOnInit() {
     this.subscriptions.push(
-      this.activatedRoute.params.map(params => params.service).subscribe((service) => {
-        this.serviceName = service;
-      })
+      this.activatedRoute.params
+        .map(params => params.service)
+        .subscribe(service => {
+          this.serviceName = service;
+        })
     );
     if (!this.serviceName) {
       this.configurationForm.controls.serviceName.setValidators([
         Validators.required,
         formValidators.uniqueServiceNameValidator(this.serviceNamesListSubject)
       ]);
-      this.changeDetectionRef.detectChanges();
     }
-    this.configurationComponents$ = this.configurationForm.controls.configuration.valueChanges.map((newValue: string): string[] => {
-      let components: string[];
-      try {
-        const inputs: {[key: string]: any}[] = (newValue ? JSON.parse(newValue) : {}).input;
-        components = inputs && inputs.length ? inputs.map(input => input.type) : [];
-      } catch (error) {
-        components = [];
-      }
-      return components;
-    }).startWith([]);
+    this.configurationComponents$ = this.configurationForm.controls.configuration.valueChanges
+      .map(
+        (newValue: string): string[] => {
+          let components: string[];
+          try {
+            const inputs: { [key: string]: any }[] = (newValue ? JSON.parse(newValue) : {}).input;
+            components = inputs && inputs.length ? inputs.map(input => input.type) : [];
+          } catch (error) {
+            components = [];
+          }
+          return components || [];
+        }
+      )
+      .startWith([]);
+    this.configurationComponentsList$ = this.configurationComponents$
+      .map(
+        (components: string[]): ListItem[] =>
+          components
+            .filter((component: string) => component)
+            .map(
+              (component: string, index: number): ListItem => {
+                return {
+                  value: component,
+                  label: component,
+                  isChecked: index === 0
+                };
+              }
+            )
+      )
+      .startWith([]);
     if (this.existingServiceNames instanceof Observable) {
-      this.subscriptions.push(
-        this.existingServiceNames.subscribe((serviceNames: ShipperClusterService[]) => {
-          this.serviceNamesListSubject.next(serviceNames);
-        })
-      );
+      this.existingServiceNames.takeUntil(this.destroyed$).subscribe((serviceNames: ShipperClusterService[]) => {
+        this.serviceNamesListSubject.next(serviceNames);
+      });
     } else {
       this.serviceNamesListSubject.next(this.existingServiceNames);
     }
@@ -168,7 +200,11 @@
         }
       });
     }
-    if (this.validatorForm && changes.clusterName && this.validatorForm.controls.clusterName.value !== changes.clusterName.currentValue) {
+    if (
+      this.validatorForm &&
+      changes.clusterName &&
+      this.validatorForm.controls.clusterName.value !== changes.clusterName.currentValue
+    ) {
       this.validatorForm.controls.clusterName.setValue(changes.clusterName.currentValue);
       this.validatorForm.markAsPristine();
     }
@@ -178,17 +214,18 @@
     if (this.subscriptions) {
       this.subscriptions.forEach(subscription => subscription.unsubscribe());
     }
+    this.destroyed$.next(true);
   }
 
   leaveDirtyFormConfirmed = () => {
     this.canDeactivateModalResult.next(true);
     this.isLeavingDirtyForm = false;
-  }
+  };
 
   leaveDirtyFormCancelled = () => {
     this.canDeactivateModalResult.next(false);
     this.isLeavingDirtyForm = false;
-  }
+  };
 
   canDeactivate(): Observable<boolean> {
     if (this.configurationForm.pristine) {
@@ -203,39 +240,33 @@
   }
 
   createForms(): void {
-    const configuration: ShipperClusterServiceConfigurationInterface = this.configuration || (
-      this.serviceName ? this.configuration : new ShipperConfigurationModel()
-    );
+    const configuration: ShipperClusterServiceConfigurationInterface =
+      this.configuration || (this.serviceName ? this.configuration : new ShipperConfigurationModel());
     this.configurationForm = this.formBuilder.group({
       clusterName: this.formBuilder.control(this.clusterName, Validators.required),
-      serviceName: this.formBuilder.control(
-        this.serviceName,
-        [Validators.required]
-      ),
-      configuration: this.formBuilder.control(
-        this.getConfigurationAsString(configuration),
-        [Validators.required, formValidators.configurationValidator()]
-      )
+      serviceName: this.formBuilder.control(this.serviceName, [Validators.required]),
+      configuration: this.formBuilder.control(this.getConfigurationAsString(configuration), [
+        Validators.required,
+        formValidators.configurationValidator()
+      ])
     });
 
     this.validatorForm = this.formBuilder.group({
-      clusterName: this.formBuilder.control(
-        this.clusterName,
-        [Validators.required]
-      ),
+      clusterName: this.formBuilder.control(this.clusterName, [Validators.required]),
       componentName: this.formBuilder.control('', [
         Validators.required,
-        formValidators.getConfigurationServiceValidator(this.configurationForm.controls.configuration)
+        formValidators.getConfigurationServiceValidator(
+          this.configurationForm.controls.configuration,
+          listItem => listItem && listItem.length && listItem[0].value
+        )
       ]),
       sampleData: this.formBuilder.control('', Validators.required),
       configuration: this.formBuilder.control('', Validators.required)
     });
-    this.subscriptions.push(
-      this.configurationForm.valueChanges.subscribe(() => {
-        this.validatorForm.controls.componentName.updateValueAndValidity();
-        this.validatorForm.controls.configuration.setValue(this.configurationForm.controls.configuration.value);
-      })
-    );
+    this.configurationForm.valueChanges.takeUntil(this.destroyed$).subscribe(() => {
+      this.validatorForm.controls.componentName.updateValueAndValidity();
+      this.validatorForm.controls.configuration.setValue(this.configurationForm.controls.configuration.value);
+    });
   }
 
   onConfigurationSubmit(): void {
@@ -249,5 +280,4 @@
       this.validationSubmit.emit(this.validatorForm);
     }
   }
-
 }
diff --git a/ambari-logsearch-web/src/app/modules/shipper/directives/validator.directive.ts b/ambari-logsearch-web/src/app/modules/shipper/directives/validator.directive.ts
index 50c1237..a590125 100644
--- a/ambari-logsearch-web/src/app/modules/shipper/directives/validator.directive.ts
+++ b/ambari-logsearch-web/src/app/modules/shipper/directives/validator.directive.ts
@@ -16,46 +16,49 @@
  * limitations under the License.
  */
 
-import {AbstractControl, ValidatorFn} from '@angular/forms';
-import {ShipperClusterService} from '@modules/shipper/models/shipper-cluster-service.type';
-import {ValidationErrors} from '@angular/forms/src/directives/validators';
-import {BehaviorSubject} from 'rxjs/BehaviorSubject';
+import { AbstractControl, ValidatorFn } from '@angular/forms';
+import { ShipperClusterService } from '@modules/shipper/models/shipper-cluster-service.type';
+import { ValidationErrors } from '@angular/forms/src/directives/validators';
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
 
 export function configurationValidator(): ValidatorFn {
   return (control: AbstractControl): ValidationErrors | null => {
     try {
-      const json: {[key: string]: any} = JSON.parse(control.value);
+      const json: { [key: string]: any } = JSON.parse(control.value);
       return null;
     } catch (error) {
       return {
-        invalidJSON: {value: control.value}
+        invalidJSON: { value: control.value }
       };
     }
   };
 }
 
-export function uniqueServiceNameValidator(
-  serviceNames: BehaviorSubject<ShipperClusterService[]>
-): ValidatorFn {
+export function uniqueServiceNameValidator(serviceNames: BehaviorSubject<ShipperClusterService[]>): ValidatorFn {
   return (control: AbstractControl): ValidationErrors | null => {
     const services: ShipperClusterService[] = serviceNames.getValue();
-    return services && services.indexOf(control.value) > -1 ? {
-      serviceNameExists: {value: control.value}
-    } : null;
+    return services && services.indexOf(control.value) > -1
+      ? {
+          serviceNameExists: { value: control.value }
+        }
+      : null;
   };
 }
 
-export function getConfigurationServiceValidator(configControl: AbstractControl): ValidatorFn {
+export function getConfigurationServiceValidator(configControl: AbstractControl, valueMapper?: Function): ValidatorFn {
   return (control: AbstractControl): ValidationErrors | null => {
     let components: string[];
     try {
-      const inputs: {[key: string]: any}[] = (configControl.value ? JSON.parse(configControl.value) : {}).input;
+      const inputs: { [key: string]: any }[] = (configControl.value ? JSON.parse(configControl.value) : {}).input;
       components = inputs && inputs.length ? inputs.map(input => input.type) : [];
     } catch (error) {
       components = [];
     }
-    return components.length && components.indexOf(control.value) === -1 ? {
-      serviceNameDoesNotExistInConfiguration: {value: control.value}
-    } : null;
+    const value = valueMapper ? valueMapper(control.value) : control.value;
+    return components.length && components.indexOf(value) === -1
+      ? {
+          serviceNameDoesNotExistInConfiguration: { value: value }
+        }
+      : null;
   };
 }