diff --git a/app/assets/javascripts/boards/components/board_app.vue b/app/assets/javascripts/boards/components/board_app.vue
index 4683f47e60af19414098db1baaabf29211b0eec9..fcbba7b521a75737a8a4674b9af760d61768292f 100644
--- a/app/assets/javascripts/boards/components/board_app.vue
+++ b/app/assets/javascripts/boards/components/board_app.vue
@@ -141,6 +141,7 @@ export default {
       :board-id="boardId"
       :add-column-form-visible="addColumnFormVisible"
       :is-swimlanes-on="isSwimlanesOn"
+      :filters="filterParams"
       @switchBoard="switchBoard"
       @setFilters="setFilters"
       @setAddColumnFormVisibility="addColumnFormVisible = $event"
@@ -157,6 +158,7 @@ export default {
       :list-query-variables="listQueryVariables"
       @setActiveList="setActiveId"
       @setAddColumnFormVisibility="addColumnFormVisible = $event"
+      @setFilters="setFilters"
     />
     <board-settings-sidebar
       v-if="activeList"
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 82633a28b338d39d94f7039a39083b7120cdffcb..1adff98ec56f05b42ffd689c7eaa537a6ce9fe54 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -164,6 +164,7 @@ export default {
       :update-filters="true"
       :index="index"
       :show-work-item-type-icon="showWorkItemTypeIcon"
+      @setFilters="$emit('setFilters', $event)"
     >
       <slot></slot>
     </board-card-inner>
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index 6ca46893aff40a051d7620055a04a858dd5fcf6b..37cf825a90f48c739fa2a87038083befda8ccbe1 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -9,15 +9,14 @@ import {
 } from '@gitlab/ui';
 import { sortBy } from 'lodash';
 import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-import { updateHistory } from '~/lib/utils/url_utility';
+import { isScopedLabel, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { updateHistory, queryToObject } from '~/lib/utils/url_utility';
 import { sprintf, __, n__ } from '~/locale';
 import isShowingLabelsQuery from '~/graphql_shared/client/is_showing_labels.query.graphql';
 import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
 import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
 import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue';
 import { ListType } from '../constants';
-import eventHub from '../eventhub';
 import { setError } from '../graphql/cache_updates';
 import IssueDueDate from './issue_due_date.vue';
 import IssueTimeEstimate from './issue_time_estimate.vue';
@@ -221,7 +220,10 @@ export default {
         updateHistory({
           url: `${filterPath}${filter}`,
         });
-        eventHub.$emit('updateTokens');
+
+        const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true });
+        const filters = convertObjectPropsToCamelCase(rawFilterParams, {});
+        this.$emit('setFilters', filters);
       }
     },
     showScopedLabel(label) {
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index 8d25c1cb8c2897bf859efefbc89a429244cd8a4a..844a4e51a07d2f91fcb2ea44f8903a662f78c0ed 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -28,6 +28,11 @@ export default {
       default: () => [],
     },
   },
+  data() {
+    return {
+      showNewForm: false,
+    };
+  },
   computed: {
     highlighted() {
       return this.highlightedLists.includes(this.list.id);
@@ -48,6 +53,11 @@ export default {
       immediate: true,
     },
   },
+  methods: {
+    toggleNewForm() {
+      this.showNewForm = !this.showNewForm;
+    },
+  },
 };
 </script>
 
@@ -70,9 +80,18 @@ export default {
         :list="list"
         :filter-params="filters"
         :board-id="boardId"
+        @toggleNewForm="toggleNewForm"
         @setActiveList="$emit('setActiveList', $event)"
       />
-      <board-list ref="board-list" :board-id="boardId" :list="list" :filter-params="filters" />
+      <board-list
+        ref="board-list"
+        :board-id="boardId"
+        :list="list"
+        :filter-params="filters"
+        :show-new-form="showNewForm"
+        @toggleNewForm="toggleNewForm"
+        @setFilters="$emit('setFilters', $event)"
+      />
     </div>
   </div>
 </template>
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index dbdfe314ae0b7f9574e5536ba39a88ab56c94d34..6ab6e416baac53c2b3cc7647be6ccbee6e01212e 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -214,6 +214,7 @@ export default {
         :data-draggable-item-type="$options.draggableItemTypes.list"
         :class="{ 'gl-display-none! gl-sm-display-inline-block!': addColumnFormVisible }"
         @setActiveList="$emit('setActiveList', $event)"
+        @setFilters="$emit('setFilters', $event)"
       />
 
       <transition name="slide" @after-enter="afterFormEnters">
@@ -238,6 +239,7 @@ export default {
       :highlighted-lists="highlightedLists"
       @setActiveList="$emit('setActiveList', $event)"
       @move-list="updateListPosition"
+      @setFilters="$emit('setFilters', $event)"
     >
       <board-add-new-column
         v-if="addColumnFormVisible"
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue
index faaef226c21d58de1170122a25339aac87655c37..d510e7a9c294ee87817247fbd7e2415aec3cbbe5 100644
--- a/app/assets/javascripts/boards/components/board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/board_filtered_search.vue
@@ -22,7 +22,6 @@ import {
 } from '~/vue_shared/components/filtered_search_bar/constants';
 import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
 import { AssigneeFilterType, GroupByParamType } from 'ee_else_ce/boards/constants';
-import eventHub from '../eventhub';
 
 export default {
   i18n: {
@@ -45,6 +44,10 @@ export default {
       type: Object,
       default: () => ({}),
     },
+    filters: {
+      type: Object,
+      required: true,
+    },
   },
   data() {
     return {
@@ -340,16 +343,21 @@ export default {
       );
     },
   },
+  watch: {
+    filters: {
+      handler(updatedFilters) {
+        this.filterParams = { ...this.filterParams, ...updatedFilters };
+        this.filteredSearchKey += 1;
+      },
+      immediate: true,
+    },
+  },
   created() {
-    eventHub.$on('updateTokens', this.updateTokens);
     if (!isEmpty(this.eeFilters)) {
       this.filterParams = this.eeFilters;
       this.$emit('setFilters', this.formattedFilterParams);
     }
   },
-  beforeDestroy() {
-    eventHub.$off('updateTokens', this.updateTokens);
-  },
   methods: {
     formattedFilterParams() {
       const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true });
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index df7f9cce5b362912af2d40d8a9dd843f2616b783..ee5bbe50a455265be956905f6932d998fe94701d 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -13,7 +13,6 @@ import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_posi
 import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
 import {
   DEFAULT_BOARD_LIST_ITEMS_SIZE,
-  toggleFormEventPrefix,
   DraggableItemTypes,
   listIssuablesQueries,
   ListType,
@@ -26,7 +25,6 @@ import {
   setError,
 } from '../graphql/cache_updates';
 import { shouldCloneCard, moveItemVariables } from '../boards_util';
-import eventHub from '../eventhub';
 import BoardCard from './board_card.vue';
 import BoardNewIssue from './board_new_issue.vue';
 import BoardCutLine from './board_cut_line.vue';
@@ -72,12 +70,15 @@ export default {
       type: Object,
       required: true,
     },
+    showNewForm: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
   },
   data() {
     return {
       showCount: false,
-      showIssueForm: false,
-      showEpicForm: false,
       currentList: null,
       isLoadingMore: false,
       toListId: null,
@@ -191,9 +192,6 @@ export default {
         wipLimit: this.list.maxIssueCount,
       });
     },
-    toggleFormEventPrefix() {
-      return this.isEpicBoard ? toggleFormEventPrefix.epic : toggleFormEventPrefix.issue;
-    },
     boardItemsSizeExceedsMax() {
       return this.list.maxIssueCount > 0 && this.listItemsCount > this.list.maxIssueCount;
     },
@@ -204,10 +202,10 @@ export default {
       return this.$apollo.queries.currentList.loading && !this.isLoadingMore;
     },
     epicCreateFormVisible() {
-      return this.isEpicBoard && this.list.listType !== STATUS_CLOSED && this.showEpicForm;
+      return this.isEpicBoard && this.list.listType !== STATUS_CLOSED && this.showNewForm;
     },
     issueCreateFormVisible() {
-      return !this.isEpicBoard && this.list.listType !== STATUS_CLOSED && this.showIssueForm;
+      return !this.isEpicBoard && this.list.listType !== STATUS_CLOSED && this.showNewForm;
     },
     listRef() {
       // When list is draggable, the reference to the list needs to be accessed differently
@@ -258,19 +256,6 @@ export default {
         this.showCount = this.scrollHeight() > Math.ceil(this.listHeight());
       });
     },
-    'list.id': {
-      handler(id, oldVal) {
-        if (id) {
-          eventHub.$on(`${this.toggleFormEventPrefix}${this.list.id}`, this.toggleForm);
-
-          eventHub.$off(`${this.toggleFormEventPrefix}${oldVal}`, this.toggleForm);
-        }
-      },
-      immediate: true,
-    },
-  },
-  beforeDestroy() {
-    eventHub.$off(`${this.toggleFormEventPrefix}${this.list.id}`, this.toggleForm);
   },
   methods: {
     listHeight() {
@@ -290,13 +275,6 @@ export default {
       });
       this.isLoadingMore = false;
     },
-    toggleForm() {
-      if (this.isEpicBoard) {
-        this.showEpicForm = !this.showEpicForm;
-      } else {
-        this.showIssueForm = !this.showIssueForm;
-      }
-    },
     isObservableItem(index) {
       // observe every 6 item of 10 to achieve smooth loading state
       return index !== 0 && index % 6 === 0;
@@ -572,7 +550,7 @@ export default {
       }
     },
     async addListItem(input) {
-      this.toggleForm();
+      this.$emit('toggleNewForm');
       this.addItemToListInProgress = true;
       let issuable;
       try {
@@ -655,12 +633,14 @@ export default {
       v-if="issueCreateFormVisible"
       :list="list"
       :board-id="boardId"
+      @toggleNewForm="$emit('toggleNewForm')"
       @addNewIssue="addListItem"
     />
     <board-new-epic
       v-if="epicCreateFormVisible"
       :list="list"
       :board-id="boardId"
+      @toggleNewForm="$emit('toggleNewForm')"
       @addNewEpic="addListItem"
     />
     <component
@@ -690,6 +670,7 @@ export default {
         :item="item"
         :data-draggable-item-type="$options.draggableItemTypes.card"
         :show-work-item-type-icon="!isEpicBoard"
+        @setFilters="$emit('setFilters', $event)"
       >
         <board-card-move-to-position
           v-if="showMoveToPosition"
@@ -715,6 +696,7 @@ export default {
         :item="item"
         :data-draggable-item-type="$options.draggableItemTypes.card"
         :show-work-item-type-icon="!isEpicBoard"
+        @setFilters="$emit('setFilters', $event)"
       >
         <board-card-move-to-position
           v-if="showMoveToPosition"
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index 3d5d7650c728e069c4f8b36b015f27768f0e2c25..8a8f149dc6a2ac60147aef8c66fd3ebdfcca90fd 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -21,12 +21,10 @@ import setActiveBoardItemMutation from 'ee_else_ce/boards/graphql/client/set_act
 import AccessorUtilities from '~/lib/utils/accessor';
 import {
   ListType,
-  toggleFormEventPrefix,
   updateListQueries,
   toggleCollapsedMutations,
   listsDeferredQuery,
 } from 'ee_else_ce/boards/constants';
-import eventHub from '../eventhub';
 import { setError } from '../graphql/cache_updates';
 import ItemCount from './item_count.vue';
 
@@ -244,19 +242,16 @@ export default {
     showScopedLabels(label) {
       return this.scopedLabelsAvailable && isScopedLabel(label);
     },
-    showNewIssueForm() {
+    showNewForm() {
       if (this.isSwimlanesHeader) {
         this.$emit('openUnassignedLane');
         this.$nextTick(() => {
-          eventHub.$emit(`${toggleFormEventPrefix.issue}${this.list.id}`);
+          this.$emit('toggleNewForm');
         });
       } else {
-        eventHub.$emit(`${toggleFormEventPrefix.issue}${this.list.id}`);
+        this.$emit('toggleNewForm');
       }
     },
-    showNewEpicForm() {
-      eventHub.$emit(`${toggleFormEventPrefix.epic}${this.list.id}`);
-    },
     toggleExpanded() {
       const collapsed = !this.list.collapsed;
       this.updateLocalCollapsedStatus(collapsed);
@@ -497,7 +492,7 @@ export default {
           size="small"
           icon="plus"
           data-testid="new-issue-btn"
-          @click="showNewIssueForm"
+          @click="showNewForm"
         />
 
         <gl-button
@@ -508,7 +503,7 @@ export default {
           size="small"
           icon="plus"
           data-testid="new-epic-btn"
-          @click="showNewEpicForm"
+          @click="showNewForm"
         />
 
         <gl-button
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index ea22bb08f2a958110d43e300e79e891f0ee0b3de..6c21ea4293625ece94f5624dafed2a674ec0754a 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -3,8 +3,6 @@ import { s__ } from '~/locale';
 import { getMilestone, formatIssueInput, getBoardQuery } from 'ee_else_ce/boards/boards_util';
 import BoardNewIssueMixin from 'ee_else_ce/boards/mixins/board_new_issue';
 
-import { toggleFormEventPrefix } from '../constants';
-import eventHub from '../eventhub';
 import { setError } from '../graphql/cache_updates';
 
 import BoardNewItem from './board_new_item.vue';
@@ -64,9 +62,6 @@ export default {
     },
   },
   computed: {
-    formEventPrefix() {
-      return toggleFormEventPrefix.issue;
-    },
     disableSubmit() {
       return this.isGroupBoard ? !this.selectedProject.name : false;
     },
@@ -107,7 +102,7 @@ export default {
       this.$emit('addNewIssue', input);
     },
     cancel() {
-      eventHub.$emit(`${this.formEventPrefix}${this.list.id}`);
+      this.$emit('toggleNewForm');
     },
   },
 };
@@ -116,7 +111,6 @@ export default {
 <template>
   <board-new-item
     :list="list"
-    :form-event-prefix="formEventPrefix"
     :submit-button-title="__('Create issue')"
     :disable-submit="disableSubmit"
     @form-submit="submit"
diff --git a/app/assets/javascripts/boards/components/board_new_item.vue b/app/assets/javascripts/boards/components/board_new_item.vue
index a4e1b8ef273fd731483026737a653706a800abea..946d791b5944be30d5dcbb746df53e60b42618d6 100644
--- a/app/assets/javascripts/boards/components/board_new_item.vue
+++ b/app/assets/javascripts/boards/components/board_new_item.vue
@@ -16,10 +16,6 @@ export default {
       type: Object,
       required: true,
     },
-    formEventPrefix: {
-      type: String,
-      required: true,
-    },
     disableSubmit: {
       type: Boolean,
       required: false,
diff --git a/app/assets/javascripts/boards/components/board_top_bar.vue b/app/assets/javascripts/boards/components/board_top_bar.vue
index 820c1fc1dd1c4542f10358fcca08db7a19ba7acb..bc13622ce4ba6532e289153ca95c81806a915e87 100644
--- a/app/assets/javascripts/boards/components/board_top_bar.vue
+++ b/app/assets/javascripts/boards/components/board_top_bar.vue
@@ -45,6 +45,10 @@ export default {
       type: Boolean,
       required: true,
     },
+    filters: {
+      type: Object,
+      required: true,
+    },
   },
   data() {
     return {
@@ -104,11 +108,13 @@ export default {
           v-if="isIssueBoard"
           :board="board"
           :is-swimlanes-on="isSwimlanesOn"
+          :filters="filters"
           @setFilters="$emit('setFilters', $event)"
         />
         <epic-board-filtered-search
           v-else
           :board="board"
+          :filters="filters"
           @setFilters="$emit('setFilters', $event)"
         />
       </div>
diff --git a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
index c28415de62008cae39c07579e9cc6114e9dab65b..2e2d04996eeaedfd14036d46acbc9a55d805e67e 100644
--- a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
@@ -57,6 +57,10 @@ export default {
       required: false,
       default: false,
     },
+    filters: {
+      type: Object,
+      required: true,
+    },
   },
   computed: {
     tokensCE() {
@@ -210,6 +214,7 @@ export default {
     :tokens="tokens"
     :board="board"
     :is-swimlanes-on="isSwimlanesOn"
+    :filters="filters"
     @setFilters="$emit('setFilters', $event)"
   />
 </template>
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index a3983f11c8657ae459a402c78cc555f61a76cb48..84564560fe332124e828ee3f2c7cb061236697f1 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -46,11 +46,6 @@ export const formType = {
   edit: 'edit',
 };
 
-export const toggleFormEventPrefix = {
-  epic: 'toggle-epic-form-',
-  issue: 'toggle-issue-form-',
-};
-
 export const INCIDENT = 'INCIDENT';
 
 export const flashAnimationDuration = 2000;
diff --git a/ee/app/assets/javascripts/boards/components/board_new_epic.vue b/ee/app/assets/javascripts/boards/components/board_new_epic.vue
index 9f3e0d75bc6f5bb95b8fc82a36c7b1cf6b36c875..ac9b096f5d5d5c005e9e0641663799ef604f1b66 100644
--- a/ee/app/assets/javascripts/boards/components/board_new_epic.vue
+++ b/ee/app/assets/javascripts/boards/components/board_new_epic.vue
@@ -1,8 +1,6 @@
 <script>
 import { s__ } from '~/locale';
 import BoardNewItem from '~/boards/components/board_new_item.vue';
-import { toggleFormEventPrefix } from '~/boards/constants';
-import eventHub from '~/boards/eventhub';
 import { setError } from '~/boards/graphql/cache_updates';
 import { getIdFromGraphQLId } from '~/graphql_shared/utils';
 import epicBoardQuery from '../graphql/epic_board.query.graphql';
@@ -58,12 +56,6 @@ export default {
     },
   },
   computed: {
-    formEventPrefix() {
-      return toggleFormEventPrefix.epic;
-    },
-    formEvent() {
-      return `${this.formEventPrefix}${this.list.id}`;
-    },
     groupPath() {
       return this.selectedGroup?.fullPath ?? this.fullPath;
     },
@@ -91,7 +83,7 @@ export default {
       });
     },
     cancel() {
-      eventHub.$emit(this.formEvent);
+      this.$emit('toggleNewForm');
     },
   },
 };
@@ -100,7 +92,6 @@ export default {
 <template>
   <board-new-item
     :list="list"
-    :form-event-prefix="formEventPrefix"
     :submit-button-title="__('Create epic')"
     @form-submit="submit"
     @form-cancel="cancel"
diff --git a/ee/app/assets/javascripts/boards/components/epic_filtered_search.vue b/ee/app/assets/javascripts/boards/components/epic_filtered_search.vue
index 41c0999058a7b58f5549021423f0ac292507bc37..74bdabcf93d7f1a5d3fcebae88635e6abed48ab2 100644
--- a/ee/app/assets/javascripts/boards/components/epic_filtered_search.vue
+++ b/ee/app/assets/javascripts/boards/components/epic_filtered_search.vue
@@ -24,6 +24,10 @@ export default {
       required: false,
       default: () => {},
     },
+    filters: {
+      type: Object,
+      required: true,
+    },
   },
   computed: {
     tokens() {
@@ -80,6 +84,7 @@ export default {
     data-testid="epic-filtered-search"
     :tokens="tokens"
     :board="board"
+    :filters="filters"
     @setFilters="$emit('setFilters', $event)"
   />
 </template>
diff --git a/ee/app/assets/javascripts/boards/components/epic_lane.vue b/ee/app/assets/javascripts/boards/components/epic_lane.vue
index 7ce23d990a4f0767b69215e1322322ca92ff7aa1..173947fd126e741dfb64ef3d7272a59878cf5d54 100644
--- a/ee/app/assets/javascripts/boards/components/epic_lane.vue
+++ b/ee/app/assets/javascripts/boards/components/epic_lane.vue
@@ -226,6 +226,7 @@ export default {
         :can-admin-epic="canAdminEpic"
         :lists="lists"
         :total-issues-count="totalIssuesCountByListId[list.id]"
+        @setFilters="$emit('setFilters', $event)"
       />
     </div>
   </div>
diff --git a/ee/app/assets/javascripts/boards/components/epics_swimlanes.vue b/ee/app/assets/javascripts/boards/components/epics_swimlanes.vue
index 7b2f006746831bcbcdd07236c5f45a8cc85e7da2..b9826f24eb9fae3d4abb3506104e827c54d5411f 100644
--- a/ee/app/assets/javascripts/boards/components/epics_swimlanes.vue
+++ b/ee/app/assets/javascripts/boards/components/epics_swimlanes.vue
@@ -69,6 +69,7 @@ export default {
       hasMoreUnassignedIssuables: {},
       isLoadingMoreIssues: false,
       totalIssuesCountByListId: {},
+      showNewForm: [],
     };
   },
   apollo: {
@@ -209,6 +210,13 @@ export default {
     setTotalIssuesCount(listId, count) {
       this.totalIssuesCountByListId[listId] = count;
     },
+    toggleNewForm(listId) {
+      if (this.showNewForm.includes(listId)) {
+        this.showNewForm.splice(this.showNewForm.indexOf(listId), 1);
+      } else {
+        this.showNewForm = [...this.showNewForm, listId];
+      }
+    },
   },
 };
 </script>
@@ -246,6 +254,7 @@ export default {
             :filter-params="filters"
             :is-swimlanes-header="true"
             :board-id="boardId"
+            @toggleNewForm="toggleNewForm(list.id)"
             @setActiveList="$emit('setActiveList', $event)"
             @openUnassignedLane="openUnassignedLane"
             @setTotalIssuesCount="setTotalIssuesCount"
@@ -259,10 +268,22 @@ export default {
           :remain="bufferSize"
           :bench="bufferSize"
           :scrollelement="$refs.scrollableContainer"
-          :item="$options.EpicLane"
-          :itemcount="epics.length"
-          :itemprops="getEpicLaneProps"
-        />
+        >
+          <epic-lane
+            v-for="epic in epics"
+            :key="epic.id"
+            :epic="epic"
+            :lists="lists"
+            :disabled="disabled"
+            :can-admin-list="canAdminList"
+            :board-id="boardId"
+            :filter-params="filters"
+            :highlighted-lists="highlightedLists"
+            :can-admin-epic="canAdminEpic"
+            :total-issues-count-by-list-id="totalIssuesCountByListId"
+            @setFilters="$emit('setFilters', $event)"
+          />
+        </virtual-list>
         <div v-if="hasMoreEpicsToLoad" class="swimlanes-button gl-pb-3 gl-pl-3 gl-sticky gl-left-0">
           <gl-button
             category="tertiary"
@@ -321,8 +342,11 @@ export default {
                 :can-admin-epic="canAdminEpic"
                 :lists="lists"
                 :total-issues-count="totalIssuesCountByListId[list.id]"
+                :show-new-form="showNewForm.indexOf(list.id) > -1"
+                @toggleNewForm="toggleNewForm(list.id)"
                 @updatePageInfo="updatePageInfo"
                 @issuesLoaded="isLoadingMoreIssues = false"
+                @setFilters="$emit('setFilters', $event)"
               />
             </div>
           </div>
diff --git a/ee/app/assets/javascripts/boards/components/issues_lane_list.vue b/ee/app/assets/javascripts/boards/components/issues_lane_list.vue
index 53b0448ce5cd1683ea635bf97dd942e9f93ffda4..ac77ab8bfecf3b173b799abbbcf773f842a8b4eb 100644
--- a/ee/app/assets/javascripts/boards/components/issues_lane_list.vue
+++ b/ee/app/assets/javascripts/boards/components/issues_lane_list.vue
@@ -4,7 +4,6 @@ import Draggable from 'vuedraggable';
 import { __, s__ } from '~/locale';
 import BoardCard from '~/boards/components/board_card.vue';
 import BoardNewIssue from '~/boards/components/board_new_issue.vue';
-import eventHub from '~/boards/eventhub';
 import { getIdFromGraphQLId } from '~/graphql_shared/utils';
 import { STATUS_CLOSED } from '~/issues/constants';
 import {
@@ -82,10 +81,14 @@ export default {
       required: false,
       default: 0,
     },
+    showNewForm: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
   },
   data() {
     return {
-      showIssueForm: false,
       toListId: null,
     };
   },
@@ -183,7 +186,7 @@ export default {
       return this.list.maxIssueCount > 0 && this.totalIssuesCount > this.list.maxIssueCount;
     },
     showNewIssue() {
-      return this.list.type !== STATUS_CLOSED && this.showIssueForm && this.isUnassignedIssuesLane;
+      return this.list.type !== STATUS_CLOSED && this.showNewForm && this.isUnassignedIssuesLane;
     },
   },
   watch: {
@@ -203,19 +206,7 @@ export default {
       }
     },
   },
-  created() {
-    eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
-  },
-  beforeDestroy() {
-    eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm);
-  },
   methods: {
-    toggleForm() {
-      this.showIssueForm = !this.showIssueForm;
-      if (this.showIssueForm && this.isUnassignedIssuesLane) {
-        this.$el.scrollIntoView(false);
-      }
-    },
     handleDragOnStart() {
       document.body.classList.add('is-dragging');
     },
@@ -391,7 +382,7 @@ export default {
       });
     },
     async addListItem(input) {
-      this.toggleForm();
+      this.$emit('toggleNewForm');
       try {
         await this.$apollo.mutate({
           mutation: listIssuablesQueries.issue.createMutation,
@@ -448,6 +439,7 @@ export default {
         v-if="showNewIssue"
         :list="list"
         :board-id="boardId"
+        @toggleNewForm="$emit('toggleNewForm')"
         @addNewIssue="addListItem"
       />
       <component
@@ -472,6 +464,7 @@ export default {
             :list="list"
             :item="issue"
             :can-admin="canAdminEpic"
+            @setFilters="$emit('setFilters', $event)"
           />
         </template>
         <gl-loading-icon
diff --git a/ee/spec/frontend/boards/components/board_filtered_search_spec.js b/ee/spec/frontend/boards/components/board_filtered_search_spec.js
index 2bc1118397d73938fd1c8a436a0eb9897d364d6f..4add3b67a3f69bc8e6d246c51fcef9f26561c57f 100644
--- a/ee/spec/frontend/boards/components/board_filtered_search_spec.js
+++ b/ee/spec/frontend/boards/components/board_filtered_search_spec.js
@@ -17,6 +17,7 @@ describe('ee/BoardFilteredSearch', () => {
       propsData: {
         tokens: [],
         board: {},
+        filters: {},
       },
       provide: {
         boardBaseUrl: 'root',
diff --git a/ee/spec/frontend/boards/components/board_list_header_spec.js b/ee/spec/frontend/boards/components/board_list_header_spec.js
index 8e2a219916a4625c2b1d4ff9996c0665604b66a1..adfc10f40eaadc7605080fa5b590c6dd75c33029 100644
--- a/ee/spec/frontend/boards/components/board_list_header_spec.js
+++ b/ee/spec/frontend/boards/components/board_list_header_spec.js
@@ -12,7 +12,6 @@ import {
   mockLabelList,
 } from 'jest/boards/mock_data';
 import { ListType } from '~/boards/constants';
-import boardsEventHub from '~/boards/eventhub';
 import * as cacheUpdates from '~/boards/graphql/cache_updates';
 import listQuery from 'ee/boards/graphql/board_lists_deferred.query.graphql';
 import epicListQuery from 'ee/boards/graphql/epic_board_lists_deferred.query.graphql';
@@ -129,7 +128,6 @@ describe('Board List Header Component', () => {
 
   describe('New epic button', () => {
     beforeEach(() => {
-      jest.spyOn(boardsEventHub, '$emit');
       createComponent({ isEpicBoard: true, issuableType: 'epic' });
     });
 
@@ -155,13 +153,12 @@ describe('Board List Header Component', () => {
       expect(findButtonGroup().exists()).toBe(false);
     });
 
-    it('emits `toggle-epic-form` event on Sidebar eventHub when clicked', () => {
-      expect(boardsEventHub.$emit).not.toHaveBeenCalled();
+    it('emits `toggleNewForm` event when clicked', () => {
+      expect(wrapper.emitted('toggleNewForm')).toBeUndefined();
 
       findNewEpicButton().trigger('click');
 
-      expect(boardsEventHub.$emit).toHaveBeenCalledWith(`toggle-epic-form-${mockList.id}`);
-      expect(boardsEventHub.$emit).toHaveBeenCalledTimes(1);
+      expect(wrapper.emitted('toggleNewForm')).toHaveLength(1);
     });
   });
 
diff --git a/ee/spec/frontend/boards/components/board_list_spec.js b/ee/spec/frontend/boards/components/board_list_spec.js
index 99216a5168963a93cd78fdeccf0bc71f17a8aeab..dfc506c29b36e453c84f9c14cd02f7c0115a77a9 100644
--- a/ee/spec/frontend/boards/components/board_list_spec.js
+++ b/ee/spec/frontend/boards/components/board_list_spec.js
@@ -11,7 +11,6 @@ import listIssuesQuery from '~/boards/graphql/lists_issues.query.graphql';
 import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
 import * as cacheUpdates from '~/boards/graphql/cache_updates';
 import { TYPE_EPIC, TYPE_ISSUE, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants';
-import eventHub from '~/boards/eventhub';
 import issueMoveListMutation from 'ee/boards/graphql/issue_move_list.mutation.graphql';
 import epicMoveListMutation from 'ee/boards/graphql/epic_move_list.mutation.graphql';
 import epicCreateMutation from 'ee/boards/graphql/epic_create.mutation.graphql';
@@ -100,6 +99,7 @@ describe('BoardList Component', () => {
           isGroupBoard: true,
           isEpicBoard,
         },
+        componentProps: { showNewForm: true },
         stubs: {
           BoardNewIssue,
           BoardNewEpic,
@@ -108,9 +108,6 @@ describe('BoardList Component', () => {
 
       await waitForPromises();
 
-      eventHub.$emit(`toggle-${issuableType}-form-${mockList.id}`);
-
-      await nextTick();
       expect(wrapper.findComponent(formComponent).exists()).toBe(true);
       expect(wrapper.findComponent(notRenderedFormComponent).exists()).toBe(false);
     },
@@ -395,6 +392,7 @@ describe('BoardList Component', () => {
           listProps: {
             id: listId,
           },
+          componentProps: { showNewForm: true },
           provide: {
             boardType: WORKSPACE_GROUP,
             issuableType,
@@ -412,8 +410,6 @@ describe('BoardList Component', () => {
 
         await waitForPromises();
 
-        eventHub.$emit(`toggle-${issuableType}-form-${listId}`);
-        await nextTick();
         expect(wrapper.findComponent(component).exists()).toBe(true);
         wrapper.findComponent(component).vm.$emit(event, { title: 'Foo' });
 
@@ -435,6 +431,7 @@ describe('BoardList Component', () => {
           listProps: {
             id: listId,
           },
+          componentProps: { showNewForm: true },
           provide: {
             boardType: WORKSPACE_GROUP,
             issuableType,
@@ -457,8 +454,6 @@ describe('BoardList Component', () => {
 
         await waitForPromises();
 
-        eventHub.$emit(`toggle-${issuableType}-form-${listId}`);
-        await nextTick();
         expect(wrapper.findComponent(component).exists()).toBe(true);
         wrapper.findComponent(component).vm.$emit(event, { title: 'Foo' });
 
diff --git a/ee/spec/frontend/boards/components/board_new_epic_spec.js b/ee/spec/frontend/boards/components/board_new_epic_spec.js
index 73584fb9f04008d540ca81e13244c42761833a44..1cfdf0b118cea4070fdd442fcdbb5de8cd895c88 100644
--- a/ee/spec/frontend/boards/components/board_new_epic_spec.js
+++ b/ee/spec/frontend/boards/components/board_new_epic_spec.js
@@ -10,7 +10,6 @@ import epicBoardQuery from 'ee/boards/graphql/epic_board.query.graphql';
 import { mockList } from 'jest/boards/mock_data';
 
 import BoardNewItem from '~/boards/components/board_new_item.vue';
-import eventHub from '~/boards/eventhub';
 
 import { mockEpicBoardResponse } from '../mock_data';
 
@@ -66,7 +65,6 @@ describe('Epic boards new epic form', () => {
     expect(boardNewItem.exists()).toBe(true);
     expect(boardNewItem.props()).toEqual({
       list: mockList,
-      formEventPrefix: 'toggle-epic-form-',
       submitButtonTitle: 'Create epic',
       disableSubmit: false,
     });
@@ -79,11 +77,10 @@ describe('Epic boards new epic form', () => {
     expect(groupSelect.exists()).toBe(true);
   });
 
-  it('emits event `toggle-epic-form` with current list Id suffix on eventHub when `board-new-item` emits form-cancel event', async () => {
-    jest.spyOn(eventHub, '$emit').mockImplementation();
+  it('emits event `toggleNewForm` when `board-new-item` emits form-cancel event', async () => {
     findBoardNewItem().vm.$emit('form-cancel');
 
     await nextTick();
-    expect(eventHub.$emit).toHaveBeenCalledWith(`toggle-epic-form-${mockList.id}`);
+    expect(wrapper.emitted('toggleNewForm')).toHaveLength(1);
   });
 });
diff --git a/ee/spec/frontend/boards/components/board_top_bar_spec.js b/ee/spec/frontend/boards/components/board_top_bar_spec.js
index c15b0e9f081031e545f54624d88e41aa097d3de0..4820012b6f71b883daa8ba796f2c25c279b9d2d7 100644
--- a/ee/spec/frontend/boards/components/board_top_bar_spec.js
+++ b/ee/spec/frontend/boards/components/board_top_bar_spec.js
@@ -44,6 +44,7 @@ describe('BoardTopBar', () => {
         boardId: 'gid://gitlab/Board/1',
         isSwimlanesOn: false,
         addColumnFormVisible: false,
+        filters: {},
       },
       provide: {
         swimlanesFeatureAvailable: false,
diff --git a/ee/spec/frontend/boards/components/epics_swimlanes_spec.js b/ee/spec/frontend/boards/components/epics_swimlanes_spec.js
index 4ab81e6c77394246e884684b08fce2fc79e03823..aa433d915b009fa20d7baea3612aa1306c58fa0d 100644
--- a/ee/spec/frontend/boards/components/epics_swimlanes_spec.js
+++ b/ee/spec/frontend/boards/components/epics_swimlanes_spec.js
@@ -136,15 +136,16 @@ describe('EpicsSwimlanes', () => {
       expect(virtualList.props()).toMatchObject({
         remain: bufferSize,
         bench: bufferSize,
-        item: EpicLane,
         size: EPIC_LANE_BASE_HEIGHT,
-        itemcount: mockEpics.length,
-        itemprops: expect.any(Function),
       });
 
       expect(virtualList.props().scrollelement).toBe(scrollableContainer);
     });
 
+    it('renders epic lanes', () => {
+      expect(wrapper.findAllComponents(EpicLane)).toHaveLength(mockEpics.length);
+    });
+
     it('does not display load more epics button if there are no more epics', () => {
       expect(findLoadMoreEpicsButton().exists()).toBe(false);
     });
diff --git a/ee/spec/frontend/boards/components/issues_lane_list_spec.js b/ee/spec/frontend/boards/components/issues_lane_list_spec.js
index 63fc9bfe4b0f56bb65a6b7eabded58f590919f97..606841c932b106d74749625e2df3e6ca341117ff 100644
--- a/ee/spec/frontend/boards/components/issues_lane_list_spec.js
+++ b/ee/spec/frontend/boards/components/issues_lane_list_spec.js
@@ -7,7 +7,6 @@ import waitForPromises from 'helpers/wait_for_promises';
 import { DraggableItemTypes } from 'ee_else_ce/boards/constants';
 import listQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql';
 import IssuesLaneList from 'ee/boards/components/issues_lane_list.vue';
-import eventHub from '~/boards/eventhub';
 import BoardCard from '~/boards/components/board_card.vue';
 import BoardNewIssue from '~/boards/components/board_new_issue.vue';
 import { ListType } from '~/boards/constants';
@@ -49,6 +48,7 @@ describe('IssuesLaneList', () => {
     canAdminEpic = false,
     highlightedLists = [],
     totalIssuesCount = 2,
+    showNewForm = false,
     listsIssuesQueryHandler = listIssuesQueryHandlerSuccess,
     moveIssueMutationHandler = moveIssueMutationHandlerSuccess,
     createIssueMutationHandler = createIssueMutationHandlerSuccess,
@@ -118,6 +118,7 @@ describe('IssuesLaneList', () => {
         lists: mockLists,
         highlightedLists,
         totalIssuesCount,
+        showNewForm,
       },
       provide: {
         fullPath: 'gitlab-org',
@@ -329,12 +330,11 @@ describe('IssuesLaneList', () => {
         },
         isUnassignedIssuesLane: true,
         canAdminEpic: true,
+        showNewForm: true,
       });
 
       await waitForPromises();
 
-      eventHub.$emit(`toggle-issue-form-${mockList.id}`);
-      await nextTick();
       expect(findNewIssueForm().exists()).toBe(true);
       findNewIssueForm().vm.$emit('addNewIssue', { title: 'Foo' });
 
@@ -350,13 +350,12 @@ describe('IssuesLaneList', () => {
         },
         isUnassignedIssuesLane: true,
         canAdminEpic: true,
+        showNewForm: true,
         createIssueMutationHandler: queryHandlerFailure,
       });
 
       await waitForPromises();
 
-      eventHub.$emit(`toggle-issue-form-${mockList.id}`);
-      await nextTick();
       expect(findNewIssueForm().exists()).toBe(true);
       findNewIssueForm().vm.$emit('addNewIssue', { title: 'Foo' });
 
diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js
index 8f2752b6bd840b36f498c5e0721ba3bb4d30eabd..162544e19bbe06397b83cb1828d128e5e38d027c 100644
--- a/spec/frontend/boards/board_card_inner_spec.js
+++ b/spec/frontend/boards/board_card_inner_spec.js
@@ -10,7 +10,6 @@ import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/i
 import BoardCardInner from '~/boards/components/board_card_inner.vue';
 import isShowingLabelsQuery from '~/graphql_shared/client/is_showing_labels.query.graphql';
 import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
-import eventHub from '~/boards/eventhub';
 import { TYPE_ISSUE } from '~/issues/constants';
 import { updateHistory } from '~/lib/utils/url_utility';
 import { mockLabelList, mockIssue, mockIssueFullPath, mockIssueDirectNamespace } from './mock_data';
@@ -436,9 +435,8 @@ describe('Board card component', () => {
         expect(updateHistory).toHaveBeenCalledTimes(1);
       });
 
-      it('emits updateTokens event', () => {
-        expect(eventHub.$emit).toHaveBeenCalledTimes(1);
-        expect(eventHub.$emit).toHaveBeenCalledWith('updateTokens');
+      it('emits setFilters event', () => {
+        expect(wrapper.emitted('setFilters').length).toBe(1);
       });
     });
 
@@ -452,8 +450,8 @@ describe('Board card component', () => {
         expect(updateHistory).not.toHaveBeenCalled();
       });
 
-      it('does not emit updateTokens event', () => {
-        expect(eventHub.$emit).not.toHaveBeenCalled();
+      it('does not emit setFilters event', () => {
+        expect(wrapper.emitted('setFilters')).toBeUndefined();
       });
     });
   });
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index a43d94e9b2d920b2b0b070e03b8683e5cfd8469f..40c6857194356a0bc4289119dbc08e63935247aa 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -8,11 +8,10 @@ import createComponent from 'jest/boards/board_list_helper';
 import { ESC_KEY_CODE } from '~/lib/utils/keycodes';
 import BoardCard from '~/boards/components/board_card.vue';
 import BoardCutLine from '~/boards/components/board_cut_line.vue';
-import eventHub from '~/boards/eventhub';
 import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue';
 import listIssuesQuery from '~/boards/graphql/lists_issues.query.graphql';
 
-import { mockIssues, mockList, mockIssuesMore, mockGroupIssuesResponse } from './mock_data';
+import { mockIssues, mockIssuesMore, mockGroupIssuesResponse } from './mock_data';
 
 describe('Board list component', () => {
   let wrapper;
@@ -75,8 +74,10 @@ describe('Board list component', () => {
       expect(wrapper.find('.board-card').attributes('data-item-id')).toBe('gid://gitlab/Issue/436');
     });
 
-    it('shows new issue form after eventhub event', async () => {
-      eventHub.$emit(`toggle-issue-form-${mockList.id}`);
+    it('shows new issue form when showNewForm prop is true', async () => {
+      wrapper = createComponent({
+        componentProps: { showNewForm: true },
+      });
 
       await nextTick();
       expect(wrapper.find('.board-new-issue-form').exists()).toBe(true);
@@ -87,12 +88,10 @@ describe('Board list component', () => {
         listProps: {
           listType: ListType.closed,
         },
+        componentProps: { showNewForm: true },
       });
       await waitForPromises();
 
-      eventHub.$emit(`toggle-issue-form-${mockList.id}`);
-
-      await nextTick();
       expect(wrapper.find('.board-new-issue-form').exists()).toBe(false);
     });
 
diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js
index 5e96b508f37a3d66cd965f853533554a7fed6cd1..dbc9b42380b97b78b5cf096275ad58a529be8129 100644
--- a/spec/frontend/boards/components/board_filtered_search_spec.js
+++ b/spec/frontend/boards/components/board_filtered_search_spec.js
@@ -65,6 +65,7 @@ describe('BoardFilteredSearch', () => {
       propsData: {
         ...props,
         tokens,
+        filters: {},
       },
     });
   };
diff --git a/spec/frontend/boards/components/board_new_issue_spec.js b/spec/frontend/boards/components/board_new_issue_spec.js
index dad0d148449320ab8520268d8c60a910938807c4..0c764537a246a766eda2d81e27f876558b921c28 100644
--- a/spec/frontend/boards/components/board_new_issue_spec.js
+++ b/spec/frontend/boards/components/board_new_issue_spec.js
@@ -5,7 +5,6 @@ import createMockApollo from 'helpers/mock_apollo_helper';
 import BoardNewIssue from '~/boards/components/board_new_issue.vue';
 import BoardNewItem from '~/boards/components/board_new_item.vue';
 import ProjectSelect from '~/boards/components/project_select.vue';
-import eventHub from '~/boards/eventhub';
 import groupBoardQuery from '~/boards/graphql/group_board.query.graphql';
 import projectBoardQuery from '~/boards/graphql/project_board.query.graphql';
 import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants';
@@ -96,18 +95,16 @@ describe('Issue boards new issue form', () => {
     expect(boardNewItem.exists()).toBe(true);
     expect(boardNewItem.props()).toEqual({
       list: mockList,
-      formEventPrefix: 'toggle-issue-form-',
       submitButtonTitle: 'Create issue',
       disableSubmit: false,
     });
   });
 
-  it('emits event `toggle-issue-form` with current list Id suffix on eventHub when `board-new-item` emits form-cancel event', async () => {
-    jest.spyOn(eventHub, '$emit').mockImplementation();
+  it('emits event `toggleNewForm` when `board-new-item` emits form-cancel event', async () => {
     findBoardNewItem().vm.$emit('form-cancel');
 
     await nextTick();
-    expect(eventHub.$emit).toHaveBeenCalledWith(`toggle-issue-form-${mockList.id}`);
+    expect(wrapper.emitted('toggleNewForm')).toHaveLength(1);
   });
 
   describe('when in group issue board', () => {
diff --git a/spec/frontend/boards/components/board_new_item_spec.js b/spec/frontend/boards/components/board_new_item_spec.js
index 23acba3595adf504d98c53f01dbed22743f49326..00537cdf5a06223eb27085e09729a413744a685e 100644
--- a/spec/frontend/boards/components/board_new_item_spec.js
+++ b/spec/frontend/boards/components/board_new_item_spec.js
@@ -8,14 +8,12 @@ import { mockList } from '../mock_data';
 
 const createComponent = ({
   list = mockList,
-  formEventPrefix = 'toggle-issue-form-',
   disabledSubmit = false,
   submitButtonTitle = 'Create item',
 } = {}) =>
   mountExtended(BoardNewItem, {
     propsData: {
       list,
-      formEventPrefix,
       disabledSubmit,
       submitButtonTitle,
     },
diff --git a/spec/frontend/boards/components/board_top_bar_spec.js b/spec/frontend/boards/components/board_top_bar_spec.js
index 332f6548502bfa3759bb659ab7bc16d81374ce35..c759f0b3430b51281de0402a462a2052760fe16a 100644
--- a/spec/frontend/boards/components/board_top_bar_spec.js
+++ b/spec/frontend/boards/components/board_top_bar_spec.js
@@ -45,6 +45,7 @@ describe('BoardTopBar', () => {
         boardId: 'gid://gitlab/Board/1',
         isSwimlanesOn: false,
         addColumnFormVisible: false,
+        filters: {},
       },
       provide: {
         swimlanesFeatureAvailable: false,