You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by md...@apache.org on 2020/02/05 22:40:35 UTC

[syncope] branch 2_1_X updated: [SYNCOPE-1538] Replaced DropDown with a search field

This is an automated email from the ASF dual-hosted git repository.

mdisabatino pushed a commit to branch 2_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/2_1_X by this push:
     new b553278  [SYNCOPE-1538] Replaced DropDown with a search field
b553278 is described below

commit b55327827004d7ab2a0d75d19315206bc738d803
Author: Marco Di Sabatino Di Diodoro <ma...@tirasa.net>
AuthorDate: Wed Feb 5 23:40:11 2020 +0100

    [SYNCOPE-1538] Replaced DropDown with a search field
---
 .../client/console/commons/RealmsUtils.java        |  51 ++++++
 .../client/console/panels/RealmChoicePanel.java    | 176 ++++++++++++++-------
 .../client/console/rest/RealmRestClient.java       |   8 +-
 .../client/console/status/ReconTaskPanel.java      |  35 +++-
 .../console/tasks/SchedTaskWizardBuilder.java      |  66 ++++++--
 .../syncope/client/console/topology/Topology.java  |  16 +-
 .../markup/html/WebMarkupContainerNoVeil.java      |  42 +++++
 .../markup/html/form/AjaxSearchFieldPanel.java     | 133 ++++++++++++++++
 .../client/console/wizards/any/Details.java        |  53 +++++--
 .../wizards/resources/ConnectorDetailsPanel.java   |  45 +++++-
 .../META-INF/resources/css/syncopeConsole.css      |  19 +--
 .../client/console/panels/RealmChoicePanel.html    |  11 +-
 .../console/panels/RealmChoicePanel.properties     |  17 ++
 .../panels/RealmChoicePanel_fr_CA.properties       |  17 ++
 .../console/panels/RealmChoicePanel_it.properties  |  17 ++
 .../console/panels/RealmChoicePanel_ja.properties  |  17 ++
 .../panels/RealmChoicePanel_pt_BR.properties       |  17 ++
 .../console/panels/RealmChoicePanel_ru.properties  |  17 ++
 .../markup/html/form/AjaxCharacterFieldPanel.html  |   4 +-
 ...erFieldPanel.html => AjaxSearchFieldPanel.html} |   1 -
 .../client/console/wizards/any/Details.html        |   8 +-
 21 files changed, 631 insertions(+), 139 deletions(-)

diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/RealmsUtils.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/RealmsUtils.java
new file mode 100644
index 0000000..2564012
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/RealmsUtils.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.rest.RealmRestClient;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.rest.api.beans.RealmQuery;
+
+public final class RealmsUtils {
+
+    public static final int REALMS_VIEW_SIZE = 20;
+    
+    private RealmsUtils() {
+        // private constructor for static utility class
+    }
+
+    public static boolean enableSearchRealm() {
+        return new RealmRestClient().search(
+                new RealmQuery.Builder().keyword(
+                        SyncopeConsoleSession.get().getAuthRealms().contains(SyncopeConstants.ROOT_REALM)
+                        ? SyncopeConstants.ROOT_REALM
+                        : SyncopeConsoleSession.get().getAuthRealms().iterator().next()).build()).
+                getTotalCount() > REALMS_VIEW_SIZE;
+    }
+
+    public static boolean checkInput(final String input) {
+        return StringUtils.isNotBlank(input) && !"*".equals(input);
+    }
+
+    public static RealmQuery buildQuery(final String input) {
+        return new RealmQuery.Builder().keyword(input.contains("*") ? input : "*" + input + "*").build();
+    }
+}
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
index a20fbfd..1bac74f 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
@@ -25,14 +25,12 @@ import de.agilecoders.wicket.core.markup.html.bootstrap.button.Buttons;
 import de.agilecoders.wicket.core.markup.html.bootstrap.button.dropdown.DropDownButton;
 import de.agilecoders.wicket.core.markup.html.bootstrap.image.GlyphIconType;
 import de.agilecoders.wicket.core.markup.html.bootstrap.image.IconType;
-import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.select.BootstrapSelect;
-import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.select.BootstrapSelectConfig;
-import de.agilecoders.wicket.jquery.Key;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -41,33 +39,39 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.RealmsUtils;
 import org.apache.syncope.client.console.rest.RealmRestClient;
+import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.console.wicket.markup.html.WebMarkupContainerNoVeil;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.DynRealmTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.common.rest.api.beans.RealmQuery;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AbstractAutoCompleteRenderer;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteBehavior;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.IAutoCompleteRenderer;
 import org.apache.wicket.markup.ComponentTag;
