diff --git a/client/src/app/instance/instance.reducer.ts b/client/src/app/instance/instance.reducer.ts
index 0c1981cf76c6306499f8c3167c22227f8dedc97f..f4454161d4f8074368ddc3d583a050798ea7abf4 100644
--- a/client/src/app/instance/instance.reducer.ts
+++ b/client/src/app/instance/instance.reducer.ts
@@ -13,17 +13,20 @@ import { RouterReducerState } from 'src/app/custom-route-serializer';
 import * as metamodel from './store/reducers/metamodel.reducer';
 import * as search from './store/reducers/search.reducer';
 import * as samp from './store/reducers/samp.reducer';
+import * as coneSearch from './store/reducers/cone-search.reducer';
 
 export interface State {
     metamodel: metamodel.State,
     search: search.State,
-    samp: samp.State
+    samp: samp.State,
+    coneSearch: coneSearch.State
 }
 
 const reducers = {
     metamodel: metamodel.metamodelReducer,
     search: search.searchReducer,
-    samp: samp.sampReducer
+    samp: samp.sampReducer,
+    coneSearch: coneSearch.coneSearchReducer
 };
 
 export const instanceReducer = combineReducers(reducers);
diff --git a/client/src/app/instance/search/components/criteria/cone-search-tab.component.html b/client/src/app/instance/search/components/criteria/cone-search-tab.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..ea951c32bd3106f1c745ad5e18876c73d592bad5
--- /dev/null
+++ b/client/src/app/instance/search/components/criteria/cone-search-tab.component.html
@@ -0,0 +1,37 @@
+<accordion *ngIf="(datasetList | datasetByName:datasetSelected).config.cone_search.cone_search_enabled" [isAnimated]="true">
+    <accordion-group #ag [panelClass]="'custom-accordion'" [isOpen]="(datasetList | datasetByName:datasetSelected).config.cone_search.cone_search_opened" class="my-2">
+        <button class="btn btn-link btn-block clearfix" accordion-heading>
+            <span class="pull-left float-left">
+                Cone search
+                &nbsp;
+                <span *ngIf="ag.isOpen">
+                    <span class="fas fa-chevron-up"></span>
+                </span>
+                <span *ngIf="!ag.isOpen">
+                    <span class="fas fa-chevron-down"></span>
+                </span>
+            </span>
+        </button>
+        <div class="row">
+            <div class="col">
+                <app-cone-search
+                    [coneSearch]="coneSearch"
+                    [resolver]="resolver"
+                    [resolverIsLoading]="resolverIsLoading"
+                    [resolverIsLoaded]="resolverIsLoaded"
+                    (addConeSearch)="addConeSearch.emit($event)"
+                    (deleteConeSearch)="deleteConeSearch.emit()"
+                    (retrieveCoordinates)="retrieveCoordinates.emit($event)" #cs>
+                </app-cone-search>
+            </div>
+            <div class="col-2 text-center align-self-end">
+                <button class="btn btn-outline-success" *ngIf="!coneSearch" [hidden]="cs.form.invalid" (click)="addConeSearch.emit(cs.getConeSearch())">
+                    <span class="fas fa-plus fa-fw"></span>
+                </button>
+                <button class="btn btn-outline-danger" *ngIf="coneSearch" (click)="deleteConeSearch.emit()">
+                    <span class="fa fa-times fa-fw"></span>
+                </button>
+            </div>
+        </div>
+    </accordion-group>
+</accordion>
diff --git a/client/src/app/instance/search/components/criteria/cone-search-tab.component.ts b/client/src/app/instance/search/components/criteria/cone-search-tab.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..85a3f259e3df262a93c190d37c7733d31b1743dc
--- /dev/null
+++ b/client/src/app/instance/search/components/criteria/cone-search-tab.component.ts
@@ -0,0 +1,34 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
+
+import { Dataset } from 'src/app/metamodel/models';
+import { ConeSearch, Resolver } from 'src/app/instance/store/models';
+
+@Component({
+    selector: 'app-cone-search-tab',
+    templateUrl: 'cone-search-tab.component.html',
+    changeDetection: ChangeDetectionStrategy.OnPush
+})
+/**
+ * @class
+ * @classdesc Search cone search tab component.
+ */
+export class ConeSearchTabComponent {
+    @Input() datasetSelected: string;
+    @Input() datasetList: Dataset[];
+    @Input() coneSearch: ConeSearch;
+    @Input() resolver: Resolver;
+    @Input() resolverIsLoading: boolean;
+    @Input() resolverIsLoaded: boolean;
+    @Output() addConeSearch: EventEmitter<ConeSearch> = new EventEmitter();
+    @Output() deleteConeSearch: EventEmitter<{ }> = new EventEmitter();
+    @Output() retrieveCoordinates: EventEmitter<string> = new EventEmitter();
+}
diff --git a/client/src/app/instance/search/components/criteria/index.ts b/client/src/app/instance/search/components/criteria/index.ts
index bdee82025471c6892a6af287afb3c151e019d2fd..88656ad3c2668f4eb770c6db2672fb8302115a68 100644
--- a/client/src/app/instance/search/components/criteria/index.ts
+++ b/client/src/app/instance/search/components/criteria/index.ts
@@ -1,8 +1,10 @@
+import { ConeSearchTabComponent } from './cone-search-tab.component';
 import { CriteriaTabsComponent } from './criteria-tabs.component';
 import { CriteriaByFamilyComponent } from './criteria-by-family.component';
 import { searchTypeComponents } from './search-type';
 
 export const criteriaComponents = [
+    ConeSearchTabComponent,
     CriteriaTabsComponent,
     CriteriaByFamilyComponent,
     searchTypeComponents
diff --git a/client/src/app/instance/search/components/result/datatable-tab.component.html b/client/src/app/instance/search/components/result/datatable-tab.component.html
index 670acae1dd47d1c6dc836cbd4f78e0cec4592d37..66316d7af426d1a63ecfb6c0e2078d6b9d6d5605 100644
--- a/client/src/app/instance/search/components/result/datatable-tab.component.html
+++ b/client/src/app/instance/search/components/result/datatable-tab.component.html
@@ -1,5 +1,5 @@
-<accordion *ngIf="getDataset().config.datatable.datatable_enabled" [isAnimated]="true">
-    <accordion-group #ag [isOpen]="getDataset().config.datatable.datatable_opened" [panelClass]="'custom-accordion'" class="my-2">
+<accordion *ngIf="(datasetList | datasetByName:datasetSelected).config.datatable.datatable_enabled" [isAnimated]="true">
+    <accordion-group #ag [isOpen]="(datasetList | datasetByName:datasetSelected).config.datatable.datatable_opened" [panelClass]="'custom-accordion'" class="my-2">
         <button class="btn btn-link btn-block clearfix" accordion-heading>
             <span class="pull-left float-left">
                 Display result details
@@ -9,7 +9,7 @@
             </span>
         </button>
         <app-datatable
-                [dataset]="getDataset()"
+                [dataset]="datasetList | datasetByName:datasetSelected"
                 [attributeList]="attributeList"
                 [outputList]="outputList"
                 [dataLength]="dataLength"
diff --git a/client/src/app/instance/search/components/result/datatable-tab.component.ts b/client/src/app/instance/search/components/result/datatable-tab.component.ts
index 0b7b2258095c4ff700fc940781e0ed6a4dd5d6af..c2d7dd1dd0ce224bd65ad333c910a84809bc0c1d 100644
--- a/client/src/app/instance/search/components/result/datatable-tab.component.ts
+++ b/client/src/app/instance/search/components/result/datatable-tab.component.ts
@@ -34,13 +34,4 @@ export class DatatableTabComponent {
     @Output() retrieveData: EventEmitter<Pagination> = new EventEmitter();
     @Output() addSelectedData: EventEmitter<number | string> = new EventEmitter();
     @Output() deleteSelectedData: EventEmitter<number | string> = new EventEmitter();
-
-    /**
-     * Returns selected dataset for the search.
-     *
-     * @return Dataset
-     */
-    getDataset(): Dataset {
-        return this.datasetList.find(dataset => dataset.name === this.datasetSelected);
-    }
 }
diff --git a/client/src/app/instance/search/components/result/reminder.component.html b/client/src/app/instance/search/components/result/reminder.component.html
index d76e57d79282e0ffe5efefd8ab799a41ee6036e9..38372acef640c24c36328c786925527dd5ecfd8f 100644
--- a/client/src/app/instance/search/components/result/reminder.component.html
+++ b/client/src/app/instance/search/components/result/reminder.component.html
@@ -24,14 +24,14 @@
                         </div>
 
                         <div *ngIf="nbCriteria() > 0" class="row">
-                            <!-- <div *ngIf="isConeSearchAdded" class="col-12 col-md-6 col-xl-4 pb-3">
+                            <div *ngIf="coneSearch" class="col-12 col-md-6 col-xl-4 pb-3">
                                 <span class="title">Cone search</span>
                                 <ul class="list-unstyled pl-3">
                                     <li>RA = {{ coneSearch.ra }}°</li>
                                     <li>DEC = {{ coneSearch.dec }}°</li>
                                     <li>radius = {{ coneSearch.radius }} arcsecond</li>
                                 </ul>
-                            </div> -->
+                            </div>
 
                             <ng-container *ngFor="let family of criteriaFamilyList">
                                 <ng-container *ngIf="criteriaByFamily(family.id).length > 0">
diff --git a/client/src/app/instance/search/components/result/reminder.component.ts b/client/src/app/instance/search/components/result/reminder.component.ts
index 9961ece07a9ed7101ff1de5aa915187a94884628..8e3d88ea4ffc5584ba30b77ba2168c0a1e993cd0 100644
--- a/client/src/app/instance/search/components/result/reminder.component.ts
+++ b/client/src/app/instance/search/components/result/reminder.component.ts
@@ -28,9 +28,8 @@ export class ReminderComponent {
     @Input() criteriaFamilyList: CriteriaFamily[];
     @Input() outputFamilyList: OutputFamily[];
     @Input() outputCategoryList: OutputCategory[];
-    // @Input() isConeSearchAdded: boolean;
-    // @Input() coneSearch: ConeSearch;
     @Input() criteriaList: Criterion[];
+    @Input() coneSearch: ConeSearch;
     @Input() outputList: number[];
 
     isSummaryActivated(): boolean {
@@ -49,9 +48,9 @@ export class ReminderComponent {
      * @return number
      */
     nbCriteria(): number {
-        // if (this.isConeSearchAdded) {
-        //     return this.criteriaList.length + 1;
-        // }
+        if (this.coneSearch) {
+            return this.criteriaList.length + 1;
+        }
         return this.criteriaList.length;
     }
 
diff --git a/client/src/app/instance/search/components/summary.component.html b/client/src/app/instance/search/components/summary.component.html
index 0fc5455ed4c10d7ee751b4823bb686211b37d056..86c376fb03367425c7f6a4776396d78ee31c6422 100644
--- a/client/src/app/instance/search/components/summary.component.html
+++ b/client/src/app/instance/search/components/summary.component.html
@@ -15,14 +15,14 @@
     <p *ngIf="noCriteria()" class="pl-5 font-weight-bold">
         No selected criteria
     </p>
-    <!-- <span *ngIf="isConeSearchAdded" class="pl-5">
+    <span *ngIf="coneSearch" class="pl-5">
         Cone search:
         <ul class="ml-3 pl-5 list-unstyled">
             <li>RA = {{ coneSearch.ra }}°</li>
             <li>DEC = {{ coneSearch.dec }}°</li>
             <li>radius = {{ coneSearch.radius }} arcsecond</li>
         </ul>
-    </span> -->
+    </span>
     <ul *ngIf="criteriaList.length > 0" class="pl-5 list-unstyled">
         <li *ngFor="let criterion of criteriaList">
             {{ getAttribute(criterion.id).form_label }} {{ printCriterion(criterion) }}
diff --git a/client/src/app/instance/search/components/summary.component.ts b/client/src/app/instance/search/components/summary.component.ts
index dfa03f44f4c86f23bb6fb8ab10ad3e5a8600b462..3e76c6275872536dca5f00257e2969ea611ad3b3 100644
--- a/client/src/app/instance/search/components/summary.component.ts
+++ b/client/src/app/instance/search/components/summary.component.ts
@@ -9,9 +9,8 @@
 
 import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';
 
-import { Criterion, SearchQueryParams, getPrettyCriterion } from '../../store/models';
+import { Criterion, ConeSearch, SearchQueryParams, getPrettyCriterion } from '../../store/models';
 import { Attribute, Dataset, CriteriaFamily, OutputFamily, OutputCategory } from 'src/app/metamodel/models';
-// import { ConeSearch } from '../../shared/cone-search/store/model';
 
 @Component({
     selector: 'app-summary',
@@ -27,8 +26,6 @@ export class SummaryComponent {
     @Input() currentStep: string;
     @Input() datasetSelected: string;
     @Input() datasetList: Dataset[];
-    // @Input() isConeSearchAdded: boolean;
-    // @Input() coneSearch: ConeSearch;
     @Input() attributeList: Attribute[];
     @Input() criteriaFamilyList: CriteriaFamily[];
     @Input() outputFamilyList: OutputFamily[];
@@ -36,6 +33,7 @@ export class SummaryComponent {
     @Input() criteriaList: Criterion[];
     @Input() outputList: number[];
     @Input() queryParams: SearchQueryParams;
+    @Input() coneSearch: ConeSearch;
 
     accordionFamilyIsOpen = true;
 
@@ -54,8 +52,7 @@ export class SummaryComponent {
      * @return boolean
      */
     noCriteria(): boolean {
-        //if (this.isConeSearchAdded || this.criteriaList.length > 0) {
-        if (this.criteriaList.length > 0) {
+        if (this.coneSearch || this.criteriaList.length > 0) {
             return false
         }
         return true;
diff --git a/client/src/app/instance/search/containers/abstract-search.component.ts b/client/src/app/instance/search/containers/abstract-search.component.ts
index a6ebdbbebc3bb3175648b19ddadfb4adc037c880..6774ae781e2266fbb6a6eb2503c477954393eef0 100644
--- a/client/src/app/instance/search/containers/abstract-search.component.ts
+++ b/client/src/app/instance/search/containers/abstract-search.component.ts
@@ -3,7 +3,7 @@ import { Directive, OnInit, OnDestroy } from '@angular/core';
 import { Store } from '@ngrx/store';
 import { Observable, Subscription } from 'rxjs';
 
-import { Criterion, SearchQueryParams } from '../../store/models';
+import { ConeSearch, Criterion, SearchQueryParams } from '../../store/models';
 import { Dataset, Attribute, CriteriaFamily, OutputFamily, OutputCategory } from 'src/app/metamodel/models';
 
 import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector';
@@ -14,6 +14,7 @@ import * as outputFamilySelector from 'src/app/metamodel/selectors/output-family
 import * as outputCategorySelector from 'src/app/metamodel/selectors/output-category.selector';
 import * as searchActions from '../../store/actions/search.actions';
 import * as searchSelector from '../../store/selectors/search.selector';
+import * as coneSearchSelector from '../../store/selectors/cone-search.selector';
 
 @Directive()
 export abstract class AbstractSearchComponent implements OnInit, OnDestroy {
@@ -39,6 +40,7 @@ export abstract class AbstractSearchComponent implements OnInit, OnDestroy {
     public criteriaList: Observable<Criterion[]>;
     public outputList: Observable<number[]>;
     public queryParams: Observable<SearchQueryParams>;
+    public coneSearch: Observable<ConeSearch>;
 
     private attributeListIsLoadedSubscription: Subscription;
 
@@ -65,6 +67,7 @@ export abstract class AbstractSearchComponent implements OnInit, OnDestroy {
         this.criteriaList = this.store.select(searchSelector.selectCriteriaList);
         this.outputList = this.store.select(searchSelector.selectOutputList);
         this.queryParams = this.store.select(searchSelector.selectQueryParams);
+        this.coneSearch = this.store.select(coneSearchSelector.selectConeSearch);
     }
 
     ngOnInit() {
diff --git a/client/src/app/instance/search/containers/criteria.component.html b/client/src/app/instance/search/containers/criteria.component.html
index 5fb87883773d70c4baf88ec337f5320fec6bd919..8ff2d1d903ea462d493393f6efa68700811f4265 100644
--- a/client/src/app/instance/search/containers/criteria.component.html
+++ b/client/src/app/instance/search/containers/criteria.component.html
@@ -7,13 +7,17 @@
     && (criteriaFamilyListIsLoaded | async)
     && (attributeListIsLoaded | async)" class="row mt-4">
     <div class="col-12 col-md-8 col-lg-9">
-        <!-- <app-cone-search-tab
+        <app-cone-search-tab
             [datasetSelected]="datasetSelected | async"
             [datasetList]="datasetList | async"
-            [isConeSearchAdded]="isConeSearchAdded | async"
-            [isValidConeSearch]="isValidConeSearch | async"
-            (coneSearchAdded)="coneSearchAdded($event)">
-        </app-cone-search-tab> -->
+            [coneSearch]="coneSearch | async"
+            [resolver]="resolver | async"
+            [resolverIsLoading]="resolverIsLoading | async"
+            [resolverIsLoaded]="resolverIsLoaded | async"
+            (addConeSearch)="addConeSearch($event)"
+            (deleteConeSearch)="deleteConeSearch()"
+            (retrieveCoordinates)="retrieveCoordinates($event)">
+        </app-cone-search-tab>
         <app-criteria-tabs 
             [attributeList]="attributeList | async"
             [criteriaFamilyList]="criteriaFamilyList | async"
@@ -34,7 +38,8 @@
             [outputCategoryList]="outputCategoryList | async"
             [criteriaList]="criteriaList | async"
             [outputList]="outputList | async"
-            [queryParams]="queryParams | async">
+            [queryParams]="queryParams | async"
+            [coneSearch]="coneSearch | async">
         </app-summary>
     </div>
 </div>
@@ -47,7 +52,7 @@
         </a>
     </div>
     <div class="col col-auto">
-        <a routerLink="/search/output/{{ datasetSelected | async }}" [queryParams]="queryParams | async"
+        <a routerLink="/instance/{{ instanceSelected | async }}/search/output/{{ datasetSelected | async }}" [queryParams]="queryParams | async"
             class="btn btn-outline-primary">
             Output <span class="fas fa-arrow-right"></span>
         </a>
diff --git a/client/src/app/instance/search/containers/criteria.component.ts b/client/src/app/instance/search/containers/criteria.component.ts
index a226c24ed0131bc8d5bfba3dc12a8f590121fd29..b03d239dc5f4ac0bc2e9a84b79b23d81a2ce6cd8 100644
--- a/client/src/app/instance/search/containers/criteria.component.ts
+++ b/client/src/app/instance/search/containers/criteria.component.ts
@@ -9,9 +9,14 @@
 
 import { Component } from '@angular/core';
 
+import { Store } from '@ngrx/store';
+import { Observable } from 'rxjs';
+
 import { AbstractSearchComponent } from './abstract-search.component';
-import { Criterion } from '../../store/models';
+import { ConeSearch, Criterion, Resolver } from '../../store/models';
 import * as searchActions from '../../store/actions/search.actions';
+import * as coneSearchActions from '../../store/actions/cone-search.actions';
+import * as coneSearchSelector from '../../store/selectors/cone-search.selector';
 
 @Component({
     selector: 'app-criteria',
@@ -22,6 +27,17 @@ import * as searchActions from '../../store/actions/search.actions';
  * @classdesc Search criteria container.
  */
 export class CriteriaComponent extends AbstractSearchComponent {
+    public resolver: Observable<Resolver>;
+    public resolverIsLoading: Observable<boolean>;
+    public resolverIsLoaded: Observable<boolean>;
+
+    constructor(protected store: Store<{ }>) {
+        super(store);
+        this.resolver = this.store.select(coneSearchSelector.selectResolver);
+        this.resolverIsLoading = this.store.select(coneSearchSelector.selectResolverIsLoading);
+        this.resolverIsLoaded = this.store.select(coneSearchSelector.selectResolverIsLoaded);
+    }
+
     ngOnInit() {
         Promise.resolve(null).then(() => this.store.dispatch(searchActions.changeStep({ step: 'criteria' })));
         Promise.resolve(null).then(() => this.store.dispatch(searchActions.checkCriteria()));
@@ -45,4 +61,16 @@ export class CriteriaComponent extends AbstractSearchComponent {
     deleteCriterion(idCriterion: number): void {
         this.store.dispatch(searchActions.deleteCriterion({ idCriterion }));
     }
+
+    addConeSearch(coneSearch: ConeSearch): void {
+        this.store.dispatch(coneSearchActions.addConeSearch({ coneSearch }));
+    }
+
+    deleteConeSearch(): void {
+        this.store.dispatch(coneSearchActions.deleteConeSearch());
+    }
+
+    retrieveCoordinates(name: string): void {
+        this.store.dispatch(coneSearchActions.retrieveCoordinates({ name }));
+    }
 }
diff --git a/client/src/app/instance/search/containers/dataset.component.html b/client/src/app/instance/search/containers/dataset.component.html
index b86d581556b64900a383598f8beae670d3dff20f..77107988152d7cafa0de1aee2c1d0172768d3afd 100644
--- a/client/src/app/instance/search/containers/dataset.component.html
+++ b/client/src/app/instance/search/containers/dataset.component.html
@@ -36,7 +36,8 @@
                 [outputCategoryList]="outputCategoryList | async"
                 [criteriaList]="criteriaList | async"
                 [outputList]="outputList | async"
-                [queryParams]="queryParams | async">
+                [queryParams]="queryParams | async"
+                [coneSearch]="coneSearch | async">
             </app-summary>
         </div>
     </ng-container>
diff --git a/client/src/app/instance/search/containers/output.component.html b/client/src/app/instance/search/containers/output.component.html
index 9b0cdec4da374ed048fea9eea3630a1628a1e605..12d7f60558376fa5c8b4a679cc8fa1a2b4eafce0 100644
--- a/client/src/app/instance/search/containers/output.component.html
+++ b/client/src/app/instance/search/containers/output.component.html
@@ -27,7 +27,8 @@
             [outputCategoryList]="outputCategoryList | async"
             [criteriaList]="criteriaList | async"
             [outputList]="outputList | async"
-            [queryParams]="queryParams | async">
+            [queryParams]="queryParams | async"
+            [coneSearch]="coneSearch | async">
         </app-summary>
     </div>
 </div>
diff --git a/client/src/app/instance/search/containers/result.component.html b/client/src/app/instance/search/containers/result.component.html
index 9eacc2ffbff8b44a625d444390f47af89e481e08..ab045ae224c68d9ae47765843967539f45be1aa7 100644
--- a/client/src/app/instance/search/containers/result.component.html
+++ b/client/src/app/instance/search/containers/result.component.html
@@ -36,6 +36,7 @@
                 [outputFamilyList]="outputFamilyList | async"
                 [outputCategoryList]="outputCategoryList | async"
                 [criteriaList]="criteriaList | async"
+                [coneSearch]="coneSearch | async"
                 [outputList]="outputList | async">
             </app-reminder>
             <app-samp
diff --git a/client/src/app/instance/shared-search/components/cone-search/cone-search.component.html b/client/src/app/instance/shared-search/components/cone-search/cone-search.component.html
index c0cf4330cf393e0886bfdffecd414e6a7720b607..6e676e971e10e1ebf73318e490770eb147abdae1 100644
--- a/client/src/app/instance/shared-search/components/cone-search/cone-search.component.html
+++ b/client/src/app/instance/shared-search/components/cone-search/cone-search.component.html
@@ -1,47 +1,29 @@
 <div class="row pb-4">
     <div class="col">
         <app-resolver
-            [resolverWip]="resolverWip | async"
-            [resolver]="resolver | async"
-            [disabled]="disabled"
-            (resolveName)="retrieveCoordinates($event)">
+            [coneSearch]="coneSearch"
+            [resolver]="resolver"
+            [resolverIsLoading]="resolverIsLoading"
+            [resolverIsLoaded]="resolverIsLoaded"
+            (retrieveCoordinates)="retrieveCoordinates.emit($event)">
         </app-resolver>
     </div>
 </div>
 <div class="row">
     <div class="col pb-4">
-        <app-ra
-            [coneSearch]="coneSearch | async"
-            [resolver]="resolver | async"
-            [unit]="unit"
-            [disabled]="disabled"
-            (updateConeSearch)="updateConeSearch($event)"
-            (deleteResolver)="deleteResolver()">
+        <app-ra [form]="form" [unit]="unit" [resolver]="resolver">
         </app-ra>
     </div>
     <div class="col-auto p-0 align-self-center">
-        <button class="btn btn-outline-secondary"
-            [disabled]="disabled"
-            (click)="unit === 'degree' ? unit = 'hms' : unit = 'degree'"
-            title="Change unit">
-        <span class="fas fa-sync-alt"></span>
+        <button class="btn btn-outline-secondary" [disabled]="coneSearch" (click)="unit === 'degree' ? unit = 'hms' : unit = 'degree'" title="Change unit">
+            <span class="fas fa-sync-alt"></span>
         </button>
     </div>
     <div class="col">
-        <app-dec
-            [coneSearch]="coneSearch | async"
-            [resolver]="resolver | async"
-            [unit]="unit"
-            [disabled]="disabled"
-            (updateConeSearch)="updateConeSearch($event)"
-            (deleteResolver)="deleteResolver()">
+        <app-dec [form]="form" [unit]="unit" [resolver]="resolver">
         </app-dec>
     </div>
     <div class="col-12">
-        <app-radius
-            [coneSearch]="coneSearch | async"
-            [disabled]="disabled"
-            (updateConeSearch)="updateConeSearch($event)">
-        </app-radius>
+        <app-radius [form]="form"></app-radius>
     </div>
 </div>
diff --git a/client/src/app/instance/shared-search/components/cone-search/cone-search.component.ts b/client/src/app/instance/shared-search/components/cone-search/cone-search.component.ts
index d506c3180a782ca2f64141bb863c8e39b23ca25e..ca589c83866668ad1f6fd8953bb7567d637889df 100644
--- a/client/src/app/instance/shared-search/components/cone-search/cone-search.component.ts
+++ b/client/src/app/instance/shared-search/components/cone-search/cone-search.component.ts
@@ -7,9 +7,11 @@
  * file that was distributed with this source code.
  */
 
-import { Component, Input, Output, EventEmitter } from '@angular/core';
+import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';
+import { FormGroup, FormControl, Validators } from '@angular/forms';
 
 import { ConeSearch, Resolver } from 'src/app/instance/store/models';
+import { nanValidator, rangeValidator } from '../../validators';
 
 @Component({
     selector: 'app-cone-search',
@@ -19,14 +21,60 @@ import { ConeSearch, Resolver } from 'src/app/instance/store/models';
  * @class
  * @classdesc Cone search container.
  */
-export class ConeSearchComponent {
-    @Input() disabled: boolean = false;
-    @Input() resolverWip: boolean;
-    @Input() resolver: Resolver;
+export class ConeSearchComponent implements OnChanges {
     @Input() coneSearch: ConeSearch;
+    @Input() resolver: Resolver;
+    @Input() resolverIsLoading: boolean;
+    @Input() resolverIsLoaded: boolean;
+    @Output() addConeSearch: EventEmitter<ConeSearch> = new EventEmitter();
+    @Output() deleteConeSearch: EventEmitter<{ }> = new EventEmitter();
     @Output() retrieveCoordinates: EventEmitter<string> = new EventEmitter();
-    @Output() updateConeSearch: EventEmitter<ConeSearch> = new EventEmitter();
-    @Output() deleteResolver: EventEmitter<{}> = new EventEmitter();
 
-    unit = 'degree';
+    public form = new FormGroup({
+        ra: new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 360, 'RA')]),
+        ra_hms: new FormGroup({
+            h: new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 24, 'Hours')]),
+            m: new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Minutes')]),
+            s: new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Seconds')])
+        }),
+        dec: new FormControl('', [Validators.required, nanValidator, rangeValidator(-90, 90, 'DEC')]),
+        dec_dms: new FormGroup({
+            d: new FormControl('', [Validators.required, nanValidator, rangeValidator(-90, 90, 'Degree')]),
+            m: new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Minutes')]),
+            s: new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Seconds')])
+        }),
+        radius: new FormControl(2, [Validators.required, rangeValidator(0, 150, 'Radius')])
+    });
+
+    public unit = 'degree';
+
+    ngOnChanges(changes: SimpleChanges) {
+        if (changes.resolver && changes.resolver.currentValue) {
+            this.unit = 'degree';
+        }
+
+        if (changes.coneSearch && !changes.coneSearch.currentValue) {
+            if (this.unit = 'degree') {
+                this.form.controls.ra.enable();
+                this.form.controls.dec.enable();
+                this.form.controls.radius.enable();
+            } else {
+                this.form.controls.ra_hms.enable();
+                this.form.controls.dec_dms.enable();
+            }
+        }
+
+        if (changes.coneSearch && changes.coneSearch.currentValue) {
+            this.form.patchValue(this.coneSearch);
+            this.form.disable();
+        }
+    }
+
+    getConeSearch(): ConeSearch {
+        return {
+            ra: this.form.controls.ra.value,
+            dec: this.form.controls.dec.value,
+            radius: this.form.controls.radius.value
+        };
+    }
 }
diff --git a/client/src/app/instance/shared-search/components/cone-search/dec.component.html b/client/src/app/instance/shared-search/components/cone-search/dec.component.html
index 93539d69f28e7d93341ffa4e254b8440f9acc3aa..c8fe7677d7fa8cafd270f39ecdfae51c2630b970 100644
--- a/client/src/app/instance/shared-search/components/cone-search/dec.component.html
+++ b/client/src/app/instance/shared-search/components/cone-search/dec.component.html
@@ -1,92 +1,75 @@
-<div class="row px-3">
-    <label>DEC</label>
-    <div class="input-group">
-        <input type="text" class="form-control" [formControl]="decDegree" (input)="decChange()" autocomplete="off">
-        <div class="input-group-append">
-            <span class="input-group-text">°</span>
-        </div>
-    </div>
-</div>
-
-<div class="row mt-2 px-3">
-    <div class="col px-0 pr-xl-1">
+<form [formGroup]="form" novalidate>
+    <div class="row px-3">
+        <label>DEC</label>
         <div class="input-group">
-            <input type="text"
-                   class="form-control"
-                   [formControl]="decH"
-                   (input)="decChange()"
-                   (focusin)="changeFocus('dech', true)"
-                   (focusout)="changeFocus('dech', false)"
-                   (change)="setToDefaultValue()"
-                   autocomplete="off">
+            <input type="number" class="form-control" formControlName="dec" autocomplete="off">
             <div class="input-group-append">
                 <span class="input-group-text">°</span>
             </div>
         </div>
     </div>
-    <div class="w-100 d-block d-xl-none"></div>
-    <div class="col mt-1 mt-xl-auto px-0 pr-xl-1">
-        <div class="input-group">
-            <input type="text"
-                   class="form-control"
-                   [formControl]="decM"
-                   (input)="decChange()"
-                   (focusin)="changeFocus('decm', true)"
-                   (focusout)="changeFocus('decm', false)"
-                   (change)="setToDefaultValue()"
-                   autocomplete="off">
-            <div class="input-group-append">
-                <span class="input-group-text">'</span>
+
+    <div formGroupName="dec_dms">
+        <div class="row mt-2 px-3">
+            <div class="col px-0 pr-xl-1">
+                <div class="input-group">
+                    <input type="number" class="form-control" formControlName="d" autocomplete="off">
+                    <div class="input-group-append">
+                        <span class="input-group-text">°</span>
+                    </div>
+                </div>
             </div>
-        </div>
-    </div>
-    <div class="w-100 d-block d-xl-none"></div>
-    <div class="col mt-1 mt-xl-auto px-0">
-        <div class="input-group">
-            <input type="text"
-                   class="form-control"
-                   [formControl]="decS"
-                   (input)="decChange()"
-                   (focusin)="changeFocus('decs', true)"
-                   (focusout)="changeFocus('decs', false)"
-                   (change)="setToDefaultValue()"
-                   autocomplete="off">
-            <div class="input-group-append">
-                <span class="input-group-text">''</span>
+            <div class="w-100 d-block d-xl-none"></div>
+            <div class="col mt-1 mt-xl-auto px-0 pr-xl-1">
+                <div class="input-group">
+                    <input type="number" class="form-control" formControlName="m" autocomplete="off">
+                    <div class="input-group-append">
+                        <span class="input-group-text">'</span>
+                    </div>
+                </div>
+            </div>
+            <div class="w-100 d-block d-xl-none"></div>
+            <div class="col mt-1 mt-xl-auto px-0">
+                <div class="input-group">
+                    <input type="number" class="form-control" formControlName="s" autocomplete="off">
+                    <div class="input-group-append">
+                        <span class="input-group-text">''</span>
+                    </div>
+                </div>
             </div>
         </div>
     </div>
-</div>
+</form>
 
-<div *ngIf="decDegree.invalid" class="row px-3 text-danger">
-    <div *ngIf="decDegree.errors.nan">
-        {{ decDegree.errors.nan.value }}
+<div *ngIf="form.controls.dec.invalid" class="row px-3 text-danger">
+    <div *ngIf="form.controls.dec.errors.nan">
+        {{ form.controls.dec.errors.nan.value }}
     </div>
-    <div *ngIf="decDegree.errors.range" [hidden]="decDegree.errors.nan">
-        {{ decDegree.errors.range.value }}
+    <div *ngIf="form.controls.dec.errors.range" [hidden]="form.controls.dec.errors.nan">
+        {{ form.controls.dec.errors.range.value }}
     </div>
 </div>
-<div *ngIf="decH.invalid" class="row px-3 text-danger">
-    <div *ngIf="decH.errors.nan">
-        {{ decH.errors.nan.value }}
+<div *ngIf="getDecDmsForm().controls.d.invalid" class="row px-3 text-danger">
+    <div *ngIf="getDecDmsForm().controls.d.errors.nan">
+        {{ getDecDmsForm().controls.d.errors.nan.value }}
     </div>
-    <div *ngIf="decH.errors.range" [hidden]="decH.errors.nan">
-        {{ decH.errors.range.value }}
+    <div *ngIf="getDecDmsForm().controls.d.errors.range" [hidden]="getDecDmsForm().controls.d.errors.nan">
+        {{ getDecDmsForm().controls.d.errors.range.value }}
     </div>
 </div>
-<div *ngIf="decM.invalid" class="row px-3 text-danger">
-    <div *ngIf="decM.errors.nan">
-        {{ decM.errors.nan.value }}
+<div *ngIf="getDecDmsForm().controls.m.invalid" class="row px-3 text-danger">
+    <div *ngIf="getDecDmsForm().controls.m.errors.nan">
+        {{ getDecDmsForm().controls.m.errors.nan.value }}
     </div>
-    <div *ngIf="decM.errors.range" [hidden]="decM.errors.nan">
-        {{ decM.errors.range.value }}
+    <div *ngIf="getDecDmsForm().controls.m.errors.range" [hidden]="getDecDmsForm().controls.m.errors.nan">
+        {{ getDecDmsForm().controls.m.errors.range.value }}
     </div>
 </div>
-<div *ngIf="decS.invalid" class="row px-3 text-danger">
-    <div *ngIf="decS.errors.nan">
-        {{ decS.errors.nan.value }}
+<div *ngIf="getDecDmsForm().controls.s.invalid" class="row px-3 text-danger">
+    <div *ngIf="getDecDmsForm().controls.s.errors.nan">
+        {{ getDecDmsForm().controls.s.errors.nan.value }}
     </div>
-    <div *ngIf="decS.errors.range" [hidden]="decS.errors.nan">
-        {{ decS.errors.range.value }}
+    <div *ngIf="getDecDmsForm().controls.s.errors.range" [hidden]="getDecDmsForm().controls.s.errors.nan">
+        {{ getDecDmsForm().controls.s.errors.range.value }}
     </div>
 </div>
diff --git a/client/src/app/instance/shared-search/components/cone-search/dec.component.ts b/client/src/app/instance/shared-search/components/cone-search/dec.component.ts
index 3566031548cf7ad568b692487382f20033bccb0d..193bc66543fb5e9e5110c7d582591d5305160e29 100644
--- a/client/src/app/instance/shared-search/components/cone-search/dec.component.ts
+++ b/client/src/app/instance/shared-search/components/cone-search/dec.component.ts
@@ -7,11 +7,13 @@
  * file that was distributed with this source code.
  */
 
-import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
-import { FormControl, Validators } from '@angular/forms';
+import { Component, Input, ChangeDetectionStrategy, OnInit, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
+import { FormGroup } from '@angular/forms';
 
-import { nanValidator, rangeValidator } from '../../validators';
-import { ConeSearch, Resolver } from 'src/app/instance/store/models';
+import { Subscription } from 'rxjs';
+import { debounceTime } from 'rxjs/operators';
+
+import { Resolver } from 'src/app/instance/store/models';
 
 @Component({
     selector: 'app-dec',
@@ -23,199 +25,71 @@ import { ConeSearch, Resolver } from 'src/app/instance/store/models';
  * @class
  * @classdesc DEC component.
  */
-export class DecComponent {
-    /**
-     * Disables DEC fields.
-     *
-     * @param  {boolean} disabled - If the field has to be disabled.
-     */
-    @Input()
-    set disabled(disabled: boolean) {
-        this.isDisabled = disabled;
-        this.initFields();
+export class DecComponent implements OnInit, OnDestroy, OnChanges {
+    @Input() form: FormGroup;
+    @Input() unit: string;
+    @Input() resolver: Resolver;
+
+    public decControlSubscription: Subscription
+    public decDmsSubscription: Subscription;
+
+    ngOnInit() {
+        this.form.controls.dec_dms.disable();
+        this.decControlSubscription = this.form.controls.dec.valueChanges.pipe(debounceTime(250))
+            .subscribe(deg => this.deg2DMS(deg));
     }
-    /**
-     * Sets RA, DEC and radius from cone search.
-     *
-     * @param  {ConeSearch} coneSearch - The cone search.
-     */
-    @Input()
-    set coneSearch(coneSearch: ConeSearch) {
-        this.ra = coneSearch.ra;
-        this.radius = coneSearch.radius;
-        if (coneSearch.dec) {
-            this.decDegree.setValue(coneSearch.dec);
-            if(this.decDegree.valid && !this.decHFocused && !this.decMFocused && !this.decSFocused) {
-                this.decDegree2HMS(coneSearch.dec);
+
+    ngOnChanges(changes: SimpleChanges): void {
+        if (changes.unit && !changes.unit.firstChange) {
+            if (changes.unit.currentValue === 'degree') {
+                this.form.controls.dec_dms.disable();
+                this.form.controls.dec.enable();
+                this.decControlSubscription = this.form.controls.dec.valueChanges.pipe(debounceTime(250))
+                    .subscribe(deg => this.deg2DMS(deg));
+                if (this.decDmsSubscription) this.decDmsSubscription.unsubscribe();
+            }
+            if (changes.unit.currentValue === 'hms') {
+                this.form.controls.dec_dms.enable();
+                this.form.controls.dec.disable();
+                this.decDmsSubscription = this.form.controls.dec_dms.valueChanges.pipe(debounceTime(250))
+                    .subscribe(value => this.DMS2Deg(value));
+                if (this.decControlSubscription) this.decControlSubscription.unsubscribe();
             }
-        } else {
-            this.decDegree.reset();
-            this.decH.reset();
-            this.decM.reset();
-            this.decS.reset();
         }
-        this.initFields();
-    }
-    /**
-     * Sets RA from resolver.
-     *
-     * @param  {Resolver} resolver - The resolver.
-     */
-    @Input()
-    set resolver(resolver: Resolver) {
-        this.resolvedDec = null;
-        if (resolver) {
-            this.resolvedDec = resolver.dec;
-            this.decDegree.setValue(resolver.dec);
-            this.decDegree2HMS(resolver.dec);
+
+        if (changes.resolver && changes.resolver.currentValue) {
+            this.form.controls.dec.setValue(changes.resolver.currentValue.dec);
         }
     }
-    /**
-     * Sets isDegree.
-     *
-     * @param  {string} unit - The unit.
-     */
-    @Input()
-    set unit(unit: string) {
-        unit === 'degree' ? this.isDegree = true : this.isDegree = false;
-        this.initFields();
-    }
-    @Output() updateConeSearch: EventEmitter<ConeSearch> = new EventEmitter();
-    @Output() deleteResolver: EventEmitter<null> = new EventEmitter();
-
-    ra: number;
-    radius: number;
-    isDisabled = false;
-    isDegree = true;
-    resolvedDec: number;
-    decHFocused: boolean = false;
-    decMFocused: boolean = false;
-    decSFocused: boolean = false;
-
-    decDegree = new FormControl('', [Validators.required, nanValidator, rangeValidator(-90, 90, 'DEC')]);
-    decH = new FormControl('', [nanValidator, rangeValidator(-90, 90, 'Degree')]);
-    decM = new FormControl('', [nanValidator, rangeValidator(0, 60, 'Minutes')]);
-    decS = new FormControl('', [nanValidator, rangeValidator(0, 60, 'Seconds')]);
 
-    /**
-     * Sets DEC fields.
-     */
-    initFields(): void {
-        if (this.isDisabled) {
-            this.decDegree.disable();
-            this.decH.disable();
-            this.decM.disable();
-            this.decS.disable();
-        } else if (this.isDegree) {
-            this.decDegree.enable();
-            this.decH.disable();
-            this.decM.disable();
-            this.decS.disable();
-        } else {
-            this.decDegree.disable();
-            this.decH.enable();
-            this.decM.enable();
-            this.decS.enable();
-        }
+    getDecDmsForm() {
+        const decDmsForm = this.form.controls.dec_dms as FormGroup;
+        return decDmsForm;
     }
 
-    /**
-     * Converts DEC hour minute second from degree and sets DEC HMS fields.
-     *
-     * @param  {number} value - The degree value.
-     */
-    decDegree2HMS(value: number): void {
-        const hh = Math.trunc(value);
-        let tmp = (Math.abs(value - hh)) * 60;
+    deg2DMS(deg: number): void {
+        const hh = Math.trunc(deg);
+        let tmp = (Math.abs(deg - hh)) * 60;
         const mm = Math.trunc(tmp);
         tmp = (tmp - mm) * 60;
         const ss = tmp.toFixed(2);
-        this.decH.setValue(hh);
-        this.decM.setValue(mm);
-        this.decS.setValue(ss);
+        const decDmsForm = this.getDecDmsForm();
+        decDmsForm.controls.d.setValue(hh);
+        decDmsForm.controls.m.setValue(mm);
+        decDmsForm.controls.s.setValue(ss);
     }
 
-    /**
-     * Sets DEC degree from hour minute second and sets DEC degree field.
-     */
-    decHMS2Degree(): void {
-        const hh = +this.decH.value;
-        const mm = +this.decM.value;
-        const ss = +this.decS.value;
-        const tmp = ((ss / 60) + mm) / 60;
-        let deg = tmp + Math.abs(hh);
-        if (hh < 0) {
+    DMS2Deg(dms: {d: number, m: number, s: number }): void {
+        const tmp = ((dms.s / 60) + dms.m) / 60;
+        let deg = tmp + Math.abs(dms.d);
+        if (dms.d < 0) {
             deg = -deg;
         }
-        this.decDegree.setValue(+deg.toFixed(8));
+        this.form.controls.dec.setValue(deg);
     }
 
-    /**
-     * Changes fields focus.
-     *
-     * @param  {string} field - The field.
-     * @param  {boolean} isFocused - Is the field is focused.
-     */
-    changeFocus(field: string, isFocused: boolean) {
-        switch (field) {
-            case 'dech':
-                this.decHFocused = isFocused;
-                break;
-            case 'decm':
-                this.decMFocused = isFocused;
-                break
-            case 'decs':
-                this.decSFocused = isFocused;
-                break;
-        }
-    }
-
-    /**
-     * Manages DEC value change.
-     */
-    decChange(): void {
-        if (this.isDegree) {
-            if (this.decDegree.valid) {
-                this.decDegree2HMS(this.decDegree.value);
-            } else {
-                this.decH.reset();
-                this.decM.reset();
-                this.decS.reset();
-            }
-            this.updateConeSearch.emit({ ra: this.ra, dec: this.decDegree.value, radius: this.radius } as ConeSearch);
-        } else {
-            if (this.decH.valid && this.decM.valid && this.decS.valid) {
-                this.setToDefaultValue();
-                this.decHMS2Degree();
-                this.updateConeSearch.emit({ ra: this.ra, dec: this.decDegree.value, radius: this.radius } as ConeSearch);
-            } else {
-                this.decDegree.reset();
-            }
-        }
-        this.resetResolver();
-    }
-
-    /**
-     * Sets DEC hour minute second fields to default value if not valid.
-     */
-    setToDefaultValue(): void {
-        if (this.decH.value === '' || this.decH.value === null) {
-            this.decH.setValue(0);
-        }
-        if (this.decM.value === '' || this.decM.value === null) {
-            this.decM.setValue(0);
-        }
-        if (this.decS.value === '' || this.decS.value === null) {
-            this.decS.setValue(0);
-        }
-    }
-
-    /**
-     * Emits reset resolver event.
-     */
-    resetResolver(): void {
-        if (this.resolvedDec && this.resolvedDec !== this.decDegree.value) {
-            this.deleteResolver.emit();
-        }
+    ngOnDestroy() {
+        if (this.decControlSubscription) this.decControlSubscription.unsubscribe();
+        if (this.decDmsSubscription) this.decDmsSubscription.unsubscribe();
     }
 }
diff --git a/client/src/app/instance/shared-search/components/cone-search/ra.component.html b/client/src/app/instance/shared-search/components/cone-search/ra.component.html
index e1ff92f6fa13d6a68cb3cbf742663ba56fe49b94..bb180bf81ba5dc29c24c2197b74691d51fbd7002 100644
--- a/client/src/app/instance/shared-search/components/cone-search/ra.component.html
+++ b/client/src/app/instance/shared-search/components/cone-search/ra.component.html
@@ -1,92 +1,75 @@
-<div class="row px-3">
-    <label>RA</label>
-    <div class="input-group">
-        <input type="text" class="form-control" [formControl]="raDegree" (input)="raChange()" autocomplete="off">
-        <div class="input-group-append">
-            <span class="input-group-text">°</span>
-        </div>
-    </div>
-</div>
-
-<div class="row mt-2 px-3">
-    <div class="col px-0 pr-xl-1">
+<form [formGroup]="form" novalidate>
+    <div class="row px-3">
+        <label>RA</label>
         <div class="input-group">
-            <input type="text"
-                   class="form-control"
-                   [formControl]="raH"
-                   (input)="raChange()"
-                   (focusin)="changeFocus('rah', true)"
-                   (focusout)="changeFocus('rah', false)"
-                   (change)="setToDefaultValue()"
-                   autocomplete="off">
+            <input type="number" class="form-control" formControlName="ra" autocomplete="off">
             <div class="input-group-append">
-                <span class="input-group-text">H</span>
+                <span class="input-group-text">°</span>
             </div>
         </div>
     </div>
-    <div class="w-100 d-block d-xl-none"></div>
-    <div class="col mt-1 mt-xl-auto px-0 pr-xl-1">
-        <div class="input-group">
-            <input type="text"
-                   class="form-control"
-                   [formControl]="raM"
-                   (input)="raChange()"
-                   (focusin)="changeFocus('ram', true)"
-                   (focusout)="changeFocus('ram', false)"
-                   (change)="setToDefaultValue()"
-                   autocomplete="off">
-            <div class="input-group-append">
-                <span class="input-group-text">'</span>
+
+    <div formGroupName="ra_hms">
+        <div class="row mt-2 px-3">
+            <div class="col px-0 pr-xl-1">
+                <div class="input-group">
+                    <input type="number" class="form-control" formControlName="h" autocomplete="off">
+                    <div class="input-group-append">
+                        <span class="input-group-text">H</span>
+                    </div>
+                </div>
             </div>
-        </div>
-    </div>
-    <div class="w-100 d-block d-xl-none"></div>
-    <div class="col mt-1 mt-xl-auto px-0">
-        <div class="input-group">
-            <input type="text"
-                   class="form-control"
-                   [formControl]="raS"
-                   (input)="raChange()"
-                   (focusin)="changeFocus('ras', true)"
-                   (focusout)="changeFocus('ras', false)"
-                   (change)="setToDefaultValue()"
-                   autocomplete="off">
-            <div class="input-group-append">
-                <span class="input-group-text">''</span>
+            <div class="w-100 d-block d-xl-none"></div>
+            <div class="col mt-1 mt-xl-auto px-0 pr-xl-1">
+                <div class="input-group">
+                    <input type="number" class="form-control" formControlName="m" autocomplete="off">
+                    <div class="input-group-append">
+                        <span class="input-group-text">'</span>
+                    </div>
+                </div>
+            </div>
+            <div class="w-100 d-block d-xl-none"></div>
+            <div class="col mt-1 mt-xl-auto px-0">
+                <div class="input-group">
+                    <input type="number" class="form-control" formControlName="s" autocomplete="off">
+                    <div class="input-group-append">
+                        <span class="input-group-text">''</span>
+                    </div>
+                </div>
             </div>
         </div>
     </div>
-</div>
+</form>
 
-<div *ngIf="raDegree.invalid" class="row px-3 text-danger">
-    <div *ngIf="raDegree.errors.nan">
-        {{ raDegree.errors.nan.value }}
+<div *ngIf="form.controls.ra.invalid" class="row px-3 text-danger">
+    <div *ngIf="form.controls.ra.errors.nan">
+        {{ form.controls.ra.errors.nan.value }}
     </div>
-    <div *ngIf="raDegree.errors.range" [hidden]="raDegree.errors.nan">
-        {{ raDegree.errors.range.value }}
+    <div *ngIf="form.controls.ra.errors.range" [hidden]="form.controls.ra.errors.nan">
+        {{ form.controls.ra.errors.range.value }}
     </div>
 </div>
-<div *ngIf="raH.invalid" class="row px-3 text-danger">
-    <div *ngIf="raH.errors.nan">
-        {{ raH.errors.nan.value }}
+<div *ngIf="getRaHmsForm().controls.h.invalid" class="row px-3 text-danger">
+    <div *ngIf="getRaHmsForm().controls.h.errors.nan">
+        {{ getRaHmsForm().controls.h.errors.nan.value }}
     </div>
-    <div *ngIf="raH.errors.range" [hidden]="raH.errors.nan">
-        {{ raH.errors.range.value }}
+    <div *ngIf="getRaHmsForm().controls.h.errors.range" [hidden]="getRaHmsForm().controls.h.errors.nan">
+        {{ getRaHmsForm().controls.h.errors.range.value }}
     </div>
 </div>
-<div *ngIf="raM.invalid" class="row px-3 text-danger">
-    <div *ngIf="raM.errors.nan">
-        {{ raM.errors.nan.value }}
+<div *ngIf="getRaHmsForm().controls.m.invalid" class="row px-3 text-danger">
+    <div *ngIf="getRaHmsForm().controls.m.errors.nan">
+        {{ getRaHmsForm().controls.m.errors.nan.value }}
     </div>
-    <div *ngIf="raM.errors.range" [hidden]="raM.errors.nan">
-        {{ raM.errors.range.value }}
+    <div *ngIf="getRaHmsForm().controls.m.errors.range" [hidden]="getRaHmsForm().controls.m.errors.nan">
+        {{ getRaHmsForm().controls.m.errors.range.value }}
     </div>
 </div>
-<div *ngIf="raS.invalid" class="row px-3 text-danger">
-    <div *ngIf="raS.errors.nan">
-        {{ raS.errors.nan.value }}
+<div *ngIf="getRaHmsForm().controls.s.invalid" class="row px-3 text-danger">
+    <div *ngIf="getRaHmsForm().controls.s.errors.nan">
+        {{ getRaHmsForm().controls.s.errors.nan.value }}
     </div>
-    <div *ngIf="raS.errors.range" [hidden]="raS.errors.nan">
-        {{ raS.errors.range.value }}
+    <div *ngIf="getRaHmsForm().controls.s.errors.range" [hidden]="getRaHmsForm().controls.s.errors.nan">
+        {{ getRaHmsForm().controls.s.errors.range.value }}
     </div>
 </div>
diff --git a/client/src/app/instance/shared-search/components/cone-search/ra.component.ts b/client/src/app/instance/shared-search/components/cone-search/ra.component.ts
index 30050f202540cf03c3d6659588e2c2c1595b5e90..aab36bf7ec811d5984d1d977b0b78847db203ab9 100644
--- a/client/src/app/instance/shared-search/components/cone-search/ra.component.ts
+++ b/client/src/app/instance/shared-search/components/cone-search/ra.component.ts
@@ -7,11 +7,13 @@
  * file that was distributed with this source code.
  */
 
-import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
-import { FormControl, Validators } from '@angular/forms';
+import { Component, Input, ChangeDetectionStrategy, OnDestroy, OnInit, OnChanges, SimpleChanges } from '@angular/core';
+import { FormGroup } from '@angular/forms';
 
-import { nanValidator, rangeValidator } from '../../validators';
-import { ConeSearch, Resolver } from 'src/app/instance/store/models';
+import { Subscription } from 'rxjs';
+import { debounceTime } from 'rxjs/operators';
+
+import { Resolver } from 'src/app/instance/store/models';
 
 @Component({
     selector: 'app-ra',
@@ -23,196 +25,68 @@ import { ConeSearch, Resolver } from 'src/app/instance/store/models';
  * @class
  * @classdesc RA component.
  */
-export class RaComponent {
-    /**
-     * Disables RA fields.
-     *
-     * @param  {boolean} disabled - If the field has to be disabled.
-     */
-    @Input()
-    set disabled(disabled: boolean) {
-        this.isDisabled = disabled;
-        this.initFields();
+export class RaComponent implements OnInit, OnDestroy, OnChanges  {
+    @Input() form: FormGroup;
+    @Input() unit: string;
+    @Input() resolver: Resolver;
+
+    public raControlSubscription: Subscription;
+    public raHmsFormSubscription: Subscription;
+
+    ngOnInit() {
+        this.form.controls.ra_hms.disable();
+        this.raControlSubscription = this.form.controls.ra.valueChanges.pipe(debounceTime(250))
+            .subscribe(deg => this.deg2HMS(deg));
     }
-    /**
-     * Sets RA, DEC and radius from cone search.
-     *
-     * @param  {ConeSearch} coneSearch - The cone search.
-     */
-    @Input()
-    set coneSearch(coneSearch: ConeSearch) {
-        this.dec = coneSearch.dec;
-        this.radius = coneSearch.radius;
-        if (coneSearch.ra) {
-            this.raDegree.setValue(coneSearch.ra);
-            if (this.raDegree.valid && !this.raHFocused && !this.raMFocused && !this.raSFocused) {
-                this.raDegree2HMS(coneSearch.ra);
+
+    ngOnChanges(changes: SimpleChanges): void {
+        if (changes.unit && !changes.unit.firstChange) {
+            if (changes.unit.currentValue === 'degree') {
+                this.form.controls.ra_hms.disable();
+                this.form.controls.ra.enable();
+                this.raControlSubscription = this.form.controls.ra.valueChanges.pipe(debounceTime(250))
+                    .subscribe(deg => this.deg2HMS(deg));
+                if (this.raHmsFormSubscription) this.raHmsFormSubscription.unsubscribe();
+            }
+            if (changes.unit.currentValue === 'hms') {
+                this.form.controls.ra_hms.enable();
+                this.form.controls.ra.disable();
+                this.raHmsFormSubscription = this.form.controls.ra_hms.valueChanges.pipe(debounceTime(250))
+                    .subscribe(value => this.HMS2Deg(value));
+                if (this.raControlSubscription) this.raControlSubscription.unsubscribe();
             }
-        } else {
-            this.raDegree.reset();
-            this.raH.reset();
-            this.raM.reset();
-            this.raS.reset();
         }
-        this.initFields();
-    }
-    /**
-     * Sets RA from resolver.
-     *
-     * @param  {Resolver} resolver - The resolver.
-     */
-    @Input()
-    set resolver(resolver: Resolver) {
-        this.resolvedRa = null;
-        if (resolver) {
-            this.resolvedRa = resolver.ra;
-            this.raDegree.setValue(resolver.ra);
-            this.raDegree2HMS(resolver.ra);
+
+        if (changes.resolver && changes.resolver.currentValue) {
+            this.form.controls.ra.setValue(changes.resolver.currentValue.ra);
         }
     }
-    /**
-     * Sets isDegree.
-     *
-     * @param  {string} unit - The unit.
-     */
-    @Input()
-    set unit(unit: string) {
-        unit === 'degree' ? this.isDegree = true : this.isDegree = false;
-        this.initFields();
-    }
-    @Output() updateConeSearch: EventEmitter<ConeSearch> = new EventEmitter();
-    @Output() deleteResolver: EventEmitter<null> = new EventEmitter();
-
-    dec: number = null;
-    radius: number = null;
-    isDisabled = false;
-    isDegree = true;
-    resolvedRa: number;
-    raHFocused: boolean = false;
-    raMFocused: boolean = false;
-    raSFocused: boolean = false;
-
-    raDegree = new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 360, 'RA')]);
-    raH = new FormControl('', [nanValidator, rangeValidator(0, 24, 'Hours')]);
-    raM = new FormControl('', [nanValidator, rangeValidator(0, 60, 'Minutes')]);
-    raS = new FormControl('', [nanValidator, rangeValidator(0, 60, 'Seconds')]);
 
-    /**
-     * Sets RA fields.
-     */
-    initFields(): void {
-        if (this.isDisabled) {
-            this.raDegree.disable();
-            this.raH.disable();
-            this.raM.disable();
-            this.raS.disable();
-        } else if (this.isDegree) {
-            this.raDegree.enable();
-            this.raH.disable();
-            this.raM.disable();
-            this.raS.disable();
-        } else {
-            this.raDegree.disable();
-            this.raH.enable();
-            this.raM.enable();
-            this.raS.enable();
-        }
+    getRaHmsForm() {
+        const raHmsForm = this.form.controls.ra_hms as FormGroup;
+        return raHmsForm;
     }
 
-    /**
-     * Converts RA hour minute second from degree and sets RA HMS fields.
-     *
-     * @param  {number} value - The degree value.
-     */
-    raDegree2HMS(value: number): void {
-        let tmp = value / 15;
+    deg2HMS(deg: number): void {
+        let tmp = deg / 15;
         const hh = Math.trunc(tmp);
         tmp = (tmp - hh) * 60;
         const mm = Math.trunc(tmp);
         tmp = (tmp - mm) * 60;
         const ss = +tmp.toFixed(2);
-        this.raH.setValue(hh);
-        this.raM.setValue(mm);
-        this.raS.setValue(ss);
+        const raHmsForm = this.getRaHmsForm();
+        raHmsForm.controls.h.setValue(hh);
+        raHmsForm.controls.m.setValue(mm);
+        raHmsForm.controls.s.setValue(ss);
     }
 
-    /**
-     * Sets RA degree from hour minute second and sets RA degree field.
-     */
-    raHMS2Degree(): void {
-        const hh = +this.raH.value;
-        const mm = +this.raM.value;
-        const ss = +this.raS.value;
-        const deg = +(((((ss / 60) + mm) / 60) + hh) * 15).toFixed(8);
-        this.raDegree.setValue(deg);
+    HMS2Deg(hms: {h: number, m: number, s: number }): void {
+        const deg = +(((((hms.s / 60) + hms.m) / 60) + hms.h) * 15).toFixed(8);
+        this.form.controls.ra.setValue(deg);
     }
 
-    /**
-     * Changes fields focus.
-     *
-     * @param  {string} field - The field.
-     * @param  {boolean} isFocused - Is the field is focused.
-     */
-    changeFocus(field: string, isFocused: boolean): void {
-        switch (field) {
-            case 'rah':
-                this.raHFocused = isFocused;
-                break;
-            case 'ram':
-                this.raMFocused = isFocused;
-                break
-            case 'ras':
-                this.raSFocused = isFocused;
-                break;
-        }
-    }
-
-    /**
-     * Manages RA value change.
-     */
-    raChange(): void {
-        if (this.isDegree) {
-            if (this.raDegree.valid) {
-                this.raDegree2HMS(this.raDegree.value);
-            } else {
-                this.raH.reset();
-                this.raM.reset();
-                this.raS.reset();
-            }
-            this.updateConeSearch.emit({ ra: this.raDegree.value, dec: this.dec, radius: this.radius } as ConeSearch);
-        } else {
-            if (this.raH.valid && this.raM.valid && this.raS.valid) {
-                this.setToDefaultValue();
-                this.raHMS2Degree();
-                this.updateConeSearch.emit({ ra: this.raDegree.value, dec: this.dec, radius: this.radius } as ConeSearch);
-            } else {
-                this.raDegree.reset();
-            }
-        }
-        this.resetResolver();
-    }
-
-    /**
-     * Sets RA hour minute second fields to default value if not valid.
-     */
-    setToDefaultValue(): void {
-        if (this.raH.value === '' || this.raH.value === null) {
-            this.raH.setValue(0);
-        }
-        if (this.raM.value === '' || this.raM.value === null) {
-            this.raM.setValue(0);
-        }
-        if (this.raS.value === '' || this.raS.value === null) {
-            this.raS.setValue(0);
-        }
-    }
-
-    /**
-     * Emits reset resolver event.
-     */
-    resetResolver(): void {
-        if (this.resolvedRa && this.resolvedRa !== this.raDegree.value) {
-            this.deleteResolver.emit();
-        }
+    ngOnDestroy() {
+        if (this.raControlSubscription) this.raControlSubscription.unsubscribe();
+        if (this.raHmsFormSubscription) this.raHmsFormSubscription.unsubscribe();
     }
 }
diff --git a/client/src/app/instance/shared-search/components/cone-search/radius.component.html b/client/src/app/instance/shared-search/components/cone-search/radius.component.html
index 406cdfc30e2dcaeb8151aad6ac776a9d23cc3c60..87cdf7a216c9304bef8e199db31a26860a70adda 100644
--- a/client/src/app/instance/shared-search/components/cone-search/radius.component.html
+++ b/client/src/app/instance/shared-search/components/cone-search/radius.component.html
@@ -1,27 +1,22 @@
-<div class="row">
-    <div class="col form-group mb-0">
-        <label>Radius</label>
-        <input #rr
-            type="range"
-            min="0"
-            max="150"
-            [formControl]="radiusRange"
-            (input)="radiusChange(rr.value)"
-            class="form-control-range mt-2"
-            autocomplete="off">
-    </div>
-    <div class="w-100 d-block d-lg-none"></div>
-    <div class="col col-lg-auto form-group mb-0">
-        <div class="input-group mt-4">
-            <input #rf id="radius-field" type="number" class="form-control" [formControl]="radiusField" (input)="radiusChange(rf.value)" autocomplete="off">
-            <div class="input-group-append">
-                <span class="input-group-text">arcsecond</span>
+<form [formGroup]="form" novalidate>
+    <div class="row">
+        <div class="col form-group mb-0">
+            <label>Radius</label>
+            <input type="range" min="0" max="150" class="form-control-range mt-2" [value]="form.value.radius" formControlName="radius" autocomplete="off">
+        </div>
+        <div class="w-100 d-block d-lg-none"></div>
+        <div class="col col-lg-auto form-group mb-0">
+            <div class="input-group mt-4">
+                <input type="number" class="form-control" [value]="form.value.radius" formControlName="radius" autocomplete="off">
+                <div class="input-group-append">
+                    <span class="input-group-text">arcsecond</span>
+                </div>
             </div>
         </div>
-    </div>
-    <div *ngIf="radiusField.invalid" class="col-12 text-danger">
-        <div *ngIf="radiusField.errors.range">
-            {{ radiusField.errors.range.value }}
+        <div *ngIf="form.controls.radius.invalid" class="col-12 text-danger">
+            <div *ngIf="form.controls.radius.errors.range">
+                {{ form.controls.radius.errors.range.value }}
+            </div>
         </div>
     </div>
-</div>
+</form>
\ No newline at end of file
diff --git a/client/src/app/instance/shared-search/components/cone-search/radius.component.ts b/client/src/app/instance/shared-search/components/cone-search/radius.component.ts
index 5add3abf531de6ea605e5547a42bc19832ec16f1..fde6ceb216655a19b21d8966877a01fd29a0d0b1 100644
--- a/client/src/app/instance/shared-search/components/cone-search/radius.component.ts
+++ b/client/src/app/instance/shared-search/components/cone-search/radius.component.ts
@@ -7,11 +7,8 @@
  * file that was distributed with this source code.
  */
 
-import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
-import { FormControl } from '@angular/forms';
-
-import { rangeValidator } from '../../validators';
-import { ConeSearch } from 'src/app/instance/store/models';
+import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
+import { FormGroup } from '@angular/forms';
 
 @Component({
     selector: 'app-radius',
@@ -24,55 +21,5 @@ import { ConeSearch } from 'src/app/instance/store/models';
  * @classdesc Radius component.
  */
 export class RadiusComponent {
-    /**
-     * Sets RA, DEC and radius from cone search.
-     *
-     * @param  {ConeSearch} coneSearch - The cone search.
-     */
-    @Input()
-    set coneSearch(coneSearch: ConeSearch) {
-        this.ra = coneSearch.ra;
-        this.dec = coneSearch.dec;
-        if (coneSearch.radius) {
-            this.radiusField.setValue(coneSearch.radius);
-            this.radiusRange.setValue(coneSearch.radius);
-        } else {
-            this.radiusRange.setValue(0);
-            this.radiusField.setValue(0);
-        }
-    }
-    /**
-     * Disables radius fields.
-     *
-     * @param  {boolean} disabled - If the field has to be disabled.
-     */
-    @Input()
-    set disabled(disabled: boolean) {
-        if (disabled) {
-            this.radiusField.disable();
-            this.radiusRange.disable();
-        } else {
-            this.radiusField.enable();
-            this.radiusRange.enable();
-        }
-    }
-    @Output() updateConeSearch: EventEmitter<ConeSearch> = new EventEmitter();
-
-    ra: number;
-    dec: number;
-    radiusRange = new FormControl('');
-    radiusField = new FormControl('', [rangeValidator(0, 150, 'Radius')]);
-
-    /**
-     * Sets radius value form inputs and emits cone search event.
-     *
-     * @param  {string} value - The value of radius.
-     *
-     * @fires EventEmitter<ConeSearch>
-     */
-    radiusChange(value: string): void {
-        this.radiusField.setValue(+value);
-        this.radiusRange.setValue(+value);
-        this.updateConeSearch.emit({ ra: this.ra, dec: this.dec, radius: +value } as ConeSearch);
-    }
+    @Input() form: FormGroup;
 }
diff --git a/client/src/app/instance/shared-search/components/cone-search/resolver.component.html b/client/src/app/instance/shared-search/components/cone-search/resolver.component.html
index 86714689d9db49082707206b9002ed94cdf661e8..abf2a55cc7b6b98bc988778340658be4d0588d4b 100644
--- a/client/src/app/instance/shared-search/components/cone-search/resolver.component.html
+++ b/client/src/app/instance/shared-search/components/cone-search/resolver.component.html
@@ -1,15 +1,17 @@
-<div class="row">
-    <div class="col pr-0">
-        <label for="resolver">Resolve RA and DEC with Sesame Name Resolver</label>
-        <input #n id="resolver" type="text" class="form-control" [formControl]="field" autocomplete="off">
+<form [formGroup]="form" (ngSubmit)="submit()" novalidate>
+    <div class="row">
+        <div class="col pr-0">
+            <label for="resolver">Resolve RA and DEC with Sesame Name Resolver</label>
+            <input type="text" class="form-control" name="name" formControlName="name" autocomplete="off">
+        </div>
+        <div class="col-auto pt-5 pt-lg-4">
+            <button *ngIf="!resolverIsLoading" [disabled]="!form.valid || form.pristine" type="submit" class="btn btn-outline-secondary mt-2">
+                <span class="fas fa-search"></span>
+            </button>
+            <button *ngIf="resolverIsLoading" class="btn btn-outline-secondary mt-2" disabled>
+                <span class="fas fa-circle-notch fa-spin"></span>
+                <span class="sr-only">Loading...</span>
+            </button>
+        </div>
     </div>
-    <div class="col-auto pt-5 pt-lg-4">
-        <button *ngIf="!resolverWip" id="btn-search" class="btn btn-outline-secondary mt-2" [disabled]="field.disabled" (click)="resolveName.emit(n.value)">
-            <span class="fas fa-search"></span>
-        </button>
-        <button *ngIf="resolverWip" id="btn-wip" class="btn btn-outline-secondary mt-2" disabled>
-            <span class="fas fa-circle-notch fa-spin"></span>
-            <span class="sr-only">Loading...</span>
-        </button>
-    </div>
-</div>
+</form>
diff --git a/client/src/app/instance/shared-search/components/cone-search/resolver.component.ts b/client/src/app/instance/shared-search/components/cone-search/resolver.component.ts
index 1c01755596db0bfad2c8509903f7f76d68e1f957..18c094444753d9795a7088eb0aca5e3a1a8fae1d 100644
--- a/client/src/app/instance/shared-search/components/cone-search/resolver.component.ts
+++ b/client/src/app/instance/shared-search/components/cone-search/resolver.component.ts
@@ -7,10 +7,10 @@
  * file that was distributed with this source code.
  */
 
-import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
-import { FormControl } from '@angular/forms';
+import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, OnInit, OnChanges, SimpleChanges } from '@angular/core';
+import { FormGroup, FormControl, Validators } from '@angular/forms';
 
-import { Resolver } from 'src/app/instance/store/models';
+import { ConeSearch, Resolver } from 'src/app/instance/store/models';
 
 @Component({
     selector: 'app-resolver',
@@ -21,25 +21,34 @@ import { Resolver } from 'src/app/instance/store/models';
  * @class
  * @classdesc Resolver component.
  */
-export class ResolverComponent {
-    @Input()
-    set disabled(disabled: boolean) {
-        if (disabled) {
-            this.field.disable();
-        } else {
-            this.field.enable();
+export class ResolverComponent implements OnInit, OnChanges {
+    @Input() coneSearch: ConeSearch;
+    @Input() resolver: Resolver;
+    @Input() resolverIsLoading: boolean;
+    @Input() resolverIsLoaded: boolean;
+    @Output() retrieveCoordinates: EventEmitter<string> = new EventEmitter();
+
+    public form = new FormGroup({
+        name: new FormControl('', [Validators.required])
+    });
+
+    ngOnInit() {
+        if (this.coneSearch) {
+            this.form.disable();
         }
     }
-    @Input() resolverWip: boolean;
-    @Input()
-    set resolver(resolver: Resolver) {
-        if (resolver) {
-            this.field.setValue(resolver.name);
-        } else {
-            this.field.reset();
+
+    ngOnChanges(changes: SimpleChanges): void {
+        if (changes.coneSearch && !changes.coneSearch.currentValue) {
+            this.form.enable();
+        }
+
+        if (changes.coneSearch && changes.coneSearch.currentValue) {
+            this.form.disable();
         }
     }
-    @Output() resolveName: EventEmitter<string> = new EventEmitter();
 
-    field = new FormControl('');
+    submit() {
+        this.retrieveCoordinates.emit(this.form.controls.name.value);
+    }
 }
diff --git a/client/src/app/instance/shared-search/components/index.ts b/client/src/app/instance/shared-search/components/index.ts
index f3ee95d0784280eae6250d149041229fd9e5127f..1bd2ebbdd5b479facf234dd6ba38ab4ef88f589e 100644
--- a/client/src/app/instance/shared-search/components/index.ts
+++ b/client/src/app/instance/shared-search/components/index.ts
@@ -1,7 +1,7 @@
-// import { coneSearchComponents } from './cone-search';
+import { coneSearchComponents } from './cone-search';
 import { datatableComponents } from './datatable';
 
 export const sharedComponents = [
-    // coneSearchComponents,
+    coneSearchComponents,
     datatableComponents
 ];
diff --git a/client/src/app/instance/store/actions/cone-search.actions.ts b/client/src/app/instance/store/actions/cone-search.actions.ts
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..779b424153952b2ca4f4e0dba7157b5a97c55c0e 100644
--- a/client/src/app/instance/store/actions/cone-search.actions.ts
+++ b/client/src/app/instance/store/actions/cone-search.actions.ts
@@ -0,0 +1,18 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { createAction, props } from '@ngrx/store';
+
+import { ConeSearch, Resolver } from '../models';
+
+export const addConeSearch = createAction('[ConeSearch] Add Cone Search', props<{ coneSearch: ConeSearch }>());
+export const deleteConeSearch = createAction('[ConeSearch] Delete Cone Search');
+export const retrieveCoordinates = createAction('[ConeSearch] Retrieve Coordinates', props<{ name: string }>());
+export const retrieveCoordinatesSuccess = createAction('[ConeSearch] Retrieve Coordinates Success', props<{ resolver: Resolver }>());
+export const retrieveCoordinatesFail = createAction('[ConeSearch] Retrieve Coordinates Fail');
diff --git a/client/src/app/instance/store/effects/cone-search.effects.ts b/client/src/app/instance/store/effects/cone-search.effects.ts
new file mode 100644
index 0000000000000000000000000000000000000000..84d2ab8fe05cc36bdba788ba155cd47ae0c7270d
--- /dev/null
+++ b/client/src/app/instance/store/effects/cone-search.effects.ts
@@ -0,0 +1,58 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Injectable } from '@angular/core';
+
+import { Actions, createEffect, ofType } from '@ngrx/effects';
+import { of } from 'rxjs';
+import { map, tap, mergeMap, catchError } from 'rxjs/operators';
+import { ToastrService } from 'ngx-toastr';
+
+import * as coneSearchActions from '../actions/cone-search.actions';
+import { ConeSearchService } from '../services/cone-search.service';
+
+@Injectable()
+export class ConeSearchEffects {
+    retrieveCoordinates$ = createEffect(() =>
+        this.actions$.pipe(
+            ofType(coneSearchActions.retrieveCoordinates),
+            mergeMap((action) => this.coneSearchService.retrieveCoordinates(action.name)
+                .pipe(
+                    map(response => {
+                        const parser = new DOMParser();
+                        const xml = parser.parseFromString(response,'text/xml');
+                        if (xml.getElementsByTagName('Resolver').length === 0) {
+                            const name = xml.getElementsByTagName('name')[0].childNodes[0].nodeValue;
+                            return coneSearchActions.retrieveCoordinatesFail();
+                        }
+                        const name = xml.getElementsByTagName('name')[0].childNodes[0].nodeValue;
+                        const ra = +xml.getElementsByTagName('jradeg')[0].childNodes[0].nodeValue;
+                        const dec = +xml.getElementsByTagName('jdedeg')[0].childNodes[0].nodeValue;
+                        const resolver = { name, ra, dec };
+                        return coneSearchActions.retrieveCoordinatesSuccess({ resolver });
+                    }),
+                    catchError(() => of(coneSearchActions.retrieveCoordinatesFail()))
+                )
+            )
+        )
+    );
+
+    retrieveCoordinatesFail$ = createEffect(() => 
+        this.actions$.pipe(
+            ofType(coneSearchActions.retrieveCoordinatesFail),
+            tap(() => this.toastr.error('Failure to retrieve coordinates', 'The coordinates could not be retrieved'))
+        ), { dispatch: false}
+    );
+
+    constructor(
+        private actions$: Actions,
+        private coneSearchService: ConeSearchService,
+        private toastr: ToastrService
+    ) {}
+}
diff --git a/client/src/app/instance/store/effects/index.ts b/client/src/app/instance/store/effects/index.ts
index 296d89b24794a19ce38357ac7eab009ed9234257..3d2ecd77ad3f9e6f15ba5a0e1938aac5679cb49d 100644
--- a/client/src/app/instance/store/effects/index.ts
+++ b/client/src/app/instance/store/effects/index.ts
@@ -1,9 +1,11 @@
 import { MetamodelEffects } from './metamodel.effects';
-import { SampEffects } from "./samp.effects";
-import { SearchEffects } from "./search.effects";
+import { SampEffects } from './samp.effects';
+import { SearchEffects } from './search.effects';
+import { ConeSearchEffects } from './cone-search.effects';
 
 export const instanceEffects = [
     MetamodelEffects,
     SampEffects,
-    SearchEffects
+    SearchEffects,
+    ConeSearchEffects
 ];
diff --git a/client/src/app/instance/store/effects/search.effects.ts b/client/src/app/instance/store/effects/search.effects.ts
index f3ffcd4d55f29538f39c453a2b763b179796226e..b92513c667482841cf169ebeef11fa595520adc9 100644
--- a/client/src/app/instance/store/effects/search.effects.ts
+++ b/client/src/app/instance/store/effects/search.effects.ts
@@ -15,7 +15,7 @@ import { of } from 'rxjs';
 import { map, tap, mergeMap, catchError } from 'rxjs/operators';
 import { ToastrService } from 'ngx-toastr';
 
-import { criterionToString, stringToCriterion } from '../models';
+import { ConeSearch, criterionToString, stringToCriterion } from '../models';
 import { SearchService } from '../services/search.service';
 import * as searchActions from '../actions/search.actions';
 import * as attributeActions from 'src/app/metamodel/actions/attribute.actions';
@@ -25,6 +25,8 @@ import * as outputFamilyActions from 'src/app/metamodel/actions/output-family.ac
 import * as outputCategoryActions from 'src/app/metamodel/actions/output-category.actions';
 import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector';
 import * as searchSelector from '../selectors/search.selector';
+import * as coneSearchActions from '../actions/cone-search.actions';
+import * as coneSearchSelector from '../selectors/cone-search.selector';
 
 @Injectable()
 export class SearchEffects {
@@ -88,11 +90,19 @@ export class SearchEffects {
         this.actions$.pipe(
             ofType(searchActions.loadDefaultFormParameters),
             concatLatestFrom(() => [
+                this.store.select(searchSelector.selectPristine),
+                this.store.select(searchSelector.selectCurrentDataset),
                 this.store.select(attributeSelector.selectAllAttributes),
                 this.store.select(searchSelector.selectCriteriaListByRoute),
+                this.store.select(coneSearchSelector.selectConeSearchByRoute),
                 this.store.select(searchSelector.selectOutputListByRoute)
             ]),
-            mergeMap(([action, attributeList, criteriaList, outputList]) => {
+            mergeMap(([action, pristine, currentDataset, attributeList, criteriaList, coneSearch, outputList]) => {
+                if (!pristine || !currentDataset) {
+                    // Default form parameters already loaded or no dataset selected
+                    return of({ type: '[No Action] Load Default Form Parameters' });
+                }
+
                 // Update criteria list
                 let defaultCriteriaList = [];
                 if (criteriaList) {
@@ -109,6 +119,17 @@ export class SearchEffects {
                         .map(attribute => stringToCriterion(attribute));
                 }
 
+                // Update cone search
+                let defaultConeSearch: ConeSearch = null;
+                if (coneSearch) {
+                    const params = coneSearch.split(':');
+                    defaultConeSearch = {
+                        ra: +params[0],
+                        dec: +params[1],
+                        radius: +params[2]
+                    };
+                }
+
                 // Update output list
                 let defaultOutputList = [];
                 if (outputList) {
@@ -124,6 +145,7 @@ export class SearchEffects {
                 // Returns actions and mark the form as dirty
                 return [
                     searchActions.updateCriteriaList({ criteriaList: defaultCriteriaList }),
+                    coneSearchActions.addConeSearch({ coneSearch: defaultConeSearch }),
                     searchActions.updateOutputList({ outputList: defaultOutputList }),
                     searchActions.markAsDirty()
                 ];
@@ -136,13 +158,17 @@ export class SearchEffects {
             ofType(searchActions.retrieveDataLength),
             concatLatestFrom(() => [
                 this.store.select(datasetSelector.selectDatasetNameByRoute),
-                this.store.select(searchSelector.selectCriteriaList)
+                this.store.select(searchSelector.selectCriteriaList),
+                this.store.select(coneSearchSelector.selectConeSearch)
             ]),
-            mergeMap(([action, datasetName, criteriaList]) => {
+            mergeMap(([action, datasetName, criteriaList, coneSearch]) => {
                 let query = datasetName + '?a=count';
                 if (criteriaList.length > 0) {
                     query += '&c=' + criteriaList.map(criterion => criterionToString(criterion)).join(';');
                 }
+                if (coneSearch) {
+                    query += '&cs=' + coneSearch.ra + ':' + coneSearch.dec + ':' + coneSearch.radius;
+                }
 
                 return this.searchService.retrieveDataLength(query)
                     .pipe(
@@ -166,13 +192,18 @@ export class SearchEffects {
             concatLatestFrom(() => [
                 this.store.select(datasetSelector.selectDatasetNameByRoute),
                 this.store.select(searchSelector.selectCriteriaList),
+                this.store.select(coneSearchSelector.selectConeSearch),
                 this.store.select(searchSelector.selectOutputList)
             ]),
-            mergeMap(([action, datasetName, criteriaList, outputList]) => {
+            mergeMap(([action, datasetName, criteriaList, coneSearch, outputList]) => {
                 let query = datasetName + '?a=' + outputList.join(';');
                 if (criteriaList.length > 0) {
                     query += '&c=' + criteriaList.map(criterion => criterionToString(criterion)).join(';');
                 }
+                if (coneSearch) {
+                    query += '&cs=' + coneSearch.ra + ':' + coneSearch.dec + ':' + coneSearch.radius;
+                }
+
                 query += '&p=' + action.pagination.nbItems + ':' + action.pagination.page;
                 query += '&o=' + action.pagination.sortedCol + ':' + action.pagination.order;
 
diff --git a/client/src/app/instance/store/reducers/cone-search.reducer.ts b/client/src/app/instance/store/reducers/cone-search.reducer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6a4ee35ce53cc7f5271515cf2811850994e04353
--- /dev/null
+++ b/client/src/app/instance/store/reducers/cone-search.reducer.ts
@@ -0,0 +1,59 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { createReducer, on } from '@ngrx/store';
+
+import * as coneSearchActions from '../actions/cone-search.actions';
+import { ConeSearch, Resolver } from '../models';
+
+export interface State {
+    coneSearch: ConeSearch;
+    resolver: Resolver;
+    resolverIsLoading: boolean;
+    resolverIsLoaded: boolean;
+}
+
+export const initialState: State = {
+    coneSearch: null,
+    resolver: null,
+    resolverIsLoading: false,
+    resolverIsLoaded: false
+}
+
+export const coneSearchReducer = createReducer(
+    initialState,
+    on(coneSearchActions.addConeSearch, (state, { coneSearch }) => ({
+        ...state,
+        coneSearch
+    })),
+    on(coneSearchActions.deleteConeSearch, state => ({
+        ...state,
+        coneSearch: null
+    })),
+    on(coneSearchActions.retrieveCoordinates, state => ({
+        ...state,
+        resolverIsLoading: true,
+        resolverIsLoaded: false
+    })),
+    on(coneSearchActions.retrieveCoordinatesSuccess, (state, { resolver }) => ({
+        ...state,
+        resolver,
+        resolverIsLoading: false,
+        resolverIsLoaded: true
+    })),
+    on(coneSearchActions.retrieveCoordinatesFail, state => ({
+        ...state,
+        resolverIsLoading: false
+    }))
+);
+
+export const selectConeSearch = (state: State) => state.coneSearch;
+export const selectResolver = (state: State) => state.resolver;
+export const selectResolverIsLoading = (state: State) => state.resolverIsLoading;
+export const selectResolverIsLoaded = (state: State) => state.resolverIsLoaded;
diff --git a/client/src/app/instance/store/selectors/cone-search.selector.ts b/client/src/app/instance/store/selectors/cone-search.selector.ts
new file mode 100644
index 0000000000000000000000000000000000000000..695bba185eacc01db90b4dfface55f691ee3d3c7
--- /dev/null
+++ b/client/src/app/instance/store/selectors/cone-search.selector.ts
@@ -0,0 +1,43 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { createSelector } from '@ngrx/store';
+
+import * as reducer from '../../instance.reducer';
+import * as fromConeSearch from '../reducers/cone-search.reducer';
+
+export const selectConeSearchState = createSelector(
+    reducer.getInstanceState,
+    (state: reducer.State) => state.coneSearch
+);
+
+export const selectConeSearch = createSelector(
+    selectConeSearchState,
+    fromConeSearch.selectConeSearch
+);
+
+export const selectResolver = createSelector(
+    selectConeSearchState,
+    fromConeSearch.selectResolver
+);
+
+export const selectResolverIsLoading = createSelector(
+    selectConeSearchState,
+    fromConeSearch.selectResolverIsLoading
+);
+
+export const selectResolverIsLoaded = createSelector(
+    selectConeSearchState,
+    fromConeSearch.selectResolverIsLoaded
+);
+
+export const selectConeSearchByRoute = createSelector(
+    reducer.selectRouterState,
+    router => router.state.queryParams.cs as string
+);
diff --git a/client/src/app/instance/store/selectors/search.selector.ts b/client/src/app/instance/store/selectors/search.selector.ts
index ee70032ca896242b28fe17f59bd61982c7159f74..094c36733e1f0aed698df8503b56aaf91977b642 100644
--- a/client/src/app/instance/store/selectors/search.selector.ts
+++ b/client/src/app/instance/store/selectors/search.selector.ts
@@ -9,9 +9,10 @@
 
 import { createSelector } from '@ngrx/store';
 
-import { Criterion, SearchQueryParams, criterionToString } from '../models';
+import { Criterion, SearchQueryParams, criterionToString, ConeSearch } from '../models';
 import * as reducer from '../../instance.reducer';
 import * as fromSearch from '../reducers/search.reducer';
+import * as coneSearchSelector from './cone-search.selector';
 
 export const selectInstanceState = createSelector(
     reducer.getInstanceState,
@@ -100,12 +101,14 @@ export const selectSelectedData = createSelector(
 
 export const selectQueryParams = createSelector(
     selectCriteriaList,
+    coneSearchSelector.selectConeSearch,
     selectOutputList,
     selectCriteriaStepChecked,
     selectOutputStepChecked,
     selectResultStepChecked,
     (
         criteriaList: Criterion[],
+        coneSearch: ConeSearch,
         outputList: number[],
         criteriaStepChecked: boolean,
         outputStepChecked: boolean,
@@ -118,6 +121,12 @@ export const selectQueryParams = createSelector(
             s: step,
             a: outputList.join(';')
         };
+        if (coneSearch) {
+            queryParams = {
+                ...queryParams,
+                cs: coneSearch.ra + ':' + coneSearch.dec + ':' + coneSearch.radius
+            };
+        }
         if (criteriaList.length > 0) {
             queryParams = {
                 ...queryParams,
diff --git a/client/src/app/instance/store/services/cone-search.service.ts b/client/src/app/instance/store/services/cone-search.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..37c3420e5f1af5b426de2cf6bc6c8885e152f8bb
--- /dev/null
+++ b/client/src/app/instance/store/services/cone-search.service.ts
@@ -0,0 +1,33 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable } from 'rxjs';
+
+@Injectable()
+/**
+ * @class
+ * @classdesc Cone search service.
+ */
+export class ConeSearchService {
+    constructor(private http: HttpClient) { }
+
+    /**
+     * Retrieves coordinates of an object name.
+     *
+     * @param  {string} name - The name of the object.
+     *
+     * @return Observable<any>
+     */
+    retrieveCoordinates(name: string): Observable<any> {
+        const url = 'https://cdsweb.u-strasbg.fr/cgi-bin/nph-sesame/-ox/NSV?' + name;
+        return this.http.get(url, { responseType: 'text' });
+    }
+}
diff --git a/client/src/app/instance/store/services/index.ts b/client/src/app/instance/store/services/index.ts
index 136f9cb320ff0395ea365076e1f7753d31f9f680..4707c60a165f5e0b28a886c148854579537703d5 100644
--- a/client/src/app/instance/store/services/index.ts
+++ b/client/src/app/instance/store/services/index.ts
@@ -1,7 +1,9 @@
 import { SearchService } from './search.service';
 import { SampService } from './samp.service';
+import { ConeSearchService } from './cone-search.service';
 
 export const instanceServices = [
     SearchService,
-    SampService
+    SampService,
+    ConeSearchService
 ];
diff --git a/server/src/Search/Query/ConeSearch.php b/server/src/Search/Query/ConeSearch.php
index f229f130e1a0d35ecb4a4179a9fc2160507bec29..4d4cee16257e82b9b412a6507e67c444f2aaa1a4 100644
--- a/server/src/Search/Query/ConeSearch.php
+++ b/server/src/Search/Query/ConeSearch.php
@@ -45,12 +45,12 @@ class ConeSearch extends AbstractQueryPart
             $radius = floatval($radius);
             $coneSearchConfig = $dataset->getConfig()['cone_search'];
 
-            if ($coneSearchConfig['enabled'] !== true) {
+            if ($coneSearchConfig['cone_search_enabled'] !== true) {
                 throw SearchQueryException::coneSearchUnavailable();
             }
 
-            $attributeRa = $this->getAttribute($dataset, $coneSearchConfig['column_ra']);
-            $attributeDec = $this->getAttribute($dataset, $coneSearchConfig['column_dec']);
+            $attributeRa = $this->getAttribute($dataset, $coneSearchConfig['cone_search_column_ra']);
+            $attributeDec = $this->getAttribute($dataset, $coneSearchConfig['cone_search_column_dec']);
             $columnRa = $dataset->getTableRef() . '.' . $attributeRa->getName();
             $columnDec = $dataset->getTableRef() . '.' . $attributeDec->getName();