diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index c9a5ee2ce8580bbf847263b8aff2ac53c2eed2ae..57112ab4fb4a9afb80d78f264c62c02ead35602a 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -27,7 +27,7 @@ import 'ee/boards/models/list';
 import 'ee/boards/models/issue';
 import 'ee/boards/models/project';
 import BoardService from 'ee/boards/services/board_service';
-import BoardsSelector from 'ee/boards/components/boards_selector';
+import BoardsSelector from 'ee/boards/components/boards_selector.vue';
 import collapseIcon from 'ee/boards/icons/fullscreen_collapse.svg';
 import expandIcon from 'ee/boards/icons/fullscreen_expand.svg';
 import tooltip from '~/vue_shared/directives/tooltip';
@@ -356,11 +356,34 @@ export default () => {
     `,
   });
 
+  const boardsSwitcherElement = document.getElementById('js-multiple-boards-switcher');
   // eslint-disable-next-line no-new
   new Vue({
-    el: '#js-multiple-boards-switcher',
+    el: boardsSwitcherElement,
     components: {
       BoardsSelector,
     },
+    data() {
+      const { dataset } = boardsSwitcherElement;
+
+      const boardsSelectorProps = {
+        ...dataset,
+        currentBoard: JSON.parse(dataset.currentBoard),
+        hasMissingBoards: dataset.hasMissingBoards === 'true',
+        canAdminBoard: dataset.canAdminBoard === 'true',
+        multipleIssueBoardsAvailable: dataset.multipleIssueBoardsAvailable === 'true',
+        projectId: Number(dataset.projectId),
+        groupId: Number(dataset.groupId),
+        scopedIssueBoardFeatureEnabled: dataset.scopedIssueBoardFeatureEnabled === 'true',
+        weights: JSON.parse(dataset.weights),
+      };
+
+      return { boardsSelectorProps };
+    },
+    render(createElement) {
+      return createElement(BoardsSelector, {
+        props: this.boardsSelectorProps,
+      });
+    },
   });
 };
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 824bbe3524bd64e48c96645c5841ae097cdff33b..6939aba68964b31638c227844d16727a74e33afe 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -7,8 +7,7 @@
 .issues-filters
   .issues-details-filters.filtered-search-block{ class: block_css_class, "v-pre" => type == :boards_modal }
     - if type == :boards
-      #js-multiple-boards-switcher.inline.boards-switcher{ "v-cloak" => true }
-        = render_if_exists "shared/boards/switcher", board: board
+      = render_if_exists "shared/boards/switcher", board: board
     = form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form' do
       - if params[:search].present?
         = hidden_field_tag :search, params[:search]
diff --git a/ee/app/assets/javascripts/boards/components/board_form.vue b/ee/app/assets/javascripts/boards/components/board_form.vue
index 342b16d12106dea715d89db08307e6d77c26a82d..6aab5af66a7c10acad2a233bf90b46f5d5846100 100644
--- a/ee/app/assets/javascripts/boards/components/board_form.vue
+++ b/ee/app/assets/javascripts/boards/components/board_form.vue
@@ -57,9 +57,9 @@ export default {
       default: 0,
     },
     weights: {
-      type: String,
+      type: Array,
       required: false,
-      default: '',
+      default: () => [],
     },
   },
   data() {
@@ -126,9 +126,6 @@ export default {
     readonly() {
       return !this.canAdminBoard;
     },
-    weightsArray() {
-      return JSON.parse(this.weights);
-    },
     submitDisabled() {
       return this.isLoading || this.board.name.length === 0;
     },
@@ -269,7 +266,7 @@ export default {
             <board-weight-select
               v-model="board.weight"
               :board="board"
-              :weights="weightsArray"
+              :weights="weights"
               :can-edit="canAdminBoard"
             />
           </div>
diff --git a/ee/app/assets/javascripts/boards/components/boards_selector.js b/ee/app/assets/javascripts/boards/components/boards_selector.vue
similarity index 54%
rename from ee/app/assets/javascripts/boards/components/boards_selector.js
rename to ee/app/assets/javascripts/boards/components/boards_selector.vue
index 9feed8c4f448e7344fbca3db2f6b5148a6044817..0f777f7dd5606c035b2ea69075e51706c4ec532e 100644
--- a/ee/app/assets/javascripts/boards/components/boards_selector.js
+++ b/ee/app/assets/javascripts/boards/components/boards_selector.vue
@@ -1,15 +1,19 @@
-import Vue from 'vue';
+<script>
 import $ from 'jquery';
 import { throttle } from 'underscore';
+import { GlLoadingIcon } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
 import boardsStore from '~/boards/stores/boards_store';
 import BoardForm from './board_form.vue';
 import AssigneeList from './assignees_list_slector';
 import MilestoneList from './milestone_list_selector';
 
-export default Vue.extend({
+export default {
   name: 'BoardsSelector',
   components: {
+    Icon,
     BoardForm,
+    GlLoadingIcon,
   },
   props: {
     currentBoard: {
@@ -24,6 +28,42 @@ export default Vue.extend({
       type: Number,
       default: 200,
     },
+    boardBaseUrl: {
+      type: String,
+      required: true,
+    },
+    hasMissingBoards: {
+      type: Boolean,
+      required: true,
+    },
+    canAdminBoard: {
+      type: Boolean,
+      required: true,
+    },
+    multipleIssueBoardsAvailable: {
+      type: Boolean,
+      required: true,
+    },
+    labelsPath: {
+      type: String,
+      required: true,
+    },
+    projectId: {
+      type: Number,
+      required: true,
+    },
+    groupId: {
+      type: Number,
+      required: true,
+    },
+    scopedIssueBoardFeatureEnabled: {
+      type: Boolean,
+      required: true,
+    },
+    weights: {
+      type: Array,
+      required: true,
+    },
   },
   data() {
     return {
@@ -151,4 +191,75 @@ export default Vue.extend({
       }
     },
   },
-});
+};
+</script>
+
+<template>
+  <div class="boards-switcher js-boards-selector">
+    <span class="boards-selector-wrapper js-boards-selector-wrapper">
+      <div class="dropdown">
+        <button
+          class="dropdown-menu-toggle js-dropdown-toggle"
+          type="button"
+          data-toggle="dropdown"
+          @click="loadBoards"
+        >
+          {{ board.name }} <icon name="chevron-down" />
+        </button>
+        <div class="dropdown-menu" :class="{ 'is-loading': loading }">
+          <div class="dropdown-content-faded-mask js-scroll-fade" :class="scrollFadeClass">
+            <ul
+              v-if="!loading"
+              ref="content"
+              class="dropdown-list js-dropdown-list"
+              @scroll.passive="throttledSetScrollFade"
+            >
+              <li
+                v-for="otherBoard in boards"
+                :key="otherBoard.id"
+                class="dropdown-item js-dropdown-item"
+              >
+                <a :href="`${boardBaseUrl}/${otherBoard.id}`"> {{ otherBoard.name }} </a>
+              </li>
+              <li v-if="hasMissingBoards" class="small unclickable">
+                {{
+                  s__(
+                    'IssueBoards|Some of your boards are hidden, activate a license to see them again.',
+                  )
+                }}
+              </li>
+            </ul>
+          </div>
+
+          <gl-loading-icon v-if="loading" class="dropdown-loading" />
+
+          <div v-if="canAdminBoard" class="dropdown-footer">
+            <ul class="dropdown-footer-list">
+              <li v-if="multipleIssueBoardsAvailable">
+                <button type="button" @click.prevent="showPage('new');">
+                  {{ s__('IssueBoards|Create new board') }}
+                </button>
+              </li>
+              <li v-if="showDelete">
+                <button type="button" class="text-danger" @click.prevent="showPage('delete');">
+                  {{ s__('IssueBoards|Delete board') }}
+                </button>
+              </li>
+            </ul>
+          </div>
+        </div>
+      </div>
+
+      <board-form
+        v-if="currentPage"
+        :milestone-path="milestonePath"
+        :labels-path="labelsPath"
+        :project-id="projectId"
+        :group-id="groupId"
+        :can-admin-board="canAdminBoard"
+        :scoped-issue-board-feature-enabled="scopedIssueBoardFeatureEnabled"
+        :weights="weights"
+      />
+    </span>
+  </div>
+</template>
diff --git a/ee/app/views/shared/boards/_switcher.html.haml b/ee/app/views/shared/boards/_switcher.html.haml
index 389f2fae12df359795c3aaf29aa669349ed3eade..7d4f6b6ec6283ddc8f5af096ffb466dee2341fcc 100644
--- a/ee/app/views/shared/boards/_switcher.html.haml
+++ b/ee/app/views/shared/boards/_switcher.html.haml
@@ -2,46 +2,14 @@
 - milestone_filter_opts = { format: :json }
 - milestone_filter_opts = milestone_filter_opts.merge(only_group_milestones: true) if board.group_board?
 
-%boards-selector.js-boards-selector{ "inline-template" => true,
-  ":current-board" => current_board_json,
-  "milestone-path" => milestones_filter_path(milestone_filter_opts) }
-  %span.boards-selector-wrapper.js-boards-selector-wrapper
-    .dropdown
-      %button.dropdown-menu-toggle.js-dropdown-toggle{ "v-on:click" => "loadBoards",
-        data: { toggle: "dropdown" } }
-        {{ board.name }}
-        = icon("chevron-down")
-      .dropdown-menu{ ":class" => "{ 'is-loading': loading }" }
-        .dropdown-content-faded-mask.js-scroll-fade{ ":class" => "scrollFadeClass" }
-          %ul.dropdown-list.js-dropdown-list{ "v-if" => "!loading", "v-on:scroll.passive" => "throttledSetScrollFade", ref: "content" }
-            %li.dropdown-item.js-dropdown-item{ "v-for" => "board in boards" }
-              %a{ ":href" => "'#{board_base_url}/' + board.id" }
-                {{ board.name }}
-            - if !multiple_boards_available? && current_board_parent.boards.size > 1
-              %li
-                .small.unclickable
-                  Some of your boards are hidden, activate a license to see them again.
-
-        .dropdown-loading{ "v-if" => "loading" }
-          = icon("spin spinner")
-
-        - if can?(current_user, :admin_board, parent)
-          .dropdown-footer
-            %ul.dropdown-footer-list
-              - if parent.multiple_issue_boards_available?
-                %li
-                  %a{ "href" => "#", "v-on:click.prevent" => "showPage('new')" }
-                    Create new board
-              %li{ "v-if" => "showDelete" }
-                %a{ "href" => "#", "v-on:click.prevent" => "showPage('delete')" }
-                  %span.text-danger
-                    Delete board
-
-    %board-form{ ":milestone-path" => "milestonePath",
-      "labels-path" => labels_filter_path_with_defaults(only_group_labels: true, include_descendant_groups: true),
-      ":project-id" => "Number(#{@project&.id})",
-      ":group-id" => "Number(#{@group&.id})",
-      ":can-admin-board" => can?(current_user, :admin_board, parent),
-      ":scoped-issue-board-feature-enabled" => parent.feature_available?(:scoped_issue_board) ? 'true' : 'false',
-      "weights" => [Issue::WEIGHT_ANY] + Issue.weight_options,
-      "v-if" => "currentPage" }
+#js-multiple-boards-switcher.inline.boards-switcher{ data: { current_board: current_board_json,
+    milestone_path: milestones_filter_path(milestone_filter_opts),
+    board_base_url: board_base_url,
+    has_missing_boards: (!multiple_boards_available? && current_board_parent.boards.size > 1).to_s,
+    can_admin_board: can?(current_user, :admin_board, parent).to_s,
+    multiple_issue_boards_available: parent.multiple_issue_boards_available?.to_s,
+    labels_path: labels_filter_path_with_defaults(only_group_labels: true, include_descendant_groups: true),
+    project_id: @project&.id,
+    group_id: @group&.id,
+    scoped_issue_board_feature_enabled: parent.feature_available?(:scoped_issue_board) ? 'true' : 'false',
+    weights: ([Issue::WEIGHT_ANY] + Issue.weight_options).to_json } }
diff --git a/ee/spec/features/boards/multiple_boards_spec.rb b/ee/spec/features/boards/multiple_boards_spec.rb
index 5942d358992f913b2bd42366a15fd98dc7a003a0..a3dedc30b61901fe31f4c988050c5d6bd0586b4f 100644
--- a/ee/spec/features/boards/multiple_boards_spec.rb
+++ b/ee/spec/features/boards/multiple_boards_spec.rb
@@ -51,7 +51,7 @@ describe 'Multiple Issue Boards', :js do
         click_button board.name
 
         page.within('.dropdown-menu') do
-          click_link 'Create new board'
+          click_button 'Create new board'
         end
 
         fill_in 'board-new-name', with: 'This is a new board'
@@ -67,7 +67,7 @@ describe 'Multiple Issue Boards', :js do
         wait_for_requests
 
         page.within('.dropdown-menu') do
-          click_link 'Delete board'
+          click_button 'Delete board'
         end
 
         expect(page).to have_content('Are you sure you want to delete this board?')
diff --git a/ee/spec/features/boards/scoped_issue_board_spec.rb b/ee/spec/features/boards/scoped_issue_board_spec.rb
index 41d4dea9db54ed38022afacbb52ca96306bdb09c..8dc0b5d9d533e5e8285d1d1fface23affaff8c8a 100644
--- a/ee/spec/features/boards/scoped_issue_board_spec.rb
+++ b/ee/spec/features/boards/scoped_issue_board_spec.rb
@@ -97,10 +97,10 @@ describe 'Scoped issue boards', :js do
           visit group_boards_path(group)
           wait_for_requests
 
-          expect(page).to have_css('#js-multiple-boards-switcher')
-          page.within '#js-multiple-boards-switcher' do
+          expect(page).to have_css('.js-boards-selector')
+          page.within '.js-boards-selector' do
             find('.dropdown-menu-toggle').click
-            click_link 'Create new board'
+            click_button 'Create new board'
           end
 
           click_button 'Expand'
@@ -433,10 +433,10 @@ describe 'Scoped issue boards', :js do
     end
 
     it "doesn't show the input when creating a board" do
-      page.within '#js-multiple-boards-switcher' do
+      page.within '.js-boards-selector' do
         find('.dropdown-menu-toggle').click
 
-        click_link 'Create new board'
+        click_button 'Create new board'
 
         # To make sure the form is shown
         expect(page).to have_field('board-new-name')
@@ -501,11 +501,11 @@ describe 'Scoped issue boards', :js do
   end
 
   def create_board_scope(filter, value)
-    page.within '#js-multiple-boards-switcher' do
+    page.within '.js-boards-selector' do
       find('.dropdown-menu-toggle').click
     end
 
-    click_link 'Create new board'
+    click_button 'Create new board'
 
     find('#board-new-name').set 'test'
 
diff --git a/ee/spec/javascripts/boards/components/boards_selector_spec.js b/ee/spec/javascripts/boards/components/boards_selector_spec.js
index da810298adb1a0b93ccaf53a2929c61f2df4ba7e..ab6c023c011457f6e00e8e7b334caa14f23cc49d 100644
--- a/ee/spec/javascripts/boards/components/boards_selector_spec.js
+++ b/ee/spec/javascripts/boards/components/boards_selector_spec.js
@@ -1,8 +1,9 @@
 import Vue from 'vue';
 import BoardService from 'ee/boards/services/board_service';
-import BoardsSelector from 'ee/boards/components/boards_selector';
+import BoardsSelector from 'ee/boards/components/boards_selector.vue';
 import setTimeoutPromiseHelper from 'spec/helpers/set_timeout_promise_helper';
 import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import { TEST_HOST } from 'spec/test_constants';
 
 const throttleDuration = 1;
 
@@ -27,8 +28,7 @@ describe('BoardsSelector', () => {
   });
 
   beforeEach(done => {
-    loadFixtures('boards/show.html.raw');
-
+    setFixtures('<div class="js-boards-selector"></div>');
     window.gl = window.gl || {};
 
     window.gl.boardService = new BoardService({
@@ -44,12 +44,29 @@ describe('BoardsSelector', () => {
 
     spyOn(BoardService.prototype, 'allBoards').and.returnValue(boardServiceResponse);
 
+    const Component = Vue.extend(BoardsSelector);
     vm = mountComponent(
-      BoardsSelector,
+      Component,
       {
         throttleDuration,
-        currentBoard: {},
-        milestonePath: '',
+        currentBoard: {
+          id: 1,
+          name: 'Development',
+          milestone_id: null,
+          weight: null,
+          assignee_id: null,
+          labels: [],
+        },
+        milestonePath: `${TEST_HOST}/milestone/path`,
+        boardBaseUrl: `${TEST_HOST}/board/base/url`,
+        hasMissingBoards: false,
+        canAdminBoard: true,
+        multipleIssueBoardsAvailable: true,
+        labelsPath: `${TEST_HOST}/labels/path`,
+        projectId: 42,
+        groupId: 19,
+        scopedIssueBoardFeatureEnabled: true,
+        weights: [],
       },
       document.querySelector('.js-boards-selector'),
     );
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index b19a7f46ef5c39b8a80aa3f83f9a2cdc0fdf9d91..f9ebf49a2cb9f3a24ed2b8c89c7ece5d1eb15603 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4577,6 +4577,15 @@ msgstr ""
 msgid "IssueBoards|Boards"
 msgstr ""
 
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
 msgid "Issues"
 msgstr ""