-import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.IChoiceRenderer;
 import org.apache.wicket.markup.html.link.AbstractLink;
 import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.request.Response;
 
 public class RealmChoicePanel extends Panel {
 
     private static final long serialVersionUID = -1100228004207271270L;
 
-    private static final int REALMS_VIEW_SIZE = 15;
+    private static final String SEARCH_REALMS = "searchRealms";
 
     private final RealmRestClient realmRestClient = new RealmRestClient();
 
@@ -77,7 +81,7 @@ public class RealmChoicePanel extends Panel {
 
     private final LoadableDetachableModel<List<DynRealmTO>> dynRealmTree;
 
-    private final WebMarkupContainer container;
+    private final WebMarkupContainerNoVeil container;
 
     private Model<RealmTO> model;
 
@@ -87,11 +91,18 @@ public class RealmChoicePanel extends Panel {
 
     private final List<AbstractLink> links = new ArrayList<>();
 
+    private String searchQuery;
+
+    private List<RealmTO> realmsChoices;
+
+    private boolean isSearchEnabled;
+
     public RealmChoicePanel(final String id, final PageReference pageRef) {
         super(id);
         this.pageRef = pageRef;
         availableRealms = SyncopeConsoleSession.get().getAuthRealms();
         tree = new HashMap<>();
+        isSearchEnabled = RealmsUtils.enableSearchRealm();
 
         realmTree = new LoadableDetachableModel<List<Pair<String, RealmTO>>>() {
 
@@ -114,9 +125,14 @@ public class RealmChoicePanel extends Panel {
 
             @Override
             protected List<Pair<String, RealmTO>> load() {
-                Map<String, Pair<RealmTO, List<RealmTO>>> map = reloadRealmParentMap();
+                Map<String, Pair<RealmTO, List<RealmTO>>> map = reloadRealmParentMap(isSearchEnabled);
                 List<Pair<String, RealmTO>> full = new ArrayList<>();
-                getChildren(full, null, map, StringUtils.EMPTY);
+                if (isSearchEnabled) {
+                    full = map.entrySet().stream().map(
+                            el -> Pair.of(el.getKey(), el.getValue().getKey())).collect(Collectors.toList());
+                } else {
+                    getChildren(full, null, map, StringUtils.EMPTY);
+                }
                 return full.stream().filter(realm -> availableRealms.stream().anyMatch(
                         availableRealm -> realm.getValue().getFullPath().startsWith(availableRealm))).
                         collect(Collectors.toList());
@@ -146,8 +162,13 @@ public class RealmChoicePanel extends Panel {
             }
         };
 
-        model = Model.of(realmTree.getObject().stream().findFirst().get().getValue());
-        container = new WebMarkupContainer("container", realmTree);
+        RealmTO realmTO = realmRestClient.search(
+                new RealmQuery.Builder().keyword("*" + availableRealms.stream().findFirst().get() + "*").build()).
+                getResult().stream().findFirst().get();
+
+        model = Model.of(realmTO);
+        searchQuery = realmTO.getName();
+        container = new WebMarkupContainerNoVeil("container", realmTree);
         container.setOutputMarkupId(true);
         add(container);
         reloadRealmTree();
@@ -169,63 +190,71 @@ public class RealmChoicePanel extends Panel {
         label.setOutputMarkupId(true);
         container.addOrReplace(label);
 
-        if ((realmTree.getObject().size() + dynRealmTree.getObject().size()) > REALMS_VIEW_SIZE) {
-            List<Pair<String, RealmTO>> realms = Stream.of(
-                    realmTree.getObject(),
-                    dynRealmTree.getObject().stream().map(
-                            item -> {
-                                final RealmTO realmTO = new RealmTO();
-                                realmTO.setKey(item.getKey());
-                                realmTO.setName(item.getKey());
-                                realmTO.setFullPath(item.getKey());
-                                return Pair.of(item.getKey(), realmTO);
-                            }).collect(Collectors.toList())).flatMap(Collection::stream).collect(Collectors.toList());
-
-            BootstrapSelectConfig config = new BootstrapSelectConfig().withLiveSearch(true);
-            config.put(new Key<>("styleBase", "btn"), "btn glyphicon glyphicon-folder-open");
-            BootstrapSelect<Pair<String, RealmTO>> select =
-                    new BootstrapSelect<>("realmsLiveSearch", new Model<>(), realms);
-            select.with(config);
-            select.setOutputMarkupId(true);
-            select.setChoiceRenderer(new IChoiceRenderer<Pair<String, RealmTO>>() {
-
-                private static final long serialVersionUID = 5978544741356774985L;
+        if (isSearchEnabled) {
+            realmsChoices = buildRealmChoices();
+            final AutoCompleteSettings settings = new AutoCompleteSettings();
+            settings.setShowCompleteListOnFocusGain(false);
+            settings.setShowListOnEmptyInput(false);
 
-                @Override
-                public Object getDisplayValue(final Pair<String, RealmTO> object) {
-                    return object.getKey();
-                }
+            final AutoCompleteTextField<String> searchRealms =
+                    new AutoCompleteTextField<String>(SEARCH_REALMS, new Model<String>(), settings) {
+
+                private static final long serialVersionUID = -6635259975264955783L;
 
                 @Override
-                public String getIdValue(final Pair<String, RealmTO> object, final int index) {
-                    return object.getKey();
+                protected Iterator<String> getChoices(final String input) {
+                    searchQuery = input;
+                    realmsChoices = RealmsUtils.checkInput(input)
+                            ? buildRealmChoices()
+                            : Collections.<RealmTO>emptyList();
+                    return realmsChoices.stream().
+                            map(item -> item.getFullPath()).sorted().collect(Collectors.toList()).iterator();
                 }
 
                 @Override
-                public Pair<String, RealmTO> getObject(final String id,
-                        final IModel<? extends List<? extends Pair<String, RealmTO>>> choices) {
-
-                    return choices.getObject().stream().
-                            filter(object -> object.getKey().equals(id)).findFirst().orElse(null);
+                protected AutoCompleteBehavior<String> newAutoCompleteBehavior(
+                        final IAutoCompleteRenderer<String> renderer,
+                        final AutoCompleteSettings settings) {
+                    return super.newAutoCompleteBehavior(new AbstractAutoCompleteRenderer<String>() {
+
+                        private static final long serialVersionUID = -4789925973199139157L;
+
+                        @Override
+                        protected void renderChoice(
+                                final String object,
+                                final Response response,
+                                final String criteria) {
+                            response.write(object);
+                        }
+
+                        @Override
+                        protected String getTextValue(final String object) {
+                            return object;
+                        }
+                    }, settings);
                 }
-            });
-            select.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+            };
+
+            searchRealms.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
 
                 private static final long serialVersionUID = -6139318907146065915L;
 
                 @Override
                 protected void onUpdate(final AjaxRequestTarget target) {
-                    model.setObject(select.getModelObject().getValue());
-                    label.setDefaultModelObject(model.getObject().getFullPath());
-                    realmLabel.setDefaultModel(new ResourceModel("realmLabel", "Realm"));
-                    target.add(label);
-                    send(pageRef.getPage(), Broadcast.EXACT,
-                            new ChosenRealm<>(select.getModelObject().getValue(), target));
+                    realmsChoices.stream().filter(
+                            item -> item.getFullPath().equals(searchRealms.getModelObject())).
+                            findFirst().ifPresent(realm -> {
+                                model.setObject(realm);
+                                label.setDefaultModelObject(model.getObject().getFullPath());
+                                realmLabel.setDefaultModel(new ResourceModel("realmLabel", "Realm"));
+                                target.add(label);
+                                send(pageRef.getPage(), Broadcast.EXACT, new ChosenRealm<>(realm, target));
+                            });
                 }
             });
-            buildRealmLinks(label, realmLabel);
+
             Fragment fragment = new Fragment("realmsFragment", "realmsSearchFragment", container);
-            fragment.addOrReplace(select);
+            fragment.addOrReplace(searchRealms);
             container.addOrReplace(fragment);
         } else {
             final DropDownButton realms = new DropDownButton(
@@ -362,15 +391,26 @@ public class RealmChoicePanel extends Panel {
         return this;
     }
 
-    private Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap() {
-        return reloadRealmParentMap(realmRestClient.list().stream().
+    private Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap(final boolean enableSearch) {
+        List<RealmTO> realmsToList = enableSearch
+                ? realmRestClient.search(new RealmQuery.Builder().
+                        keyword(searchQuery.contains("*")
+                                ? searchQuery
+                                : "*" + searchQuery + "*").build()).getResult()
+                : realmRestClient.list();
+
+        return reloadRealmParentMap(realmsToList.stream().
                 sorted(Comparator.comparing(RealmTO::getName)).
-                collect(Collectors.toList()));
+                collect(Collectors.toList()), enableSearch);
     }
 
-    private Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap(final List<RealmTO> realms) {
+    private Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap(
+            final List<RealmTO> realms,
+            final boolean enableSearch) {
         tree.clear();
-        tree.put(null, Pair.<RealmTO, List<RealmTO>>of(realms.get(0), new ArrayList<>()));
+        if (!enableSearch) {
+            tree.put(null, Pair.<RealmTO, List<RealmTO>>of(realms.get(0), new ArrayList<>()));
+        }
 
         final Map<String, List<RealmTO>> cache = new HashMap<>();
 
@@ -391,10 +431,23 @@ public class RealmChoicePanel extends Panel {
                 cache.put(realm.getParent(), new ArrayList<>(Collections.singleton(realm)));
             }
         });
-
         return tree;
     }
 
+    private List<RealmTO> buildRealmChoices() {
+        return Stream.of(
+                realmTree.getObject().stream().map(item -> item.getValue()).collect(Collectors.toList()),
+                dynRealmTree.getObject().stream().map(
+                        item -> {
+                            final RealmTO realmTO = new RealmTO();
+                            realmTO.setKey(item.getKey());
+                            realmTO.setName(item.getKey());
+                            realmTO.setFullPath(item.getKey());
+                            return realmTO;
+                        }).collect(Collectors.toList())).flatMap(Collection::stream).
+                collect(Collectors.toList());
+    }
+
     /**
      * Gets current selected realm.
      *
@@ -418,6 +471,7 @@ public class RealmChoicePanel extends Panel {
             }
         }
         return null;
+
     }
 
     public static class ChosenRealm<T> {
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
index 6a96b20..25a7cac 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
@@ -23,8 +23,10 @@ import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.DynRealmTO;
+import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.rest.api.beans.RealmQuery;
 import org.apache.syncope.common.rest.api.service.DynRealmService;
 import org.apache.syncope.common.rest.api.service.RealmService;
 
@@ -34,7 +36,11 @@ import org.apache.syncope.common.rest.api.service.RealmService;
 public class RealmRestClient extends BaseRestClient {
 
     private static final long serialVersionUID = -8549081557283519638L;
-
+    
+    public PagedResult<RealmTO> search(final RealmQuery query) {
+        return getService(RealmService.class).search(query);
+    }
+    
     public List<RealmTO> list() {
         return getService(RealmService.class).list(SyncopeConstants.ROOT_REALM);
     }
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java
index 3ba1a8a..261edba 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java
@@ -19,11 +19,14 @@
 package org.apache.syncope.client.console.status;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Comparator;
+import java.util.Iterator;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.RealmsUtils;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
@@ -32,6 +35,7 @@ import org.apache.syncope.client.console.rest.ReconciliationRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSearchFieldPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ProvisioningTaskTO;
@@ -45,6 +49,7 @@ import org.apache.syncope.common.rest.api.beans.ReconQuery;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.model.CompoundPropertyModel;
@@ -116,8 +121,29 @@ public class ReconTaskPanel extends MultilevelPanel.SecondLevel {
         if (taskTO instanceof PushTaskTO) {
             form.add(new Label("realm", ""));
         } else {
-            AjaxDropDownChoicePanel<String> realm = new AjaxDropDownChoicePanel<>(
-                    "realm", "destinationRealm", new PropertyModel<>(taskTO, "destinationRealm"), false);
+            boolean isSearchEnabled = RealmsUtils.enableSearchRealm();
+            final AutoCompleteSettings settings = new AutoCompleteSettings();
+            settings.setShowCompleteListOnFocusGain(!isSearchEnabled);
+            settings.setShowListOnEmptyInput(!isSearchEnabled);
+
+            final AjaxSearchFieldPanel realm =
+                    new AjaxSearchFieldPanel("realm", "destinationRealm",
+                            new PropertyModel<String>(taskTO, "destinationRealm"), settings) {
+
+                private static final long serialVersionUID = -6390474600233486704L;
+
+                @Override
+                protected Iterator<String> getChoices(final String input) {
+                    return (RealmsUtils.checkInput(input)
+                            ? (isSearchEnabled
+                                    ? realmRestClient.search(RealmsUtils.buildQuery(input)).getResult()
+                                    : realmRestClient.list())
+                            : Collections.<RealmTO>emptyList()).stream().
+                            sorted(Comparator.comparing(RealmTO::getName)).
+                            map(RealmTO::getFullPath).collect(Collectors.toList()).iterator();
+                }
+            };
+
             form.add(realm);
             realm.addRequiredLabel();
             realm.setOutputMarkupId(true);
@@ -125,11 +151,6 @@ public class ReconTaskPanel extends MultilevelPanel.SecondLevel {
             if (isOnSyncope) {
                 realm.getField().setModelObject(SyncopeConstants.ROOT_REALM);
                 realm.setVisible(false);
-            } else {
-                realm.setChoices(realmRestClient.list().stream().
-                        sorted(Comparator.comparing(RealmTO::getName)).
-                        map(RealmTO::getFullPath).
-                        collect(Collectors.toList()));
             }
         }
 
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
index a23f39b..3e4dab0 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
@@ -21,9 +21,11 @@ package org.apache.syncope.client.console.tasks;
 import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.RealmsUtils;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.RealmRestClient;
 import org.apache.syncope.client.console.rest.TaskRestClient;
@@ -31,6 +33,7 @@ import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormCompo
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSearchFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
 import org.apache.syncope.common.lib.to.EntityTO;
@@ -46,6 +49,7 @@ import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
 import org.apache.wicket.extensions.wizard.WizardModel;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -60,6 +64,8 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
 
     private final TaskRestClient taskRestClient = new TaskRestClient();
 
+    private final RealmRestClient realmRestClient = new RealmRestClient();
+
     private final ImplementationRestClient implRestClient = new ImplementationRestClient();
 
     private final TaskType type;
@@ -68,17 +74,17 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
 
     private CrontabPanel crontabPanel;
 
+    private String realmQuery;
+
+    private boolean isSearchEnabled;
+
     private final LoadableDetachableModel<List<String>> realms = new LoadableDetachableModel<List<String>>() {
 
         private static final long serialVersionUID = 5275935387613157437L;
 
         @Override
         protected List<String> load() {
-            List<String> result = new RealmRestClient().list().stream().
-                    map(RealmTO::getFullPath).collect(Collectors.toList());
-            Collections.sort(result);
-
-            return result;
+            return searchRealms().stream().map(RealmTO::getFullPath).sorted().collect(Collectors.toList());
         }
     };
 
@@ -113,6 +119,12 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
         return wizardModel;
     }
 
+    private List<RealmTO> searchRealms() {
+        return isSearchEnabled
+                ? realmRestClient.search(RealmsUtils.buildQuery(realmQuery)).getResult()
+                : realmRestClient.list();
+    }
+
     public class Profile extends WizardStep {
 
         private static final long serialVersionUID = -3043839139187792810L;
@@ -162,6 +174,7 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
         };
 
         public Profile(final SchedTaskTO taskTO) {
+            isSearchEnabled = RealmsUtils.enableSearchRealm();
             AjaxTextFieldPanel name = new AjaxTextFieldPanel("name", "name", new PropertyModel<>(taskTO, "name"),
                     false);
             name.addRequiredLabel();
@@ -230,14 +243,28 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
                 }
             });
 
-            AjaxDropDownChoicePanel<String> destinationRealm = new AjaxDropDownChoicePanel<>(
-                    "destinationRealm", "destinationRealm",
-                    new PropertyModel<String>(taskTO, "destinationRealm"), false).
-                    setChoices(realms);
+            final AutoCompleteSettings settings = new AutoCompleteSettings();
+            settings.setShowCompleteListOnFocusGain(!isSearchEnabled);
+            settings.setShowListOnEmptyInput(!isSearchEnabled);
+
+            final AjaxSearchFieldPanel destinationRealm =
+                    new AjaxSearchFieldPanel("destinationRealm", "destinationRealm",
+                            new PropertyModel<String>(taskTO, "destinationRealm"), settings) {
+
+                private static final long serialVersionUID = -6390474600233486704L;
+
+                @Override
+                protected Iterator<String> getChoices(final String input) {
+                    realmQuery = input;
+                    return (RealmsUtils.checkInput(input)
+                            ? searchRealms().stream().map(RealmTO::getFullPath).collect(Collectors.toList())
+                            : Collections.<String>emptyList()).iterator();
+                }
+            };
+
             if (taskTO instanceof PullTaskTO) {
                 destinationRealm.addRequiredLabel();
             }
-            destinationRealm.setNullValid(!(taskTO instanceof PullTaskTO));
             pullTaskSpecifics.add(destinationRealm);
 
             AjaxCheckBoxPanel remediation = new AjaxCheckBoxPanel(
@@ -254,14 +281,23 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
                 pushTaskSpecifics.setEnabled(false).setVisible(false);
             }
 
-            AjaxDropDownChoicePanel<String> sourceRealm = new AjaxDropDownChoicePanel<>(
-                    "sourceRealm", "sourceRealm",
-                    new PropertyModel<String>(taskTO, "sourceRealm"), false).
-                    setChoices(realms);
+            final AjaxSearchFieldPanel sourceRealm = new AjaxSearchFieldPanel("sourceRealm", "sourceRealm",
+                    new PropertyModel<String>(taskTO, "sourceRealm"), settings) {
+
+                private static final long serialVersionUID = -6390474600233486704L;
+
+                @Override
+                protected Iterator<String> getChoices(final String input) {
+                    realmQuery = input;
+                    return (RealmsUtils.checkInput(input)
+                            ? searchRealms().stream().map(RealmTO::getFullPath).collect(Collectors.toList())
+                            : Collections.<String>emptyList()).iterator();
+                }
+            };
+
             if (taskTO instanceof PushTaskTO) {
                 sourceRealm.addRequiredLabel();
             }
-            sourceRealm.setNullValid(!(taskTO instanceof PushTaskTO));
             pushTaskSpecifics.add(sourceRealm);
 
             // ------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java b/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
index b586966..29b4c35 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
@@ -40,6 +40,7 @@ import org.apache.syncope.client.console.wizards.resources.AbstractResourceWizar
 import org.apache.syncope.client.console.rest.BaseRestClient;
 import org.apache.syncope.client.console.rest.ConnectorRestClient;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.WebMarkupContainerNoVeil;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
@@ -51,7 +52,6 @@ import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
 import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.IAjaxIndicatorAware;
 import org.apache.wicket.behavior.Behavior;
 import org.apache.wicket.event.IEvent;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
@@ -609,18 +609,4 @@ public class Topology extends BasePage {
                     resourceCreateEvent.getKind()));
         }
     }
-
-    private static class WebMarkupContainerNoVeil extends WebMarkupContainer implements IAjaxIndicatorAware {
-
-        private static final long serialVersionUID = 6883930486048460708L;
-
-        WebMarkupContainerNoVeil(final String id) {
-            super(id);
-        }
-
-        @Override
-        public String getAjaxIndicatorMarkupId() {
-            return StringUtils.EMPTY;
-        }
-    }
 }
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/WebMarkupContainerNoVeil.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/WebMarkupContainerNoVeil.java
new file mode 100644
index 0000000..9faf87e
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/WebMarkupContainerNoVeil.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.wicket.markup.html;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.wicket.ajax.IAjaxIndicatorAware;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.IModel;
+
+public class WebMarkupContainerNoVeil extends WebMarkupContainer implements IAjaxIndicatorAware {
+
+    private static final long serialVersionUID = 6883930486048460708L;
+
+    public WebMarkupContainerNoVeil(final String id) {
+        super(id);
+    }
+
+    public WebMarkupContainerNoVeil(final String id, final IModel<?> model) {
+        super(id, model);
+    }
+
+    @Override
+    public String getAjaxIndicatorMarkupId() {
+        return StringUtils.EMPTY;
+    }
+}
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxSearchFieldPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxSearchFieldPanel.java
new file mode 100644
index 0000000..a6943af
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxSearchFieldPanel.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.wicket.markup.html.form;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAutoCompleteBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteBehavior;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.IAutoCompleteRenderer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.validation.IValidator;
+
+public class AjaxSearchFieldPanel extends FieldPanel<String> implements Cloneable {
+
+    private static final long serialVersionUID = 6890905510177974519L;
+
+    private List<String> choices = Collections.emptyList();
+
+    private final IAutoCompleteRenderer<String> renderer;
+
+    private final AutoCompleteSettings settings;
+
+    public AjaxSearchFieldPanel(final String id, final String name, final IModel<String> model) {
+        this(id, name, model, null, null);
+    }
+
+    public AjaxSearchFieldPanel(
+            final String id, final String name,
+            final IModel<String> model,
+            final AutoCompleteSettings settings) {
+        this(id, name, model, null, settings);
+    }
+
+    public AjaxSearchFieldPanel(
+            final String id, final String name,
+            final IModel<String> model,
+            final IAutoCompleteRenderer<String> renderer,
+            final AutoCompleteSettings settings) {
+        super(id, name, model);
+
+        this.settings = settings;
+        this.renderer = renderer;
+
+        field = new AutoCompleteTextField<String>("textField", model, settings) {
+
+            private static final long serialVersionUID = -6648767303091874219L;
+
+            @Override
+            protected Iterator<String> getChoices(final String input) {
+                return AjaxSearchFieldPanel.this.getChoices(input);
+            }
+
+            @Override
+            protected AutoCompleteBehavior<String> newAutoCompleteBehavior(
+                    final IAutoCompleteRenderer<String> renderer, final AutoCompleteSettings settings) {
+
+                return new IndicatorAutoCompleteBehavior<String>(
+                        AjaxSearchFieldPanel.this.renderer != null ? AjaxSearchFieldPanel.this.renderer : renderer,
+                        AjaxSearchFieldPanel.this.settings != null ? AjaxSearchFieldPanel.this.settings : settings) {
+
+                    private static final long serialVersionUID = 1070808433195962931L;
+
+                    @Override
+                    protected Iterator<String> getChoices(final String input) {
+                        return AjaxSearchFieldPanel.this.getChoices(input);
+                    }
+                };
+            }
+        };
+        add(field.setLabel(new ResourceModel(name, name)).setOutputMarkupId(true));
+
+        if (!isReadOnly()) {
+            field.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = -6139318907146065915L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget target) {
+                    AjaxSearchFieldPanel.this.onUpdateBehavior();
+                }
+            });
+        }
+    }
+
+    @Override
+    public FieldPanel<String> setRequired(final boolean required) {
+        return super.setRequired(required);
+    }
+
+    public List<String> getChoices() {
+        return choices;
+    }
+
+    public void addValidator(final IValidator<String> validator) {
+        this.field.add(validator);
+    }
+
+    public void onUpdateBehavior() {
+    }
+
+    protected Iterator<String> getChoices(final String input) {
+        return choices.iterator();
+    }
+
+    @Override
+    public FieldPanel<String> clone() {
+        final AjaxSearchFieldPanel panel = (AjaxSearchFieldPanel) super.clone();
+        return panel;
+    }
+}
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
index 5016e7d..8d11492 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
@@ -19,18 +19,23 @@
 package org.apache.syncope.client.console.wizards.any;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.stream.Collectors;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.RealmsUtils;
 import org.apache.syncope.client.console.pages.Realms;
 import org.apache.syncope.client.console.rest.RealmRestClient;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSearchFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.model.PropertyModel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,6 +46,8 @@ public class Details<T extends AnyTO> extends WizardStep {
 
     protected static final Logger LOG = LoggerFactory.getLogger(Details.class);
 
+    private final RealmRestClient realmRestClient = new RealmRestClient();
+
     protected final PageReference pageRef;
 
     private final FieldPanel<String> realm;
@@ -52,27 +59,47 @@ public class Details<T extends AnyTO> extends WizardStep {
             final PageReference pageRef) {
 
         this.pageRef = pageRef;
-
+        final List<String> authRealms = SyncopeConsoleSession.get().getAuthRealms();
         final T inner = wrapper.getInnerObject();
-
+        final Fragment fragment;
+        
         if (templateMode) {
             realm = new AjaxTextFieldPanel(
                     "destinationRealm", "destinationRealm", new PropertyModel<>(inner, "realm"), false);
             AjaxTextFieldPanel.class.cast(realm).enableJexlHelp();
-        } else {
-            final List<RealmTO> realms = pageRef.getPage() instanceof Realms
-                    ? getRealmsFromLinks(Realms.class.cast(pageRef.getPage()).getRealmChoicePanel().getLinks())
-                    : new RealmRestClient().list();
+            fragment = new Fragment("realmsFragment", "realmsTemplateFragment", this);
 
-            realm = new AjaxDropDownChoicePanel<>(
-                    "destinationRealm", "destinationRealm", new PropertyModel<>(inner, "realm"), false);
-
-            ((AjaxDropDownChoicePanel<String>) realm).setChoices(
-                    realms.stream().map(RealmTO::getFullPath).collect(Collectors.toList()));
+        } else {
+            boolean isSearchEnabled = RealmsUtils.enableSearchRealm();
+            final AutoCompleteSettings settings = new AutoCompleteSettings();
+            settings.setShowCompleteListOnFocusGain(!isSearchEnabled);
+            settings.setShowListOnEmptyInput(!isSearchEnabled);
+
+            realm = new AjaxSearchFieldPanel("destinationRealm", "destinationRealm",
+                    new PropertyModel<>(inner, "realm"), settings) {
+
+                private static final long serialVersionUID = -6390474600233486704L;
+
+                @Override
+                protected Iterator<String> getChoices(final String input) {
+                    return (isSearchEnabled
+                            ? realmRestClient.search(RealmsUtils.buildQuery(input)).getResult()
+                            : pageRef.getPage() instanceof Realms
+                            ? getRealmsFromLinks(Realms.class.cast(pageRef.getPage()).getRealmChoicePanel().getLinks())
+                            : realmRestClient.list()).
+                            stream().filter(realm -> authRealms.stream().anyMatch(
+                            authRealm -> realm.getFullPath().startsWith(authRealm))).
+                            map(item -> item.getFullPath()).collect(Collectors.toList()).iterator();
+                }
+            };
+
+            fragment = new Fragment("realmsFragment", "realmsSearchFragment", this);
         }
-        add(realm);
+        fragment.addOrReplace(realm);
+        addOrReplace(fragment);
         add(getGeneralStatusInformation("generalStatusInformation", inner).
                 setEnabled(includeStatusPanel).setVisible(includeStatusPanel).setRenderBodyOnly(true));
+
     }
 
     public Details<T> disableRealmSpecification() {
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java
index d69b7d3..877b3aa 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java
@@ -19,13 +19,16 @@
 package org.apache.syncope.client.console.wizards.resources;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.RealmsUtils;
 import org.apache.syncope.client.console.rest.RealmRestClient;
 import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSearchFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.ConnBundleTO;
@@ -33,6 +36,7 @@ import org.apache.syncope.common.lib.to.ConnInstanceTO;
 import org.apache.syncope.common.lib.to.ConnPoolConfTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.form.DropDownChoice;
 import org.apache.wicket.model.LoadableDetachableModel;
@@ -42,6 +46,12 @@ public class ConnectorDetailsPanel extends WizardStep {
 
     private static final long serialVersionUID = -2435937897614232137L;
 
+    private final RealmRestClient realmRestClient = new RealmRestClient();
+
+    private String realmQuery;
+
+    private boolean isSearchEnabled;
+
     private final LoadableDetachableModel<List<String>> realms;
 
     public ConnectorDetailsPanel(final ConnInstanceTO connInstanceTO, final List<ConnBundleTO> bundles) {
@@ -49,13 +59,16 @@ public class ConnectorDetailsPanel extends WizardStep {
         setOutputMarkupId(true);
 
         final List<String> authRealms = SyncopeConsoleSession.get().getAuthRealms();
+        isSearchEnabled = RealmsUtils.enableSearchRealm();
+
         realms = new LoadableDetachableModel<List<String>>() {
 
             private static final long serialVersionUID = 5275935387613157437L;
 
             @Override
             protected List<String> load() {
-                return new RealmRestClient().list().stream().
+                List<RealmTO> realmList = searchRealms();
+                return realmList.stream().
                         filter(realm -> authRealms.stream().
                         anyMatch(authRealm -> realm.getFullPath().startsWith(authRealm))).
                         map(RealmTO::getFullPath).
@@ -64,9 +77,27 @@ public class ConnectorDetailsPanel extends WizardStep {
             }
         };
 
-        AjaxDropDownChoicePanel<String> realm = new AjaxDropDownChoicePanel<>(
-                "adminRealm", "adminRealm", new PropertyModel<>(connInstanceTO, "adminRealm"), false);
-        realm.setChoices(realms);
+        final AutoCompleteSettings settings = new AutoCompleteSettings();
+        settings.setShowCompleteListOnFocusGain(!isSearchEnabled);
+        settings.setShowListOnEmptyInput(!isSearchEnabled);
+
+        AjaxSearchFieldPanel realm = new AjaxSearchFieldPanel("adminRealm", "adminRealm",
+                new PropertyModel<>(connInstanceTO, "adminRealm"), settings) {
+
+            private static final long serialVersionUID = -6390474600233486704L;
+
+            @Override
+            protected Iterator<String> getChoices(final String input) {
+                realmQuery = input;
+                return (isSearchEnabled
+                        ? searchRealms()
+                        : realmRestClient.list()).
+                        stream().filter(realm -> authRealms.stream().anyMatch(
+                        authRealm -> realm.getFullPath().startsWith(authRealm))).
+                        map(item -> item.getFullPath()).collect(Collectors.toList()).iterator();
+            }
+        };
+
         realm.setOutputMarkupId(true);
         realm.addRequiredLabel();
         add(realm);
@@ -168,4 +199,10 @@ public class ConnectorDetailsPanel extends WizardStep {
                 && object.getBundleName().equals(connInstanceTO.getBundleName())).
                 map(ConnBundleTO::getVersion).collect(Collectors.toList());
     }
+
+    private List<RealmTO> searchRealms() {
+        return isSearchEnabled
+                ? realmRestClient.search(RealmsUtils.buildQuery(realmQuery)).getResult()
+                : realmRestClient.list();
+    }
 }
diff --git a/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css b/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css
index c1758ae..78bef15 100644
--- a/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css
+++ b/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css
@@ -1167,21 +1167,10 @@ div#tablehandling ul.menu li a {
   padding: 0px !important;
 }
 
-.realm-live-search .dropdown-menu li a {
-  height: 22px;
-}
-
-.realm-live-search #bs-select-1-0 {
-  display: none;
+.realm-choice #realm-choice-field {
+  padding-right: 20px;
 }
 
-.realm-live-search.dropdown.bootstrap-select .bs-caret {
-    display: none;
-}
-.realm-live-search.bootstrap-select>.dropdown-toggle {
-    width: 50px;
-    background: transparent;
-    border: none;
-    color: #3c8dbc;
-    float: right;
+.realm-choice #realm-choice-folder {
+  color: #3c8dbc;
 }
\ No newline at end of file
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html
index a6271bb..3d015ed 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html
@@ -20,13 +20,18 @@ under the License.
   <wicket:panel>
     <div wicket:id="container" class="realm-header">
       <div class="realm-label">
-        <label wicket:id="realmLabel"/>: <label wicket:id="realm"/>
+        <label wicket:id="realmLabel"/>: <label wicket:id="realm"/> 
       </div>
       <span wicket:id="realmsFragment"></span>
 
-      <wicket:fragment wicket:id="realmsSearchFragment">
+      <wicket:fragment wicket:id="realmsSearchFragment"> 
         <div class="realm-choice">
-          <select wicket:id="realmsLiveSearch" class="realm-live-search"></select> 
+          <div id="realm-choice-field" class="input-group">
+            <span class="input-group-addon"> 
+              <i id="realm-choice-folder" class="glyphicon glyphicon-folder-open"></i>
+            </span>
+            <input type="text" class="form-control" wicket:id="searchRealms" wicket:message="placeholder:search"/>
+          </div>
         </div>
       </wicket:fragment>
       <wicket:fragment wicket:id="realmsListFragment">
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.properties
new file mode 100644
index 0000000..ccd697f
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+search=Search
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_fr_CA.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_fr_CA.properties
new file mode 100644
index 0000000..60881c2
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_fr_CA.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+search=Recherche
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_it.properties
new file mode 100644
index 0000000..1522846
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_it.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+search=Cerca
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_ja.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_ja.properties
new file mode 100644
index 0000000..6c85ab8
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_ja.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+search=\u691c\u7d22
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_pt_BR.properties
new file mode 100644
index 0000000..0ead5fe
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_pt_BR.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+search=Pesquisa
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_ru.properties
new file mode 100644
index 0000000..2164746
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel_ru.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+search=\u041f\u043e\u0438\u0441\u043a \u0434\u043b\u044f
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCharacterFieldPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCharacterFieldPanel.html
index 2c1b7bb..e9123ef 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCharacterFieldPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCharacterFieldPanel.html
@@ -20,11 +20,9 @@ under the License.
   <wicket:extend>
     <wicket:enclosure child="field-label">
       <label wicket:id="field-label">[LABEL]</label><span wicket:id="required"/>
-      <span wicket:id="jexlInfo" class="glyphicon glyphicon-info-sign" style="cursor: pointer"></span>
-      <span wicket:id="externalAction"/>
     </wicket:enclosure>
     <fieldset class="input-group">
-      <input type="text" class="form-control" wicket:id="textField" placeholder=""/>
+      <input type="text" class="form-control" wicket:id="searchField" placeholder=""/>
     </fieldset>
   </wicket:extend>
 </html>
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCharacterFieldPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxSearchFieldPanel.html
similarity index 92%
copy from client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCharacterFieldPanel.html
copy to client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxSearchFieldPanel.html
index 2c1b7bb..78d702b 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCharacterFieldPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxSearchFieldPanel.html
@@ -20,7 +20,6 @@ under the License.
   <wicket:extend>
     <wicket:enclosure child="field-label">
       <label wicket:id="field-label">[LABEL]</label><span wicket:id="required"/>
-      <span wicket:id="jexlInfo" class="glyphicon glyphicon-info-sign" style="cursor: pointer"></span>
       <span wicket:id="externalAction"/>
     </wicket:enclosure>
     <fieldset class="input-group">
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Details.html b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Details.html
index a6773aa..aff6e32 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Details.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Details.html
@@ -20,7 +20,13 @@ under the License.
   <wicket:panel>
     <div class="details">
       <div class="form-group">
-        <span wicket:id="destinationRealm">[DESTINATION REALM]</span>
+        <span wicket:id="realmsFragment"></span>
+        <wicket:fragment wicket:id="realmsSearchFragment"> 
+          <span wicket:id="destinationRealm">[DESTINATION REALM]</span>
+        </wicket:fragment>
+        <wicket:fragment wicket:id="realmsTemplateFragment"> 
+          <span wicket:id="destinationRealm">[DESTINATION REALM]</span>
+        </wicket:fragment>
       </div>
       <wicket:child/>
     </div>