From aae90f477fa02f1d893f0190348cd164e7f614b3 Mon Sep 17 00:00:00 2001
From: Alexander Haller <alex@baserow.io>
Date: Wed, 20 Jul 2022 18:07:00 +0000
Subject: [PATCH] Remove primary from table

---
 changelog.md                                  |   1 +
 .../ConditionalColorValueProviderForm.vue     |  14 +-
 .../SingleSelectColorValueProviderForm.vue    |   6 +-
 .../components/views/kanban/KanbanView.vue    |  20 +-
 .../kanban/KanbanViewCreateStackContext.vue   |   5 -
 .../views/kanban/KanbanViewHeader.vue         |  17 +-
 .../views/kanban/KanbanViewStack.vue          |  12 +-
 .../views/kanban/KanbanViewStackContext.vue   |   6 -
 .../views/kanban/KanbanViewStackedBy.vue      |  11 +-
 .../kanban/KanbanViewUpdateStackContext.vue   |   5 -
 .../baserow_premium/store/view/kanban.js      |  68 ++---
 .../modules/baserow_premium/viewTypes.js      |  12 +-
 .../unit/premium/store/view/kanban.spec.js    |  36 ---
 .../database/components/field/FieldForm.vue   |   2 +-
 .../components/field/FieldFormulaSubForm.vue  |   2 +-
 .../components/field/FileFieldModal.vue       |   1 +
 .../components/row/ForeignRowEditModal.vue    |  10 +-
 .../components/row/RowCreateModal.vue         |  20 +-
 .../database/components/row/RowEditModal.vue  |  39 +--
 .../database/components/table/Table.vue       |  10 -
 .../components/table/TableTemplate.vue        |  10 +-
 .../components/view/ViewDecoratorContext.vue  |   7 +-
 .../components/view/ViewDecoratorMenu.vue     |   5 -
 .../view/ViewFieldConditionsForm.vue          |  29 +-
 .../database/components/view/ViewFilter.vue   |   5 -
 .../components/view/ViewFilterForm.vue        |  11 +-
 .../view/ViewFilterTypeFileTypeDropdown.vue   |   4 -
 .../database/components/view/ViewSearch.vue   |   5 -
 .../components/view/ViewSearchContext.vue     |   6 -
 .../database/components/view/ViewSort.vue     |   5 -
 .../components/view/ViewSortContext.vue       |  30 +-
 .../components/view/form/FormView.vue         |   5 -
 .../components/view/form/FormViewHeader.vue   |   4 -
 .../components/view/gallery/GalleryView.vue   |  20 +-
 .../view/gallery/GalleryViewHeader.vue        |  10 +-
 .../components/view/grid/GridView.vue         |  44 ++-
 .../components/view/grid/GridViewHeader.vue   |  10 +-
 .../view/grid/GridViewRowDragging.vue         |   8 +-
 .../components/webhook/WebhookForm.vue        |   2 +-
 .../mixins/bufferedRowsDragAndDrop.js         |   1 -
 .../modules/database/mixins/viewDecoration.js |   9 +-
 .../modules/database/mixins/viewFilter.js     |  11 +-
 .../modules/database/pages/publicGridView.vue |  10 +-
 web-frontend/modules/database/pages/table.vue |   4 +-
 web-frontend/modules/database/realtime.js     |   3 -
 web-frontend/modules/database/store/field.js  |  36 +--
 .../database/store/view/bufferedRows.js       |  75 ++---
 .../modules/database/store/view/gallery.js    |   3 +-
 .../modules/database/store/view/grid.js       | 126 ++++-----
 web-frontend/modules/database/utils/field.js  |  10 +
 web-frontend/modules/database/utils/view.js   |  12 +-
 web-frontend/modules/database/viewTypes.js    |  56 +---
 .../__snapshots__/viewFilterForm.spec.js.snap |   4 -
 .../gallery/galleryViewDecoration.spec.js     |  13 +-
 .../view/grid/gridViewDecoration.spec.js      |  11 +-
 .../view/viewDecoratorContext.spec.js         |  14 +-
 .../components/view/viewFilterForm.spec.js    |  26 +-
 .../database/store/view/bufferedRows.spec.js  | 260 +++++++-----------
 .../unit/database/store/view/grid.spec.js     |  71 ++---
 .../test/unit/database/utils/field.spec.js    |  42 +++
 .../test/unit/database/viewFilters.spec.js    |  14 +-
 61 files changed, 426 insertions(+), 902 deletions(-)
 create mode 100644 web-frontend/modules/database/utils/field.js
 create mode 100644 web-frontend/test/unit/database/utils/field.spec.js

diff --git a/changelog.md b/changelog.md
index b660a1cf0..47a1d4beb 100644
--- a/changelog.md
+++ b/changelog.md
@@ -29,6 +29,7 @@ For example:
 
 ### Breaking Changes
 * API endpoints `undo` and `redo` now returns a list of actions undone/redone instead of a single action.
+* Removed `primary` from all `components`and `stores` where it isn't absolutely required. [#1057](https://gitlab.com/bramw/baserow/-/issues/1057)
 
 * **breaking change** Webhooks `row.created`, `row.updated` and `row.deleted` are
   replaced with `rows.created`, `rows.updated` and `rows.deleted`, containing multiple
diff --git a/premium/web-frontend/modules/baserow_premium/components/views/ConditionalColorValueProviderForm.vue b/premium/web-frontend/modules/baserow_premium/components/views/ConditionalColorValueProviderForm.vue
index 6c8cbd246..6f654df6b 100644
--- a/premium/web-frontend/modules/baserow_premium/components/views/ConditionalColorValueProviderForm.vue
+++ b/premium/web-frontend/modules/baserow_premium/components/views/ConditionalColorValueProviderForm.vue
@@ -46,7 +46,6 @@
           :filters="color.filters"
           :disable-filter="false"
           :filter-type="color.operator"
-          :primary="primary"
           :fields="fields"
           :view="view"
           :read-only="readOnly"
@@ -95,10 +94,6 @@ export default {
       type: Object,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -108,11 +103,6 @@ export default {
       required: true,
     },
   },
-  computed: {
-    allFields() {
-      return [this.primary, ...this.fields]
-    },
-  },
   methods: {
     orderColor(colorIds) {
       const newColors = colorIds.map((colorId) =>
@@ -138,7 +128,7 @@ export default {
           ConditionalColorValueProviderType.getDefaultColorConf(
             this.$registry,
             {
-              fields: this.allFields,
+              fields: this.fields,
             },
             true
           ),
@@ -176,7 +166,7 @@ export default {
               ConditionalColorValueProviderType.getDefaultFilterConf(
                 this.$registry,
                 {
-                  fields: this.allFields,
+                  fields: this.fields,
                 }
               ),
             ],
diff --git a/premium/web-frontend/modules/baserow_premium/components/views/SingleSelectColorValueProviderForm.vue b/premium/web-frontend/modules/baserow_premium/components/views/SingleSelectColorValueProviderForm.vue
index 961a81a90..b7cf687af 100644
--- a/premium/web-frontend/modules/baserow_premium/components/views/SingleSelectColorValueProviderForm.vue
+++ b/premium/web-frontend/modules/baserow_premium/components/views/SingleSelectColorValueProviderForm.vue
@@ -33,10 +33,6 @@ export default {
       type: Object,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -48,7 +44,7 @@ export default {
   },
   computed: {
     selectFields() {
-      return [this.primary, ...this.fields].filter(
+      return this.fields.filter(
         ({ type }) => type === SingleSelectFieldType.getType()
       )
     },
diff --git a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanView.vue b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanView.vue
index fc040fbe9..724966713 100644
--- a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanView.vue
+++ b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanView.vue
@@ -4,7 +4,6 @@
       :table="table"
       :view="view"
       :fields="fields"
-      :primary="primary"
       :read-only="readOnly"
       :store-prefix="storePrefix"
       :include-field-options-on-refresh="true"
@@ -29,7 +28,6 @@
         :view="view"
         :card-fields="cardFields"
         :fields="fields"
-        :primary="primary"
         :read-only="readOnly"
         :store-prefix="storePrefix"
         @create-row="openCreateRowModal"
@@ -45,7 +43,6 @@
         :view="view"
         :card-fields="cardFields"
         :fields="fields"
-        :primary="primary"
         :read-only="readOnly"
         :store-prefix="storePrefix"
         @create-row="openCreateRowModal"
@@ -63,14 +60,12 @@
       <KanbanViewCreateStackContext
         ref="addOptionContext"
         :fields="fields"
-        :primary="primary"
         :store-prefix="storePrefix"
       ></KanbanViewCreateStackContext>
     </div>
     <RowCreateModal
       ref="rowCreateModal"
       :table="table"
-      :primary="primary"
       :primary-is-sortable="true"
       :visible-fields="cardFields"
       :hidden-fields="hiddenFields"
@@ -88,7 +83,6 @@
       ref="rowEditModal"
       :database="database"
       :table="table"
-      :primary="primary"
       :primary-is-sortable="true"
       :visible-fields="cardFields"
       :hidden-fields="hiddenFields"
@@ -155,10 +149,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     readOnly: {
       type: Boolean,
       required: true,
@@ -176,15 +166,13 @@ export default {
      */
     cardFields() {
       const fieldOptions = this.fieldOptions
-      return [this.primary]
-        .concat(this.fields)
+      return this.fields
         .filter(filterVisibleFieldsFunction(fieldOptions))
         .sort(sortFieldsByOrderAndIdFunction(fieldOptions))
     },
     hiddenFields() {
       const fieldOptions = this.fieldOptions
-      return [this.primary]
-        .concat(this.fields)
+      return this.fields
         .filter(filterHiddenFieldsFunction(fieldOptions))
         .sort(sortFieldsByOrderAndIdFunction(fieldOptions))
     },
@@ -193,7 +181,7 @@ export default {
      * cards in stacks.
      */
     singleSelectField() {
-      const allFields = [this.primary].concat(this.fields)
+      const allFields = this.fields
       for (let i = 0; i < allFields.length; i++) {
         if (allFields[i].id === this.singleSelectFieldId) {
           return allFields[i]
@@ -239,7 +227,6 @@ export default {
             view: this.view,
             table: this.table,
             fields: this.fields,
-            primary: this.primary,
             values: row,
           }
         )
@@ -256,7 +243,6 @@ export default {
             table: this.table,
             view: this.view,
             fields: this.fields,
-            primary: this.primary,
             row,
             field,
             value,
diff --git a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewCreateStackContext.vue b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewCreateStackContext.vue
index 94ebb2b04..5d152c080 100644
--- a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewCreateStackContext.vue
+++ b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewCreateStackContext.vue
@@ -28,10 +28,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     storePrefix: {
       type: String,
       required: true,
@@ -51,7 +47,6 @@ export default {
           this.storePrefix + 'view/kanban/createStack',
           {
             fields: this.fields,
-            primary: this.primary,
             color: values.color,
             value: values.value,
           }
diff --git a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewHeader.vue b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewHeader.vue
index 21efd2a0a..cc20f218e 100644
--- a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewHeader.vue
+++ b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewHeader.vue
@@ -30,7 +30,6 @@
           :table="table"
           :view="view"
           :fields="fields"
-          :primary="primary"
           :read-only="readOnly"
           :store-prefix="storePrefix"
           @refresh="$emit('refresh', $event)"
@@ -57,7 +56,7 @@
       </a>
       <ViewFieldsContext
         ref="customizeContext"
-        :fields="allFields"
+        :fields="fields"
         :read-only="readOnly"
         :field-options="fieldOptions"
         :cover-image-field="view.card_cover_image_field"
@@ -100,10 +99,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     readOnly: {
       type: Boolean,
       required: true,
@@ -111,17 +106,13 @@ export default {
   },
   computed: {
     stackedByFieldName() {
-      const allFields = [this.primary].concat(this.fields)
-      for (let i = 0; i < allFields.length; i++) {
-        if (allFields[i].id === this.view.single_select_field) {
-          return allFields[i].name
+      for (let i = 0; i < this.fields.length; i++) {
+        if (this.fields[i].id === this.view.single_select_field) {
+          return this.fields[i].name
         }
       }
       return ''
     },
-    allFields() {
-      return [this.primary].concat(this.fields)
-    },
     ...mapState({
       tableLoading: (state) => state.table.loading,
     }),
diff --git a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStack.vue b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStack.vue
index bbfd23dde..7e721ff7c 100644
--- a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStack.vue
+++ b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStack.vue
@@ -52,7 +52,6 @@
           ref="editContext"
           :option="option"
           :fields="fields"
-          :primary="primary"
           :store-prefix="storePrefix"
           @create-row="$emit('create-row', { option })"
           @refresh="$emit('refresh', $event)"
@@ -167,10 +166,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     readOnly: {
       type: Boolean,
       required: true,
@@ -229,11 +224,7 @@ export default {
     },
     coverImageField() {
       const fieldId = this.view.card_cover_image_field
-      return (
-        [this.primary]
-          .concat(this.fields)
-          .find((field) => field.id === fieldId) || null
-      )
+      return this.fields.find((field) => field.id === fieldId) || null
     },
   },
   watch: {
@@ -358,7 +349,6 @@ export default {
             {
               table: this.table,
               fields: this.fields,
-              primary: this.primary,
             }
           )
         } catch (error) {
diff --git a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStackContext.vue b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStackContext.vue
index 6cb9ce4ba..69adbcce8 100644
--- a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStackContext.vue
+++ b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStackContext.vue
@@ -19,7 +19,6 @@
           ref="updateContext"
           :option="option"
           :fields="fields"
-          :primary="primary"
           :store-prefix="storePrefix"
           @saved="hide()"
         ></KanbanViewUpdateStackContext>
@@ -79,10 +78,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     storePrefix: {
       type: String,
       required: true,
@@ -103,7 +98,6 @@ export default {
           {
             optionId: this.option.id,
             fields: this.fields,
-            primary: this.primary,
             deferredFieldUpdate: true,
           }
         )
diff --git a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStackedBy.vue b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStackedBy.vue
index c62dfd297..27af2c550 100644
--- a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStackedBy.vue
+++ b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewStackedBy.vue
@@ -9,7 +9,7 @@
     <ChooseSingleSelectField
       :view="view"
       :table="table"
-      :fields="allFields"
+      :fields="fields"
       :value="view.single_select_field"
       :read-only="readOnly"
       :loading="loading"
@@ -39,10 +39,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     readOnly: {
       type: Boolean,
       required: true,
@@ -58,11 +54,6 @@ export default {
       loading: false,
     }
   },
-  computed: {
-    allFields() {
-      return [this.primary, ...this.fields]
-    },
-  },
   methods: {
     async update(value) {
       this.loading = true
diff --git a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewUpdateStackContext.vue b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewUpdateStackContext.vue
index 4b7af8b74..72998cf78 100644
--- a/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewUpdateStackContext.vue
+++ b/premium/web-frontend/modules/baserow_premium/components/views/kanban/KanbanViewUpdateStackContext.vue
@@ -36,10 +36,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     storePrefix: {
       type: String,
       required: true,
@@ -60,7 +56,6 @@ export default {
           {
             optionId: this.option.id,
             fields: this.fields,
-            primary: this.primary,
             values,
           }
         )
diff --git a/premium/web-frontend/modules/baserow_premium/store/view/kanban.js b/premium/web-frontend/modules/baserow_premium/store/view/kanban.js
index a5d04669c..467bf81b3 100644
--- a/premium/web-frontend/modules/baserow_premium/store/view/kanban.js
+++ b/premium/web-frontend/modules/baserow_premium/store/view/kanban.js
@@ -331,12 +331,11 @@ export const actions = {
    */
   async createNewRow(
     { dispatch, commit, getters },
-    { view, table, fields, primary, values }
+    { view, table, fields, values }
   ) {
     // First prepare an object that we can send to the
-    const allFields = [primary].concat(fields)
     const preparedValues = {}
-    allFields.forEach((field) => {
+    fields.forEach((field) => {
       const name = `field_${field.id}`
       const fieldType = this.$registry.get('field', field._.type.type)
 
@@ -360,7 +359,6 @@ export const actions = {
       view,
       values: data,
       fields,
-      primary,
     })
   },
   /**
@@ -376,7 +374,7 @@ export const actions = {
    */
   async createdNewRow(
     { dispatch, commit, getters, rootGetters },
-    { view, values, fields, primary }
+    { view, values, fields }
   ) {
     const row = clone(values)
     populateRow(row)
@@ -385,7 +383,6 @@ export const actions = {
       view,
       row,
       fields,
-      primary,
     })
     if (!matchesFilters) {
       return
@@ -398,7 +395,7 @@ export const actions = {
 
     const sortedRows = clone(stack.results)
     sortedRows.push(row)
-    sortedRows.sort(getRowSortFunction(this.$registry, [], fields, primary))
+    sortedRows.sort(getRowSortFunction(this.$registry, [], fields))
     const index = sortedRows.findIndex((r) => r.id === row.id)
     const isLast = index === sortedRows.length - 1
 
@@ -420,7 +417,7 @@ export const actions = {
    */
   async deletedExistingRow(
     { dispatch, commit, getters },
-    { view, row, fields, primary }
+    { view, row, fields }
   ) {
     row = clone(row)
     populateRow(row)
@@ -429,7 +426,6 @@ export const actions = {
       view,
       row,
       fields,
-      primary,
     })
     if (!matchesFilters) {
       return
@@ -456,7 +452,7 @@ export const actions = {
   /**
    * Check if the provided row matches the provided view filters.
    */
-  rowMatchesFilters(context, { view, fields, primary, row, overrides = {} }) {
+  rowMatchesFilters(context, { view, fields, row, overrides = {} }) {
     const values = JSON.parse(JSON.stringify(row))
     Object.assign(values, overrides)
 
@@ -467,7 +463,7 @@ export const actions = {
           this.$registry,
           view.filter_type,
           view.filters,
-          primary === null ? fields : [primary, ...fields],
+          fields,
           values
         )
   },
@@ -479,7 +475,7 @@ export const actions = {
    */
   async updatedExistingRow(
     { dispatch, getters, commit },
-    { view, row, values, fields, primary }
+    { view, row, values, fields }
   ) {
     const singleSelectFieldId = getters.getSingleSelectFieldId
     const fieldName = `field_${singleSelectFieldId}`
@@ -490,7 +486,6 @@ export const actions = {
       view,
       row: oldRow,
       fields,
-      primary,
     })
     const oldOption = oldRow[fieldName]
     const oldStackId = oldOption !== null ? oldOption.id : 'null'
@@ -506,7 +501,6 @@ export const actions = {
       view,
       row: newRow,
       fields,
-      primary,
     })
     const newOption = newRow[fieldName]
     const newStackId = newOption !== null ? newOption.id : 'null'
@@ -522,9 +516,7 @@ export const actions = {
     }
     newStackResults.push(newRow)
     newStackCount++
-    newStackResults.sort(
-      getRowSortFunction(this.$registry, [], fields, primary)
-    )
+    newStackResults.sort(getRowSortFunction(this.$registry, [], fields))
     const newIndex = newStackResults.findIndex((r) => r.id === newRow.id)
     const newIsLast = newIndex === newStackResults.length - 1
     const newExists =
@@ -580,7 +572,7 @@ export const actions = {
    * need to updated and will make a call to the backend. If something goes wrong,
    * the row is moved back to the original stack and position.
    */
-  async stopRowDrag({ dispatch, commit, getters }, { table, fields, primary }) {
+  async stopRowDrag({ dispatch, commit, getters }, { table, fields }) {
     const row = getters.getDraggingRow
 
     if (row === null) {
@@ -601,9 +593,9 @@ export const actions = {
     // We need to have the single select option field instance because we need
     // access to the available options. We can figure that out by looking looping
     // over the provided fields.
-    const singleSelectField = [primary]
-      .concat(fields)
-      .find((field) => field.id === getters.getSingleSelectFieldId)
+    const singleSelectField = fields.find(
+      (field) => field.id === getters.getSingleSelectFieldId
+    )
     const singleSelectFieldType = this.$registry.get(
       'field',
       SingleSelectFieldType.getType()
@@ -755,10 +747,9 @@ export const actions = {
    */
   async updateRowValue(
     { commit, dispatch },
-    { view, table, row, field, fields, primary, value, oldValue }
+    { view, table, row, field, fields, value, oldValue }
   ) {
     const fieldType = this.$registry.get('field', field._.type.type)
-    const allFields = [primary].concat(fields)
     const newValues = {}
     const newValuesForUpdate = {}
     const oldValues = {}
@@ -770,7 +761,7 @@ export const actions = {
     )
     oldValues[fieldName] = oldValue
 
-    allFields.forEach((fieldToCall) => {
+    fields.forEach((fieldToCall) => {
       const fieldType = this.$registry.get('field', fieldToCall._.type.type)
       const fieldToCallName = `field_${fieldToCall.id}`
       const currentFieldValue = row[fieldToCallName]
@@ -791,7 +782,6 @@ export const actions = {
       row,
       values: newValues,
       fields,
-      primary,
     })
 
     try {
@@ -807,7 +797,6 @@ export const actions = {
         row,
         values: oldValues,
         fields,
-        primary,
       })
       throw error
     }
@@ -816,13 +805,10 @@ export const actions = {
    * Creates a new stack by updating the related field option of the view's
    * field. The values in the store also be updated accordingly.
    */
-  async createStack(
-    { getters, commit, dispatch },
-    { fields, primary, color, value }
-  ) {
-    const field = [primary]
-      .concat(fields)
-      .find((field) => field.id === getters.getSingleSelectFieldId)
+  async createStack({ getters, commit, dispatch }, { fields, color, value }) {
+    const field = fields.find(
+      (field) => field.id === getters.getSingleSelectFieldId
+    )
 
     const updateValues = {
       type: field.type,
@@ -868,11 +854,11 @@ export const actions = {
    */
   async updateStack(
     { getters, commit, dispatch },
-    { fields, primary, optionId, values }
+    { fields, optionId, values }
   ) {
-    const field = [primary]
-      .concat(fields)
-      .find((field) => field.id === getters.getSingleSelectFieldId)
+    const field = fields.find(
+      (field) => field.id === getters.getSingleSelectFieldId
+    )
 
     const options = clone(field.select_options)
     const index = options.findIndex((o) => o.id === optionId)
@@ -911,11 +897,11 @@ export const actions = {
    */
   async deleteStack(
     { getters, commit, dispatch },
-    { fields, primary, optionId, deferredFieldUpdate = false }
+    { fields, optionId, deferredFieldUpdate = false }
   ) {
-    const field = [primary]
-      .concat(fields)
-      .find((field) => field.id === getters.getSingleSelectFieldId)
+    const field = fields.find(
+      (field) => field.id === getters.getSingleSelectFieldId
+    )
 
     const options = clone(field.select_options)
     const index = options.findIndex((o) => o.id === optionId)
diff --git a/premium/web-frontend/modules/baserow_premium/viewTypes.js b/premium/web-frontend/modules/baserow_premium/viewTypes.js
index c7185b815..16809d38a 100644
--- a/premium/web-frontend/modules/baserow_premium/viewTypes.js
+++ b/premium/web-frontend/modules/baserow_premium/viewTypes.js
@@ -54,7 +54,7 @@ export class KanbanViewType extends PremiumViewType {
     return KanbanView
   }
 
-  async fetch({ store }, view, fields, primary, storePrefix = '') {
+  async fetch({ store }, view, fields, storePrefix = '') {
     // If the single select field is `null` we can't fetch the initial data anyway,
     // we don't have to do anything. The KanbanView component will handle it by
     // showing a form to choose or create a single select field.
@@ -72,7 +72,6 @@ export class KanbanViewType extends PremiumViewType {
     { store },
     view,
     fields,
-    primary,
     storePrefix = '',
     includeFieldOptions = false
   ) {
@@ -113,7 +112,6 @@ export class KanbanViewType extends PremiumViewType {
     { store },
     tableId,
     fields,
-    primary,
     values,
     metadata,
     storePrefix = ''
@@ -121,9 +119,8 @@ export class KanbanViewType extends PremiumViewType {
     if (this.isCurrentView(store, tableId)) {
       await store.dispatch(storePrefix + 'view/kanban/createdNewRow', {
         view: store.getters['view/getSelected'],
-        fields,
-        primary,
         values,
+        fields,
       })
     }
   }
@@ -132,7 +129,6 @@ export class KanbanViewType extends PremiumViewType {
     { store },
     tableId,
     fields,
-    primary,
     row,
     values,
     metadata,
@@ -142,20 +138,18 @@ export class KanbanViewType extends PremiumViewType {
       await store.dispatch(storePrefix + 'view/kanban/updatedExistingRow', {
         view: store.getters['view/getSelected'],
         fields,
-        primary,
         row,
         values,
       })
     }
   }
 
-  async rowDeleted({ store }, tableId, fields, primary, row, storePrefix = '') {
+  async rowDeleted({ store }, tableId, fields, row, storePrefix = '') {
     if (this.isCurrentView(store, tableId)) {
       await store.dispatch(storePrefix + 'view/kanban/deletedExistingRow', {
         view: store.getters['view/getSelected'],
         row,
         fields,
-        primary,
       })
     }
   }
diff --git a/premium/web-frontend/test/unit/premium/store/view/kanban.spec.js b/premium/web-frontend/test/unit/premium/store/view/kanban.spec.js
index 0f7858453..9168bca21 100644
--- a/premium/web-frontend/test/unit/premium/store/view/kanban.spec.js
+++ b/premium/web-frontend/test/unit/premium/store/view/kanban.spec.js
@@ -40,14 +40,6 @@ describe('Kanban view store', () => {
     store.registerModule('kanban', kanbanStore)
 
     const fields = []
-    const primary = {
-      id: 1,
-      name: 'Single select',
-      type: 'single_select',
-      options: [{ id: 1, color: 'blue', value: '' }],
-      primary: true,
-    }
-
     await store.dispatch('kanban/createdNewRow', {
       view,
       values: {
@@ -56,7 +48,6 @@ describe('Kanban view store', () => {
         field_1: null,
       },
       fields,
-      primary,
     })
     await store.dispatch('kanban/createdNewRow', {
       view,
@@ -66,7 +57,6 @@ describe('Kanban view store', () => {
         field_1: null,
       },
       fields,
-      primary,
     })
 
     expect(store.state.kanban.stacks.null.count).toBe(3)
@@ -83,7 +73,6 @@ describe('Kanban view store', () => {
         field_1: { id: 1 },
       },
       fields,
-      primary,
     })
     await store.dispatch('kanban/createdNewRow', {
       view,
@@ -93,7 +82,6 @@ describe('Kanban view store', () => {
         field_1: { id: 1 },
       },
       fields,
-      primary,
     })
 
     expect(store.state.kanban.stacks['1'].count).toBe(102)
@@ -125,13 +113,6 @@ describe('Kanban view store', () => {
     store.registerModule('kanban', kanbanStore)
 
     const fields = []
-    const primary = {
-      id: 1,
-      name: 'Single select',
-      type: 'single_select',
-      options: [{ id: 1, color: 'blue', value: '' }],
-      primary: true,
-    }
 
     await store.dispatch('kanban/deletedExistingRow', {
       view,
@@ -141,7 +122,6 @@ describe('Kanban view store', () => {
         field_1: null,
       },
       fields,
-      primary,
     })
 
     expect(store.state.kanban.stacks.null.count).toBe(0)
@@ -155,7 +135,6 @@ describe('Kanban view store', () => {
         field_1: { id: 1 },
       },
       fields,
-      primary,
     })
     await store.dispatch('kanban/deletedExistingRow', {
       view,
@@ -165,7 +144,6 @@ describe('Kanban view store', () => {
         field_1: { id: 1 },
       },
       fields,
-      primary,
     })
 
     expect(store.state.kanban.stacks['1'].count).toBe(98)
@@ -200,13 +178,6 @@ describe('Kanban view store', () => {
     store.registerModule('kanban', kanbanStore)
 
     const fields = []
-    const primary = {
-      id: 1,
-      name: 'Single select',
-      type: 'single_select',
-      options: [{ id: 1, color: 'blue', value: '' }],
-      primary: true,
-    }
 
     // Should be moved to the first in the buffer
     await store.dispatch('kanban/updatedExistingRow', {
@@ -216,7 +187,6 @@ describe('Kanban view store', () => {
         order: '9.00',
       },
       fields,
-      primary,
     })
     // Should be completely ignored because it's outside of the buffer
     await store.dispatch('kanban/updatedExistingRow', {
@@ -226,7 +196,6 @@ describe('Kanban view store', () => {
         order: '13.00',
       },
       fields,
-      primary,
     })
     // Did not exist before, but has moved within the buffer.
     await store.dispatch('kanban/updatedExistingRow', {
@@ -236,7 +205,6 @@ describe('Kanban view store', () => {
         order: '8.00',
       },
       fields,
-      primary,
     })
 
     expect(store.state.kanban.stacks['1'].count).toBe(101)
@@ -255,7 +223,6 @@ describe('Kanban view store', () => {
         field_1: null,
       },
       fields,
-      primary,
     })
     // Moved to stack `null`, because the position is within the buffer, we expect
     // it to be added to it.
@@ -267,7 +234,6 @@ describe('Kanban view store', () => {
         order: '1.00',
       },
       fields,
-      primary,
     })
 
     expect(store.state.kanban.stacks.null.count).toBe(3)
@@ -290,7 +256,6 @@ describe('Kanban view store', () => {
         field_1: { id: 1 },
       },
       fields,
-      primary,
     })
     // Moved to stack `1`, because the position is outside the buffer, we expect it
     // not to be in there.
@@ -301,7 +266,6 @@ describe('Kanban view store', () => {
         field_1: { id: 1 },
       },
       fields,
-      primary,
     })
 
     expect(store.state.kanban.stacks.null.count).toBe(1)
diff --git a/web-frontend/modules/database/components/field/FieldForm.vue b/web-frontend/modules/database/components/field/FieldForm.vue
index cccf6012b..6ada5d0b9 100644
--- a/web-frontend/modules/database/components/field/FieldForm.vue
+++ b/web-frontend/modules/database/components/field/FieldForm.vue
@@ -128,7 +128,7 @@ export default {
       return this.defaultValues ? this.defaultValues.id : null
     },
     ...mapGetters({
-      fields: 'field/getAllWithPrimary',
+      fields: 'field/getAll',
     }),
   },
   validations() {
diff --git a/web-frontend/modules/database/components/field/FieldFormulaSubForm.vue b/web-frontend/modules/database/components/field/FieldFormulaSubForm.vue
index fa5d1525b..e54f5c27e 100644
--- a/web-frontend/modules/database/components/field/FieldFormulaSubForm.vue
+++ b/web-frontend/modules/database/components/field/FieldFormulaSubForm.vue
@@ -69,7 +69,7 @@ export default {
   },
   computed: {
     ...mapGetters({
-      rawFields: 'field/getAllWithPrimary',
+      rawFields: 'field/getAll',
     }),
     localOrServerFormulaType() {
       return (
diff --git a/web-frontend/modules/database/components/field/FileFieldModal.vue b/web-frontend/modules/database/components/field/FileFieldModal.vue
index c5f6fcab4..40429a905 100644
--- a/web-frontend/modules/database/components/field/FileFieldModal.vue
+++ b/web-frontend/modules/database/components/field/FileFieldModal.vue
@@ -131,6 +131,7 @@ export default {
     return {
       renaming: false,
       selected: 0,
+      canClose: true,
     }
   },
   computed: {
diff --git a/web-frontend/modules/database/components/row/ForeignRowEditModal.vue b/web-frontend/modules/database/components/row/ForeignRowEditModal.vue
index 44a9c184c..de0f2213a 100644
--- a/web-frontend/modules/database/components/row/ForeignRowEditModal.vue
+++ b/web-frontend/modules/database/components/row/ForeignRowEditModal.vue
@@ -6,7 +6,6 @@
     :table="table"
     :rows="[]"
     :visible-fields="fields"
-    :primary="primary"
     @hidden="$emit('hidden', $event)"
   ></RowEditModal>
 </template>
@@ -37,7 +36,6 @@ export default {
       fetchedTableAndFields: false,
       table: {},
       fields: [],
-      primary: undefined,
     }
   },
   computed: {
@@ -88,13 +86,7 @@ export default {
       fieldData.forEach((part, index) => {
         populateField(fieldData[index], this.$registry)
       })
-      const primaryIndex = fieldData.findIndex((item) => item.primary === true)
-      if (primaryIndex !== -1) {
-        this.primary = fieldData.splice(primaryIndex, 1)[0]
-        this.fields = [this.primary, ...fieldData]
-      } else {
-        this.fields = fieldData
-      }
+      this.fields = fieldData
 
       // Mark the table and fields as fetched, so that we don't have to do that a
       // second time when the user opens another row.
diff --git a/web-frontend/modules/database/components/row/RowCreateModal.vue b/web-frontend/modules/database/components/row/RowCreateModal.vue
index 4a480ec6a..bccf36b04 100644
--- a/web-frontend/modules/database/components/row/RowCreateModal.vue
+++ b/web-frontend/modules/database/components/row/RowCreateModal.vue
@@ -1,7 +1,7 @@
 <template>
   <Modal ref="modal">
     <form @submit.prevent="create">
-      <h2 v-if="primary !== undefined" class="box__title">
+      <h2 class="box__title">
         {{ heading }}
       </h2>
       <Error :error="error"></Error>
@@ -62,6 +62,7 @@ import modal from '@baserow/modules/core/mixins/modal'
 import error from '@baserow/modules/core/mixins/error'
 import RowEditModalFieldsList from './RowEditModalFieldsList.vue'
 import RowEditModalHiddenFieldsSection from './RowEditModalHiddenFieldsSection.vue'
+import { getPrimaryOrFirstField } from '@baserow/modules/database/utils/field'
 
 export default {
   name: 'RowCreateModal',
@@ -75,11 +76,6 @@ export default {
       type: Object,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: false,
-      default: undefined,
-    },
     primaryIsSortable: {
       type: Boolean,
       required: false,
@@ -111,11 +107,17 @@ export default {
       return this.visibleFields.concat(this.hiddenFields)
     },
     heading() {
-      const name = `field_${this.primary.id}`
+      const field = getPrimaryOrFirstField(this.visibleFields)
+
+      if (!field) {
+        return null
+      }
+
+      const name = `field_${field.id}`
       if (Object.prototype.hasOwnProperty.call(this.row, name)) {
         return this.$registry
-          .get('field', this.primary.type)
-          .toHumanReadableString(this.primary, this.row[name])
+          .get('field', field.type)
+          .toHumanReadableString(field, this.row[name])
       } else {
         return null
       }
diff --git a/web-frontend/modules/database/components/row/RowEditModal.vue b/web-frontend/modules/database/components/row/RowEditModal.vue
index 1fa6899f0..d45b6a656 100644
--- a/web-frontend/modules/database/components/row/RowEditModal.vue
+++ b/web-frontend/modules/database/components/row/RowEditModal.vue
@@ -8,8 +8,8 @@
     @hidden="$emit('hidden', { row })"
   >
     <template #content>
-      <h2 v-if="primary !== undefined" class="box__title">
-        {{ getHeading(primary, row) }}
+      <h2 class="box__title">
+        {{ heading }}
       </h2>
       <RowEditModalFieldsList
         :primary-is-sortable="primaryIsSortable"
@@ -80,6 +80,7 @@ import modal from '@baserow/modules/core/mixins/modal'
 import CreateFieldContext from '@baserow/modules/database/components/field/CreateFieldContext'
 import RowEditModalFieldsList from './RowEditModalFieldsList.vue'
 import RowEditModalHiddenFieldsSection from './RowEditModalHiddenFieldsSection.vue'
+import { getPrimaryOrFirstField } from '@baserow/modules/database/utils/field'
 
 export default {
   name: 'RowEditModal',
@@ -92,17 +93,13 @@ export default {
   props: {
     database: {
       type: Object,
-      required: true,
+      required: false,
+      default: null,
     },
     table: {
       type: Object,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: false,
-      default: undefined,
-    },
     primaryIsSortable: {
       type: Boolean,
       required: false,
@@ -151,6 +148,22 @@ export default {
     row() {
       return this.modalRow.row
     },
+    heading() {
+      const field = getPrimaryOrFirstField(this.visibleFields)
+
+      if (!field) {
+        return null
+      }
+
+      const name = `field_${field.id}`
+      if (Object.prototype.hasOwnProperty.call(this.row, name)) {
+        return this.$registry
+          .get('field', field.type)
+          .toHumanReadableString(field, this.row[name])
+      } else {
+        return null
+      }
+    },
   },
   watch: {
     /**
@@ -208,16 +221,6 @@ export default {
       context.table = this.table
       this.$emit('update', context)
     },
-    getHeading(primary, row) {
-      const name = `field_${primary.id}`
-      if (Object.prototype.hasOwnProperty.call(row, name)) {
-        return this.$registry
-          .get('field', primary.type)
-          .toHumanReadableString(primary, row[name])
-      } else {
-        return null
-      }
-    },
   },
 }
 </script>
diff --git a/web-frontend/modules/database/components/table/Table.vue b/web-frontend/modules/database/components/table/Table.vue
index 582c1e476..29ac0da19 100644
--- a/web-frontend/modules/database/components/table/Table.vue
+++ b/web-frontend/modules/database/components/table/Table.vue
@@ -80,7 +80,6 @@
           <ViewFilter
             :view="view"
             :fields="fields"
-            :primary="primary"
             :read-only="readOnly"
             :disable-filter="disableFilter"
             @changed="refresh()"
@@ -93,7 +92,6 @@
           <ViewSort
             :view="view"
             :fields="fields"
-            :primary="primary"
             :read-only="readOnly"
             :disable-sort="disableSort"
             @changed="refresh()"
@@ -114,7 +112,6 @@
             :view="view"
             :table="table"
             :fields="fields"
-            :primary="primary"
             :read-only="readOnly"
             :disable-sort="disableSort"
             @changed="refresh()"
@@ -128,7 +125,6 @@
         :table="table"
         :view="view"
         :fields="fields"
-        :primary="primary"
         :read-only="readOnly"
         :store-prefix="storePrefix"
         @refresh="refresh"
@@ -143,7 +139,6 @@
         :table="table"
         :view="view"
         :fields="fields"
-        :primary="primary"
         :read-only="readOnly"
         :store-prefix="storePrefix"
         @refresh="refresh"
@@ -202,10 +197,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     views: {
       required: false,
       validator: (prop) => typeof prop === 'object' || prop === undefined,
@@ -349,7 +340,6 @@ export default {
           { store: this.$store },
           this.view,
           fieldsToRefresh,
-          this.primary,
           this.storePrefix,
           includeFieldOptions
         )
diff --git a/web-frontend/modules/database/components/table/TableTemplate.vue b/web-frontend/modules/database/components/table/TableTemplate.vue
index ad08d118b..379156d15 100644
--- a/web-frontend/modules/database/components/table/TableTemplate.vue
+++ b/web-frontend/modules/database/components/table/TableTemplate.vue
@@ -3,7 +3,6 @@
     :database="database"
     :table="table"
     :fields="fields"
-    :primary="primary"
     :views="views"
     :view="view"
     :table-loading="tableLoading"
@@ -38,7 +37,6 @@ export default {
       database: {},
       table: {},
       fields: [],
-      primary: {},
       views: [],
       view: {},
       tableLoading: true,
@@ -86,13 +84,7 @@ export default {
           fieldsData.forEach((part, index, d) => {
             populateField(fieldsData[index], this.$registry)
           })
-          const primaryIndex = fieldsData.findIndex(
-            (item) => item.primary === true
-          )
-          const primary =
-            primaryIndex !== -1 ? fieldsData.splice(primaryIndex, 1)[0] : null
           this.fields = fieldsData
-          this.primary = primary
 
           // Fetch and prepare the views of the given table.
           const { data: viewsData } = await ViewService(this.$client).fetchAll(
@@ -153,7 +145,7 @@ export default {
             { store: this.$store },
             view,
             this.fields,
-            this.primary,
+            null,
             'template/'
           )
           this.tableLoading = false
diff --git a/web-frontend/modules/database/components/view/ViewDecoratorContext.vue b/web-frontend/modules/database/components/view/ViewDecoratorContext.vue
index 513a101a9..13dd2e635 100644
--- a/web-frontend/modules/database/components/view/ViewDecoratorContext.vue
+++ b/web-frontend/modules/database/components/view/ViewDecoratorContext.vue
@@ -60,7 +60,6 @@
             v-if="dec.valueProviderType"
             :view="view"
             :table="table"
-            :primary="primary"
             :fields="fields"
             :read-only="readOnly"
             :options="dec.decoration.value_provider_conf"
@@ -129,10 +128,6 @@ export default {
       type: Object,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -173,7 +168,7 @@ export default {
             value_provider_type: valueProviderType.getType(),
             value_provider_conf: valueProviderType.getDefaultConfiguration({
               view: this.view,
-              fields: this.allTableFields,
+              fields: this.fields,
             }),
           },
           decoration,
diff --git a/web-frontend/modules/database/components/view/ViewDecoratorMenu.vue b/web-frontend/modules/database/components/view/ViewDecoratorMenu.vue
index d4c206ceb..2f9eec0ae 100644
--- a/web-frontend/modules/database/components/view/ViewDecoratorMenu.vue
+++ b/web-frontend/modules/database/components/view/ViewDecoratorMenu.vue
@@ -21,7 +21,6 @@
       :view="view"
       :table="table"
       :fields="fields"
-      :primary="primary"
       :read-only="readOnly"
       @changed="$emit('changed')"
     ></ViewDecoratorContext>
@@ -39,10 +38,6 @@ export default {
       type: Object,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
diff --git a/web-frontend/modules/database/components/view/ViewFieldConditionsForm.vue b/web-frontend/modules/database/components/view/ViewFieldConditionsForm.vue
index e9c130e1e..384472e86 100644
--- a/web-frontend/modules/database/components/view/ViewFieldConditionsForm.vue
+++ b/web-frontend/modules/database/components/view/ViewFieldConditionsForm.vue
@@ -51,12 +51,6 @@
           class="dropdown--floating dropdown--tiny"
           @input="updateFilter(filter, { field: $event })"
         >
-          <DropdownItem
-            :key="'primary-' + primary.id"
-            :name="primary.name"
-            :value="primary.id"
-            :disabled="hasNoCompatibleFilterTypes(primary, filterTypes)"
-          ></DropdownItem>
           <DropdownItem
             v-for="field in fields"
             :key="'field-' + field.id"
@@ -74,12 +68,7 @@
           @input="updateFilter(filter, { type: $event })"
         >
           <DropdownItem
-            v-for="fType in allowedFilters(
-              filterTypes,
-              primary,
-              fields,
-              filter.field
-            )"
+            v-for="fType in allowedFilters(filterTypes, fields, filter.field)"
             :key="fType.type"
             :name="fType.getName()"
             :value="fType.type"
@@ -93,7 +82,6 @@
           :filter="filter"
           :view="view"
           :fields="fields"
-          :primary="primary"
           :disabled="disableFilter"
           :read-only="readOnly"
           @input="updateFilter(filter, { value: $event })"
@@ -119,10 +107,6 @@ export default {
       type: String,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -184,9 +168,8 @@ export default {
     /**
      * Returns a list of filter types that are allowed for the given fieldId.
      */
-    allowedFilters(filterTypes, primary, fields, fieldId) {
-      const field =
-        primary.id === fieldId ? primary : fields.find((f) => f.id === fieldId)
+    allowedFilters(filterTypes, fields, fieldId) {
+      const field = fields.find((f) => f.id === fieldId)
       return Object.values(filterTypes).filter((filterType) => {
         return field !== undefined && filterType.fieldIsCompatible(field)
       })
@@ -214,7 +197,6 @@ export default {
       if (Object.prototype.hasOwnProperty.call(values, 'field')) {
         const allowedFilterTypes = this.allowedFilters(
           this.filterTypes,
-          this.primary,
           this.fields,
           field
         ).map((filter) => filter.type)
@@ -244,10 +226,7 @@ export default {
      * responsible for updating the filter value.
      */
     getInputComponent(type, fieldId) {
-      const field =
-        this.primary.id === fieldId
-          ? this.primary
-          : this.fields.find(({ id }) => id === fieldId)
+      const field = this.fields.find(({ id }) => id === fieldId)
       return this.$registry.get('viewFilter', type).getInputComponent(field)
     },
   },
diff --git a/web-frontend/modules/database/components/view/ViewFilter.vue b/web-frontend/modules/database/components/view/ViewFilter.vue
index 41d27d00a..7ae08b227 100644
--- a/web-frontend/modules/database/components/view/ViewFilter.vue
+++ b/web-frontend/modules/database/components/view/ViewFilter.vue
@@ -21,7 +21,6 @@
       :class="{ 'context--loading-overlay': view._.loading }"
     >
       <ViewFilterForm
-        :primary="primary"
         :fields="fields"
         :view="view"
         :read-only="readOnly"
@@ -39,10 +38,6 @@ export default {
   name: 'ViewFilter',
   components: { ViewFilterForm },
   props: {
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
diff --git a/web-frontend/modules/database/components/view/ViewFilterForm.vue b/web-frontend/modules/database/components/view/ViewFilterForm.vue
index 69f5af14e..55ff037f3 100644
--- a/web-frontend/modules/database/components/view/ViewFilterForm.vue
+++ b/web-frontend/modules/database/components/view/ViewFilterForm.vue
@@ -14,7 +14,6 @@
       :filters="view.filters"
       :disable-filter="disableFilter"
       :filter-type="view.filter_type"
-      :primary="primary"
       :fields="fields"
       :view="view"
       :read-only="readOnly"
@@ -42,6 +41,7 @@
 <script>
 import { notifyIf } from '@baserow/modules/core/utils/error'
 import ViewFieldConditionsForm from '@baserow/modules/database/components/view/ViewFieldConditionsForm'
+import { getPrimaryOrFirstField } from '@baserow/modules/database/utils/field'
 
 export default {
   name: 'ViewFilterForm',
@@ -49,10 +49,6 @@ export default {
     ViewFieldConditionsForm,
   },
   props: {
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -78,11 +74,12 @@ export default {
   methods: {
     async addFilter(values) {
       try {
+        const field = getPrimaryOrFirstField(this.fields)
         await this.$store.dispatch('view/createFilter', {
+          field,
           view: this.view,
-          field: this.primary,
           values: {
-            field: this.primary.id,
+            field: field.id,
           },
           emitEvent: false,
           readOnly: this.readOnly,
diff --git a/web-frontend/modules/database/components/view/ViewFilterTypeFileTypeDropdown.vue b/web-frontend/modules/database/components/view/ViewFilterTypeFileTypeDropdown.vue
index 1520a1918..fb68c8b5b 100644
--- a/web-frontend/modules/database/components/view/ViewFilterTypeFileTypeDropdown.vue
+++ b/web-frontend/modules/database/components/view/ViewFilterTypeFileTypeDropdown.vue
@@ -28,10 +28,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     readOnly: {
       type: Boolean,
       required: true,
diff --git a/web-frontend/modules/database/components/view/ViewSearch.vue b/web-frontend/modules/database/components/view/ViewSearch.vue
index 55eded947..df5c81bc7 100644
--- a/web-frontend/modules/database/components/view/ViewSearch.vue
+++ b/web-frontend/modules/database/components/view/ViewSearch.vue
@@ -15,7 +15,6 @@
       ref="context"
       :view="view"
       :fields="fields"
-      :primary="primary"
       :store-prefix="storePrefix"
       :always-hide-rows-not-matching-search="alwaysHideRowsNotMatchingSearch"
       @refresh="$emit('refresh', $event)"
@@ -39,10 +38,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     storePrefix: {
       type: String,
       required: true,
diff --git a/web-frontend/modules/database/components/view/ViewSearchContext.vue b/web-frontend/modules/database/components/view/ViewSearchContext.vue
index 94ef28715..517007123 100644
--- a/web-frontend/modules/database/components/view/ViewSearchContext.vue
+++ b/web-frontend/modules/database/components/view/ViewSearchContext.vue
@@ -54,10 +54,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     storePrefix: {
       type: String,
       required: true,
@@ -120,7 +116,6 @@ export default {
           // the server using the newly set search terms.
           refreshMatchesOnClient: false,
           fields: this.fields,
-          primary: this.primary,
         }
       )
       this.$emit('refresh', {
@@ -137,7 +132,6 @@ export default {
           hideRowsNotMatchingSearch: this.hideRowsNotMatchingSearch,
           refreshMatchesOnClient: true,
           fields: this.fields,
-          primary: this.primary,
         }
       )
       this.finishedLoading()
diff --git a/web-frontend/modules/database/components/view/ViewSort.vue b/web-frontend/modules/database/components/view/ViewSort.vue
index 3ab54ee27..977b34e7d 100644
--- a/web-frontend/modules/database/components/view/ViewSort.vue
+++ b/web-frontend/modules/database/components/view/ViewSort.vue
@@ -19,7 +19,6 @@
       ref="context"
       :view="view"
       :fields="fields"
-      :primary="primary"
       :read-only="readOnly"
       :disable-sort="disableSort"
       @changed="$emit('changed')"
@@ -34,10 +33,6 @@ export default {
   name: 'ViewSort',
   components: { ViewSortContext },
   props: {
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
diff --git a/web-frontend/modules/database/components/view/ViewSortContext.vue b/web-frontend/modules/database/components/view/ViewSortContext.vue
index 4f730c676..95e669a76 100644
--- a/web-frontend/modules/database/components/view/ViewSortContext.vue
+++ b/web-frontend/modules/database/components/view/ViewSortContext.vue
@@ -40,14 +40,6 @@
             class="dropdown--floating dropdown--tiny"
             @input="updateSort(sort, { field: $event })"
           >
-            <DropdownItem
-              :key="'sort-field-' + sort.id + '-' + primary.id"
-              :name="primary.name"
-              :value="primary.id"
-              :disabled="
-                sort.field !== primary.id && !isFieldAvailable(primary)
-              "
-            ></DropdownItem>
             <DropdownItem
               v-for="field in fields"
               :key="'sort-field-' + sort.id + '-' + field.id"
@@ -136,15 +128,6 @@
         </a>
         <Context ref="addContext" class="sortings__add-context">
           <ul ref="items" class="context__menu">
-            <li v-show="isFieldAvailable(primary)">
-              <a @click="addSort(primary)">
-                <i
-                  class="context__menu-icon fas fa-fw"
-                  :class="'fa-' + primary._.type.iconClass"
-                ></i>
-                {{ primary.name }}
-              </a>
-            </li>
             <li
               v-for="field in fields"
               v-show="isFieldAvailable(field)"
@@ -173,10 +156,6 @@ export default {
   name: 'ViewSortContext',
   mixins: [context],
   props: {
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -204,11 +183,7 @@ export default {
      * Calculates the total amount of available fields.
      */
     availableFieldsLength() {
-      const fields = this.fields.filter((field) =>
-        this.getCanSortInView(field)
-      ).length
-      const primary = this.getCanSortInView(this.primary) ? 1 : 0
-      return fields + primary
+      return this.fields.filter(this.getCanSortInView).length
     },
   },
   methods: {
@@ -216,9 +191,6 @@ export default {
       return this.$registry.get('field', field.type).getCanSortInView(field)
     },
     getField(fieldId) {
-      if (this.primary.id === fieldId) {
-        return this.primary
-      }
       for (const i in this.fields) {
         if (this.fields[i].id === fieldId) {
           return this.fields[i]
diff --git a/web-frontend/modules/database/components/view/form/FormView.vue b/web-frontend/modules/database/components/view/form/FormView.vue
index 05ba208a8..ce1d4c088 100644
--- a/web-frontend/modules/database/components/view/form/FormView.vue
+++ b/web-frontend/modules/database/components/view/form/FormView.vue
@@ -33,10 +33,6 @@ export default {
   components: { FormViewSidebar, FormViewPreview },
   mixins: [formViewHelpers],
   props: {
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -61,7 +57,6 @@ export default {
   computed: {
     sortedFields() {
       const fields = this.fields.slice()
-      fields.unshift(this.primary)
       return fields.sort((a, b) => {
         const orderA = this.getFieldOption(a.id, 'order', maxPossibleOrderValue)
         const orderB = this.getFieldOption(b.id, 'order', maxPossibleOrderValue)
diff --git a/web-frontend/modules/database/components/view/form/FormViewHeader.vue b/web-frontend/modules/database/components/view/form/FormViewHeader.vue
index 2f5181603..b24f069cf 100644
--- a/web-frontend/modules/database/components/view/form/FormViewHeader.vue
+++ b/web-frontend/modules/database/components/view/form/FormViewHeader.vue
@@ -31,10 +31,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     readOnly: {
       type: Boolean,
       required: true,
diff --git a/web-frontend/modules/database/components/view/gallery/GalleryView.vue b/web-frontend/modules/database/components/view/gallery/GalleryView.vue
index 2d5420ab7..fc0f7deb5 100644
--- a/web-frontend/modules/database/components/view/gallery/GalleryView.vue
+++ b/web-frontend/modules/database/components/view/gallery/GalleryView.vue
@@ -56,7 +56,6 @@
       v-if="!readOnly"
       ref="rowCreateModal"
       :table="table"
-      :primary="primary"
       :primary-is-sortable="true"
       :visible-fields="cardFields"
       :hidden-fields="hiddenFields"
@@ -74,7 +73,6 @@
       ref="rowEditModal"
       :database="database"
       :table="table"
-      :primary="primary"
       :primary-is-sortable="true"
       :visible-fields="cardFields"
       :hidden-fields="hiddenFields"
@@ -123,10 +121,6 @@ export default {
   components: { RowCard, RowCreateModal, RowEditModal },
   mixins: [viewHelpers, bufferedRowsDragAndDrop, viewDecoration],
   props: {
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -183,25 +177,19 @@ export default {
      */
     cardFields() {
       const fieldOptions = this.fieldOptions
-      return [this.primary]
-        .concat(this.fields)
+      return this.fields
         .filter(filterVisibleFieldsFunction(fieldOptions))
         .sort(sortFieldsByOrderAndIdFunction(fieldOptions))
     },
     hiddenFields() {
       const fieldOptions = this.fieldOptions
-      return [this.primary]
-        .concat(this.fields)
+      return this.fields
         .filter(filterHiddenFieldsFunction(fieldOptions))
         .sort(sortFieldsByOrderAndIdFunction(fieldOptions))
     },
     coverImageField() {
       const fieldId = this.view.card_cover_image_field
-      return (
-        [this.primary]
-          .concat(this.fields)
-          .find((field) => field.id === fieldId) || null
-      )
+      return this.fields.find((field) => field.id === fieldId) || null
     },
   },
   watch: {
@@ -373,7 +361,6 @@ export default {
             view: this.view,
             table: this.table,
             fields: this.fields,
-            primary: this.primary,
             values: row,
           }
         )
@@ -390,7 +377,6 @@ export default {
             table: this.table,
             view: this.view,
             fields: this.fields,
-            primary: this.primary,
             row,
             field,
             value,
diff --git a/web-frontend/modules/database/components/view/gallery/GalleryViewHeader.vue b/web-frontend/modules/database/components/view/gallery/GalleryViewHeader.vue
index f4e68a335..3b22814e8 100644
--- a/web-frontend/modules/database/components/view/gallery/GalleryViewHeader.vue
+++ b/web-frontend/modules/database/components/view/gallery/GalleryViewHeader.vue
@@ -20,7 +20,7 @@
       </a>
       <ViewFieldsContext
         ref="customizeContext"
-        :fields="allFields"
+        :fields="fields"
         :read-only="readOnly"
         :field-options="fieldOptions"
         :cover-image-field="view.card_cover_image_field"
@@ -35,7 +35,6 @@
       <ViewSearch
         :view="view"
         :fields="fields"
-        :primary="primary"
         :store-prefix="storePrefix"
         :always-hide-rows-not-matching-search="true"
         @refresh="$emit('refresh', $event)"
@@ -71,10 +70,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     readOnly: {
       type: Boolean,
       required: true,
@@ -85,9 +80,6 @@ export default {
     },
   },
   computed: {
-    allFields() {
-      return [this.primary].concat(this.fields)
-    },
     ...mapState({
       tableLoading: (state) => state.table.loading,
     }),
diff --git a/web-frontend/modules/database/components/view/grid/GridView.vue b/web-frontend/modules/database/components/view/grid/GridView.vue
index d72519e1a..47f1243bf 100644
--- a/web-frontend/modules/database/components/view/grid/GridView.vue
+++ b/web-frontend/modules/database/components/view/grid/GridView.vue
@@ -58,7 +58,7 @@
       class="grid-view__divider-width"
       :style="{ left: leftWidth + 'px' }"
       :grid="view"
-      :field="primary"
+      :field="leftFields[0]"
       :width="leftFieldsWidth"
       :read-only="readOnly"
       :store-prefix="storePrefix"
@@ -112,8 +112,7 @@
       ref="rowDragging"
       :table="table"
       :view="view"
-      :primary="primary"
-      :fields="visibleFields"
+      :fields="allVisibleFields"
       :store-prefix="storePrefix"
       vertical="getVerticalScrollbarElement"
       @scroll="scroll($event.pixelY, $event.pixelX)"
@@ -184,8 +183,7 @@
       ref="rowEditModal"
       :database="database"
       :table="table"
-      :primary="primary"
-      :visible-fields="[primary].concat(visibleFields)"
+      :visible-fields="allVisibleFields"
       :hidden-fields="hiddenFields"
       :rows="allRows"
       :read-only="readOnly"
@@ -232,10 +230,6 @@ export default {
   },
   mixins: [viewHelpers, gridViewHelpers, viewDecoration],
   props: {
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -266,12 +260,15 @@ export default {
     }
   },
   computed: {
+    allVisibleFields() {
+      return this.leftFields.concat(this.visibleFields)
+    },
     /**
      * Returns only the visible fields in the correct order.
      */
     visibleFields() {
       const fieldOptions = this.fieldOptions
-      return this.fields
+      return this.rightFields
         .filter(filterVisibleFieldsFunction(fieldOptions))
         .sort(sortFieldsByOrderAndIdFunction(fieldOptions))
     },
@@ -280,12 +277,15 @@ export default {
      */
     hiddenFields() {
       const fieldOptions = this.fieldOptions
-      return this.fields
+      return this.rightFields
         .filter(filterHiddenFieldsFunction(fieldOptions))
         .sort(sortFieldsByOrderAndIdFunction(fieldOptions))
     },
     leftFields() {
-      return [this.primary]
+      return this.fields.filter((field) => field.primary)
+    },
+    rightFields() {
+      return this.fields.filter((field) => !field.primary)
     },
     leftFieldsWidth() {
       return this.leftFields.reduce(
@@ -407,7 +407,6 @@ export default {
             table: this.table,
             view: this.view,
             fields: this.fields,
-            primary: this.primary,
             row,
             field,
             value,
@@ -429,7 +428,6 @@ export default {
         view: this.view,
         row,
         fields: this.fields,
-        primary: this.primary,
         overrides,
       })
     },
@@ -476,7 +474,6 @@ export default {
         {
           scrollTop: this.$refs.left.$refs.body.scrollTop,
           fields: this.fields,
-          primary: this.primary,
         }
       )
     },
@@ -501,7 +498,6 @@ export default {
             table: this.table,
             // We need a list of all fields including the primary one here.
             fields: this.fields,
-            primary: this.primary,
             values,
             before,
           }
@@ -539,7 +535,6 @@ export default {
             table: this.table,
             view: this.view,
             fields: this.fields,
-            primary: this.primary,
             row,
             getScrollTop,
           }
@@ -607,7 +602,6 @@ export default {
       this.$store.dispatch(this.storePrefix + 'view/grid/refreshRow', {
         grid: this.view,
         fields: this.fields,
-        primary: this.primary,
         row,
         getScrollTop: () => this.$refs.left.$refs.body.scrollTop,
       })
@@ -698,7 +692,6 @@ export default {
           {
             grid: this.view,
             fields: this.fields,
-            primary: this.primary,
             row,
             field,
             getScrollTop,
@@ -713,7 +706,7 @@ export default {
      */
     selectNextCell({ row, field, direction = 'next' }) {
       const fields = this.visibleFields
-      const primary = this.primary
+      const primary = this.leftFields[0]
       let nextFieldId = -1
       let nextRowId = -1
 
@@ -868,7 +861,7 @@ export default {
         this.$store.dispatch('notification/setCopying', true)
         const output = await this.$store.dispatch(
           this.storePrefix + 'view/grid/exportMultiSelect',
-          this.leftFields.concat(this.visibleFields)
+          this.allVisibleFields
         )
         // If the output is undefined, it means that there is no multiple selection.
         if (output !== undefined) {
@@ -933,8 +926,7 @@ export default {
           {
             table: this.table,
             view: this.view,
-            primary: this.primary,
-            fields: this.leftFields.concat(this.visibleFields),
+            fields: this.allVisibleFields,
             getScrollTop: () => this.$refs.left.$refs.body.scrollTop,
             data,
             rowIndex,
@@ -961,8 +953,7 @@ export default {
           {
             table: this.table,
             view: this.view,
-            primary: this.primary,
-            fields: this.leftFields.concat(this.visibleFields),
+            fields: this.allVisibleFields,
             getScrollTop: () => this.$refs.left.$refs.body.scrollTop,
           }
         )
@@ -986,8 +977,7 @@ export default {
           {
             table: this.table,
             view: this.view,
-            primary: this.primary,
-            fields: this.leftFields.concat(this.visibleFields),
+            fields: this.allVisibleFields,
             getScrollTop: () => this.$refs.left.$refs.body.scrollTop,
           }
         )
diff --git a/web-frontend/modules/database/components/view/grid/GridViewHeader.vue b/web-frontend/modules/database/components/view/grid/GridViewHeader.vue
index 6c719b5c1..b9e13b7ec 100644
--- a/web-frontend/modules/database/components/view/grid/GridViewHeader.vue
+++ b/web-frontend/modules/database/components/view/grid/GridViewHeader.vue
@@ -3,7 +3,7 @@
     <li class="header__filter-item">
       <GridViewHide
         :view="view"
-        :fields="fields"
+        :fields="fieldsAllowedToBeHidden"
         :read-only="readOnly"
         :store-prefix="storePrefix"
       ></GridViewHide>
@@ -12,7 +12,6 @@
       <ViewSearch
         :view="view"
         :fields="fields"
-        :primary="primary"
         :store-prefix="storePrefix"
         @refresh="$emit('refresh', $event)"
       ></ViewSearch>
@@ -38,10 +37,6 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     readOnly: {
       type: Boolean,
       required: true,
@@ -55,6 +50,9 @@ export default {
     ...mapState({
       tableLoading: (state) => state.table.loading,
     }),
+    fieldsAllowedToBeHidden() {
+      return this.fields.filter((field) => !field.primary)
+    },
   },
 }
 </script>
diff --git a/web-frontend/modules/database/components/view/grid/GridViewRowDragging.vue b/web-frontend/modules/database/components/view/grid/GridViewRowDragging.vue
index 0b675d9d7..6db2f6bd7 100644
--- a/web-frontend/modules/database/components/view/grid/GridViewRowDragging.vue
+++ b/web-frontend/modules/database/components/view/grid/GridViewRowDragging.vue
@@ -29,10 +29,6 @@ export default {
       type: Object,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -66,9 +62,8 @@ export default {
   },
   computed: {
     width() {
-      const allFields = [this.primary].concat(this.fields)
       return (
-        allFields.reduce(
+        this.fields.reduce(
           (value, field) => this.getFieldWidth(field.id) + value,
           0
         ) + this.gridViewRowDetailsWidth
@@ -245,7 +240,6 @@ export default {
           table: this.table,
           grid: this.view,
           fields: this.fields,
-          primary: this.primary,
           getScrollTop,
           row: this.row,
           before: this.targetRow,
diff --git a/web-frontend/modules/database/components/webhook/WebhookForm.vue b/web-frontend/modules/database/components/webhook/WebhookForm.vue
index acbe1ffc8..71ae96b48 100644
--- a/web-frontend/modules/database/components/webhook/WebhookForm.vue
+++ b/web-frontend/modules/database/components/webhook/WebhookForm.vue
@@ -331,7 +331,7 @@ export default {
       return webhookEvent.getExamplePayload(this.table, rowExample)
     },
     ...mapGetters({
-      fields: 'field/getAllWithPrimary',
+      fields: 'field/getAll',
     }),
   },
   created() {
diff --git a/web-frontend/modules/database/mixins/bufferedRowsDragAndDrop.js b/web-frontend/modules/database/mixins/bufferedRowsDragAndDrop.js
index a73813523..a9d1a6da8 100644
--- a/web-frontend/modules/database/mixins/bufferedRowsDragAndDrop.js
+++ b/web-frontend/modules/database/mixins/bufferedRowsDragAndDrop.js
@@ -88,7 +88,6 @@ export default {
               `${this.getDragAndDropStoreName(this)}/cancelRowDrag`,
               {
                 view: this.view,
-                primary: this.primary,
                 fields: this.fields,
                 row: this.dragAndDropDraggingRow,
               }
diff --git a/web-frontend/modules/database/mixins/viewDecoration.js b/web-frontend/modules/database/mixins/viewDecoration.js
index 6219c512b..6943485a1 100644
--- a/web-frontend/modules/database/mixins/viewDecoration.js
+++ b/web-frontend/modules/database/mixins/viewDecoration.js
@@ -19,15 +19,8 @@ export default {
       type: Array,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
   },
   computed: {
-    allTableFields() {
-      return [this.primary, ...this.fields]
-    },
     activeDecorations() {
       return this.view.decorations
         .map((decoration) => {
@@ -51,7 +44,7 @@ export default {
               return {
                 value: deco.valueProviderType.getValue({
                   row,
-                  fields: this.allTableFields,
+                  fields: this.fields,
                   options: decoration.value_provider_conf,
                 }),
               }
diff --git a/web-frontend/modules/database/mixins/viewFilter.js b/web-frontend/modules/database/mixins/viewFilter.js
index 17c38a46f..fc3deaf4e 100644
--- a/web-frontend/modules/database/mixins/viewFilter.js
+++ b/web-frontend/modules/database/mixins/viewFilter.js
@@ -14,10 +14,6 @@ export default {
       type: Object,
       required: true,
     },
-    primary: {
-      type: Object,
-      required: true,
-    },
     fields: {
       type: Array,
       required: true,
@@ -33,9 +29,10 @@ export default {
   },
   computed: {
     field() {
-      return this.primary.id === this.filter.field
-        ? this.primary
-        : this.fields.find((f) => f.id === this.filter.field)
+      return this.fields.find((f) => f.id === this.filter.field)
+    },
+    primary() {
+      return this.fields.find((f) => f.primary)
     },
   },
 }
diff --git a/web-frontend/modules/database/pages/publicGridView.vue b/web-frontend/modules/database/pages/publicGridView.vue
index fd91d393b..d7b7ad64c 100644
--- a/web-frontend/modules/database/pages/publicGridView.vue
+++ b/web-frontend/modules/database/pages/publicGridView.vue
@@ -5,8 +5,7 @@
       <Table
         :database="database"
         :table="table"
-        :fields="fields || startingFields"
-        :primary="primary || startingPrimary"
+        :fields="fields"
         :view="view"
         :read-only="true"
         :table-loading="false"
@@ -63,7 +62,7 @@ export default {
       const table = database.tables[0]
       await store.dispatch('table/forceSelect', { database, table })
 
-      const { primary, fields } = await store.dispatch('field/forceSetFields', {
+      await store.dispatch('field/forceSetFields', {
         fields: data.fields,
       })
 
@@ -79,13 +78,11 @@ export default {
       // It might be possible that the view also has some stores that need to be
       // filled with initial data, so we're going to call the fetch function here.
       const type = app.$registry.get('view', view.type)
-      await type.fetch({ store }, view, fields, primary, 'page/')
+      await type.fetch({ store }, view, data.fields, 'page/')
       return {
         database,
         table,
         view,
-        startingFields: fields,
-        startingPrimary: primary,
       }
     } catch (e) {
       const statusCode = e.response?.status
@@ -109,7 +106,6 @@ export default {
   },
   computed: {
     ...mapGetters({
-      primary: 'field/getPrimary',
       fields: 'field/getAll',
     }),
   },
diff --git a/web-frontend/modules/database/pages/table.vue b/web-frontend/modules/database/pages/table.vue
index 52fad864c..f0d937cba 100644
--- a/web-frontend/modules/database/pages/table.vue
+++ b/web-frontend/modules/database/pages/table.vue
@@ -3,7 +3,6 @@
     :database="database"
     :table="table"
     :fields="fields"
-    :primary="primary"
     :views="views"
     :view="view"
     :table-loading="tableLoading"
@@ -75,7 +74,6 @@ export default {
     // After selecting the table the fields become available which need to be added to
     // the data.
     data.fields = store.getters['field/getAll']
-    data.primary = store.getters['field/getPrimary']
     data.view = undefined
 
     // Because we do not have a dashboard for the table yet we're going to redirect to
@@ -101,7 +99,7 @@ export default {
           return error({ statusCode: 400, message: type.getDeactivatedText() })
         }
 
-        await type.fetch({ store }, view, data.fields, data.primary, 'page/')
+        await type.fetch({ store }, view, data.fields, 'page/')
       } catch (e) {
         // In case of a network error we want to fail hard.
         if (e.response === undefined && !(e instanceof StoreItemLookupError)) {
diff --git a/web-frontend/modules/database/realtime.js b/web-frontend/modules/database/realtime.js
index 55de93be7..21496ba04 100644
--- a/web-frontend/modules/database/realtime.js
+++ b/web-frontend/modules/database/realtime.js
@@ -163,7 +163,6 @@ export const registerRealtimeEvents = (realtime) => {
           context,
           data.table_id,
           store.getters['field/getAll'],
-          store.getters['field/getPrimary'],
           data.rows[i],
           data.metadata,
           'page/'
@@ -183,7 +182,6 @@ export const registerRealtimeEvents = (realtime) => {
           context,
           data.table_id,
           store.getters['field/getAll'],
-          store.getters['field/getPrimary'],
           rowBeforeUpdate,
           row,
           data.metadata,
@@ -205,7 +203,6 @@ export const registerRealtimeEvents = (realtime) => {
           context,
           data.table_id,
           store.getters['field/getAll'],
-          store.getters['field/getPrimary'],
           row,
           'page/'
         )
diff --git a/web-frontend/modules/database/store/field.js b/web-frontend/modules/database/store/field.js
index 87ac70966..6ee93884a 100644
--- a/web-frontend/modules/database/store/field.js
+++ b/web-frontend/modules/database/store/field.js
@@ -15,7 +15,6 @@ export const state = () => ({
   types: {},
   loading: false,
   loaded: false,
-  primary: null,
   items: [],
 })
 
@@ -35,9 +34,6 @@ export const mutations = {
   SET_LOADED(state, value) {
     state.loaded = value
   },
-  SET_PRIMARY(state, item) {
-    state.primary = Object.assign(state.primary || {}, item)
-  },
   ADD_ITEM(state, item) {
     state.items.push(item)
   },
@@ -95,15 +91,11 @@ export const actions = {
       populateField(fields[index], this.$registry)
     })
 
-    const primaryIndex = fields.findIndex((item) => item.primary === true)
-    const primary =
-      primaryIndex !== -1 ? fields.splice(primaryIndex, 1)[0] : null
-    commit('SET_PRIMARY', primary)
     commit('SET_ITEMS', fields)
     commit('SET_LOADING', false)
     commit('SET_LOADED', true)
 
-    return { primary, fields }
+    return { fields }
   },
   /**
    * Creates a new field with the provided type for the given table.
@@ -184,11 +176,7 @@ export const actions = {
     const { commit, dispatch } = context
     const fieldType = this.$registry.get('field', values.type)
     const data = populateField(values, this.$registry)
-    if (data.primary) {
-      commit('SET_PRIMARY', data)
-    } else {
-      commit('ADD_ITEM', data)
-    }
+    commit('ADD_ITEM', data)
 
     // Call the field created event on all the registered views because they might
     // need to change things in loaded data. For example the grid field will add the
@@ -242,11 +230,8 @@ export const actions = {
     const fieldType = this.$registry.get('field', data.type)
     data = populateField(data, this.$registry)
 
-    if (field.primary) {
-      commit('SET_PRIMARY', data)
-    } else {
-      commit('UPDATE_ITEM', { id: field.id, values: data })
-    }
+    commit('UPDATE_ITEM', { id: field.id, values: data })
+    commit('UPDATE_ITEM', { id: field.id, values: data })
 
     // The view might need to do some cleanup regarding the filters and sortings if the
     // type has changed.
@@ -339,22 +324,11 @@ export const getters = {
     return state.loaded
   },
   get: (state) => (id) => {
-    const primary = state.primary.id === id ? state.primary : undefined
-    return state.items.find((item) => item.id === id) || primary
-  },
-  getPrimary: (state) => {
-    return state.primary
+    return state.items.find((item) => item.id === id)
   },
   getAll(state) {
     return state.items
   },
-  getAllWithPrimary(state) {
-    if (state.primary !== null) {
-      return [state.primary, ...state.items]
-    } else {
-      return state.items
-    }
-  },
 }
 
 export default {
diff --git a/web-frontend/modules/database/store/view/bufferedRows.js b/web-frontend/modules/database/store/view/bufferedRows.js
index 605410631..fa612fded 100644
--- a/web-frontend/modules/database/store/view/bufferedRows.js
+++ b/web-frontend/modules/database/store/view/bufferedRows.js
@@ -254,7 +254,7 @@ export default ({ service, customPopulateRow }) => {
      */
     async fetchInitialRows(
       context,
-      { viewId, fields, primary, initialRowArguments = {} }
+      { viewId, fields, initialRowArguments = {} }
     ) {
       const { commit, getters } = context
       commit('SET_VIEW_ID', viewId)
@@ -366,7 +366,7 @@ export default ({ service, customPopulateRow }) => {
      */
     async refresh(
       { dispatch, commit, getters },
-      { fields, primary, includeFieldOptions = false }
+      { fields, includeFieldOptions = false }
     ) {
       // If another refresh or fetch request is currently running, we need to cancel
       // it because the response is most likely going to be outdated and we don't
@@ -458,7 +458,7 @@ export default ({ service, customPopulateRow }) => {
     /**
      * Check if the provided row matches the provided view filters.
      */
-    rowMatchesFilters(context, { view, fields, primary, row, overrides = {} }) {
+    rowMatchesFilters(context, { view, fields, row, overrides = {} }) {
       const values = JSON.parse(JSON.stringify(row))
       Object.assign(values, overrides)
 
@@ -469,7 +469,7 @@ export default ({ service, customPopulateRow }) => {
             this.$registry,
             view.filter_type,
             view.filters,
-            primary === null ? fields : [primary, ...fields],
+            fields,
             values
           )
     },
@@ -478,12 +478,11 @@ export default ({ service, customPopulateRow }) => {
      * store. Because some rows haven't been fetched from the backend, we need to
      * figure out which `null` object could have been the row in the store.
      */
-    findIndexOfNotExistingRow({ getters }, { view, fields, primary, row }) {
+    findIndexOfNotExistingRow({ getters }, { view, fields, row }) {
       const sortFunction = getRowSortFunction(
         this.$registry,
         view.sortings,
-        fields,
-        primary
+        fields
       )
       const allRows = getters.getRows
       let index = allRows.findIndex((existingRow) => {
@@ -516,15 +515,11 @@ export default ({ service, customPopulateRow }) => {
      * hasn't been fetched yet, it will then point to the `null` object representing
      * the row.
      */
-    findIndexOfExistingRow(
-      { dispatch, getters },
-      { view, fields, primary, row }
-    ) {
+    findIndexOfExistingRow({ dispatch, getters }, { view, fields, row }) {
       const sortFunction = getRowSortFunction(
         this.$registry,
         view.sortings,
-        fields,
-        primary
+        fields
       )
       const allRows = getters.getRows
       let index = allRows.findIndex((existingRow) => {
@@ -559,12 +554,11 @@ export default ({ service, customPopulateRow }) => {
      */
     async createNewRow(
       { dispatch, commit, getters },
-      { view, table, fields, primary, values }
+      { view, table, fields, values }
     ) {
       // First prepare an object that we can send to the backend.
-      const allFields = [primary].concat(fields)
       const preparedValues = {}
-      allFields.forEach((field) => {
+      fields.forEach((field) => {
         const name = `field_${field.id}`
         const fieldType = this.$registry.get('field', field._.type.type)
 
@@ -590,7 +584,6 @@ export default ({ service, customPopulateRow }) => {
       return await dispatch('afterNewRowCreated', {
         view,
         fields,
-        primary,
         values: data,
       })
     },
@@ -609,7 +602,7 @@ export default ({ service, customPopulateRow }) => {
      */
     async afterNewRowCreated(
       { dispatch, getters, commit },
-      { view, fields, primary, values }
+      { view, fields, values }
     ) {
       let row = clone(values)
       populateRow(row)
@@ -617,13 +610,11 @@ export default ({ service, customPopulateRow }) => {
       const rowMatchesFilters = await dispatch('rowMatchesFilters', {
         view,
         fields,
-        primary,
         row,
       })
       await dispatch('updateSearchMatchesForRow', {
         view,
         fields,
-        primary,
         row,
       })
       if (!rowMatchesFilters || !row._.matchSearch) {
@@ -633,7 +624,6 @@ export default ({ service, customPopulateRow }) => {
       const { index, isCertain } = await dispatch('findIndexOfNotExistingRow', {
         view,
         fields,
-        primary,
         row,
       })
 
@@ -651,10 +641,9 @@ export default ({ service, customPopulateRow }) => {
      */
     async updateRowValue(
       { commit, dispatch },
-      { table, view, row, field, fields, primary, value, oldValue }
+      { table, view, row, field, fields, value, oldValue }
     ) {
       const fieldType = this.$registry.get('field', field._.type.type)
-      const allFields = [primary].concat(fields)
       const newValues = {}
       const newValuesForUpdate = {}
       const oldValues = {}
@@ -666,7 +655,7 @@ export default ({ service, customPopulateRow }) => {
       )
       oldValues[fieldName] = oldValue
 
-      allFields.forEach((fieldToCall) => {
+      fields.forEach((fieldToCall) => {
         const fieldType = this.$registry.get('field', fieldToCall._.type.type)
         const fieldToCallName = `field_${fieldToCall.id}`
         const currentFieldValue = row[fieldToCallName]
@@ -685,7 +674,6 @@ export default ({ service, customPopulateRow }) => {
       await dispatch('afterExistingRowUpdated', {
         view,
         fields,
-        primary,
         row,
         values: newValues,
       })
@@ -698,10 +686,9 @@ export default ({ service, customPopulateRow }) => {
         )
         commit('UPDATE_ROW', { row, values: data })
       } catch (error) {
-        dispatch('updatedExistingRow', {
+        dispatch('afterExistingRowUpdated', {
           view,
           fields,
-          primary,
           row,
           values: oldValues,
         })
@@ -722,7 +709,7 @@ export default ({ service, customPopulateRow }) => {
      */
     async afterExistingRowUpdated(
       { dispatch, commit },
-      { view, fields, primary, row, values }
+      { view, fields, row, values }
     ) {
       const oldRow = clone(row)
       let newRow = Object.assign(clone(row), values)
@@ -732,25 +719,21 @@ export default ({ service, customPopulateRow }) => {
       const oldMatchesFilters = await dispatch('rowMatchesFilters', {
         view,
         fields,
-        primary,
         row: oldRow,
       })
       const newMatchesFilters = await dispatch('rowMatchesFilters', {
         view,
         fields,
-        primary,
         row: newRow,
       })
       await dispatch('updateSearchMatchesForRow', {
         view,
         fields,
-        primary,
         row: oldRow,
       })
       await dispatch('updateSearchMatchesForRow', {
         view,
         fields,
-        primary,
         row: newRow,
       })
 
@@ -763,7 +746,6 @@ export default ({ service, customPopulateRow }) => {
         await dispatch('afterExistingRowDeleted', {
           view,
           fields,
-          primary,
           row,
         })
       } else if (!oldRowMatches && newRowMatches) {
@@ -772,7 +754,6 @@ export default ({ service, customPopulateRow }) => {
         await dispatch('afterNewRowCreated', {
           view,
           fields,
-          primary,
           values: newRow,
         })
       } else if (oldRowMatches && newRowMatches) {
@@ -782,14 +763,12 @@ export default ({ service, customPopulateRow }) => {
           {
             view,
             fields,
-            primary,
             row: oldRow,
           }
         )
         const findNewRow = await dispatch('findIndexOfNotExistingRow', {
           view,
           fields,
-          primary,
           row: newRow,
         })
         let { index: newIndex } = findNewRow
@@ -831,23 +810,18 @@ export default ({ service, customPopulateRow }) => {
      * removed from is. Based on the provided values of the row we can figure out if
      * it was in the store and we can figure out what index it has.
      */
-    async afterExistingRowDeleted(
-      { dispatch, commit },
-      { view, fields, primary, row }
-    ) {
+    async afterExistingRowDeleted({ dispatch, commit }, { view, fields, row }) {
       row = clone(row)
       populateRow(row)
 
       const rowMatchesFilters = await dispatch('rowMatchesFilters', {
         view,
         fields,
-        primary,
         row,
       })
       await dispatch('updateSearchMatchesForRow', {
         view,
         fields,
-        primary,
         row,
       })
       if (!rowMatchesFilters || !row._.matchSearch) {
@@ -857,7 +831,6 @@ export default ({ service, customPopulateRow }) => {
       const { index } = await dispatch('findIndexOfExistingRow', {
         view,
         fields,
-        primary,
         row,
       })
       commit('DELETE_ROW_AT_INDEX', { index })
@@ -876,10 +849,7 @@ export default ({ service, customPopulateRow }) => {
      * need to updated and will make a call to the backend. If something goes wrong,
      * the row is moved back to the position.
      */
-    async stopRowDrag(
-      { dispatch, commit, getters },
-      { table, view, fields, primary }
-    ) {
+    async stopRowDrag({ dispatch, commit, getters }, { table, view, fields }) {
       const row = getters.getDraggingRow
 
       if (row === null) {
@@ -902,7 +872,7 @@ export default ({ service, customPopulateRow }) => {
           )
           commit('UPDATE_ROW', { row, values: data })
         } catch (error) {
-          dispatch('cancelRowDrag', { view, fields, primary, row, stop: false })
+          dispatch('cancelRowDrag', { view, fields, row, stop: false })
           throw error
         }
       }
@@ -913,7 +883,7 @@ export default ({ service, customPopulateRow }) => {
      */
     cancelRowDrag(
       { dispatch, getters, commit },
-      { view, fields, primary, row, stop = true }
+      { view, fields, row, stop = true }
     ) {
       if (stop) {
         const rows = getters.getRows
@@ -924,7 +894,6 @@ export default ({ service, customPopulateRow }) => {
       dispatch('afterExistingRowUpdated', {
         view,
         fields,
-        primary,
         row,
         values: row,
       })
@@ -958,7 +927,6 @@ export default ({ service, customPopulateRow }) => {
       { commit, dispatch, getters, state },
       {
         fields,
-        primary = null,
         activeSearchTerm = state.activeSearchTerm,
         refreshMatchesOnClient = true,
       }
@@ -969,7 +937,6 @@ export default ({ service, customPopulateRow }) => {
           dispatch('updateSearchMatchesForRow', {
             row,
             fields,
-            primary,
             forced: true,
           })
         )
@@ -982,7 +949,7 @@ export default ({ service, customPopulateRow }) => {
      */
     updateSearchMatchesForRow(
       { commit, getters, rootGetters },
-      { row, fields, primary = null, overrides, forced = false }
+      { row, fields, overrides, forced = false }
     ) {
       // Avoid computing search on table loading
       if (getters.getActiveSearchTerm || forced) {
@@ -990,7 +957,7 @@ export default ({ service, customPopulateRow }) => {
           row,
           getters.getActiveSearchTerm,
           getters.isHidingRowsNotMatchingSearch,
-          [primary, ...fields],
+          fields,
           this.$registry,
           overrides
         )
diff --git a/web-frontend/modules/database/store/view/gallery.js b/web-frontend/modules/database/store/view/gallery.js
index 29fe5136a..17d49c7a5 100644
--- a/web-frontend/modules/database/store/view/gallery.js
+++ b/web-frontend/modules/database/store/view/gallery.js
@@ -27,11 +27,10 @@ export const mutations = {
 }
 
 export const actions = {
-  async fetchInitial({ dispatch, commit }, { viewId, fields, primary }) {
+  async fetchInitial({ dispatch, commit }, { viewId, fields }) {
     const data = await dispatch('fetchInitialRows', {
       viewId,
       fields,
-      primary,
       initialRowArguments: { includeFieldOptions: true },
     })
     await dispatch('forceUpdateAllFieldOptions', data.field_options)
diff --git a/web-frontend/modules/database/store/view/grid.js b/web-frontend/modules/database/store/view/grid.js
index 659610c69..da069b750 100644
--- a/web-frontend/modules/database/store/view/grid.js
+++ b/web-frontend/modules/database/store/view/grid.js
@@ -506,7 +506,7 @@ export const actions = {
    */
   fetchByScrollTop(
     { commit, getters, rootGetters, dispatch },
-    { scrollTop, fields, primary }
+    { scrollTop, fields }
   ) {
     const windowHeight = getters.getWindowHeight
     const gridId = getters.getLastGridId
@@ -630,7 +630,7 @@ export const actions = {
             bufferLimit,
           })
           dispatch('visibleByScrollTop')
-          dispatch('updateSearch', { fields, primary })
+          dispatch('updateSearch', { fields })
           lastRequest = null
           fireScrollTop.processing = false
         })
@@ -715,7 +715,7 @@ export const actions = {
    * of calls. Therefore it will dispatch the related actions, but only every 100
    * milliseconds to prevent calling the actions who do a lot of calculating a lot.
    */
-  fetchByScrollTopDelayed({ dispatch }, { scrollTop, fields, primary }) {
+  fetchByScrollTopDelayed({ dispatch }, { scrollTop, fields }) {
     const now = Date.now()
 
     const fire = (scrollTop) => {
@@ -724,7 +724,6 @@ export const actions = {
       dispatch('fetchByScrollTop', {
         scrollTop,
         fields,
-        primary,
       })
       dispatch('visibleByScrollTop', scrollTop)
     }
@@ -753,7 +752,7 @@ export const actions = {
    */
   async fetchInitial(
     { dispatch, commit, getters, rootGetters },
-    { gridId, fields, primary }
+    { gridId, fields }
   ) {
     // Reset scrollTop when switching table
     fireScrollTop.distance = 0
@@ -798,7 +797,7 @@ export const actions = {
       top: 0,
     })
     commit('REPLACE_ALL_FIELD_OPTIONS', data.field_options)
-    dispatch('updateSearch', { fields, primary })
+    dispatch('updateSearch', { fields })
   },
   /**
    * Refreshes the current state with fresh data. It keeps the scroll offset the same
@@ -808,7 +807,7 @@ export const actions = {
    */
   refresh(
     { dispatch, commit, getters, rootGetters },
-    { view, fields, primary, includeFieldOptions = false }
+    { view, fields, includeFieldOptions = false }
   ) {
     const gridId = getters.getLastGridId
 
@@ -869,7 +868,7 @@ export const actions = {
           bufferStartIndex: offset,
           bufferLimit: data.results.length,
         })
-        dispatch('updateSearch', { fields, primary })
+        dispatch('updateSearch', { fields })
         if (includeFieldOptions) {
           if (getters.isPublic) {
             // If the view is public, then we're in read only mode and we want to
@@ -1281,10 +1280,10 @@ export const actions = {
    */
   removeRowSelectedBy(
     { dispatch, commit },
-    { grid, row, field, fields, primary, getScrollTop }
+    { grid, row, field, fields, getScrollTop }
   ) {
     commit('REMOVE_ROW_SELECTED_BY', { row, fieldId: field.id })
-    dispatch('refreshRow', { grid, row, fields, primary, getScrollTop })
+    dispatch('refreshRow', { grid, row, fields, getScrollTop })
   },
   /**
    * Called when the user wants to create a new row. Optionally a `before` row
@@ -1293,13 +1292,12 @@ export const actions = {
    */
   async createNewRow(
     { commit, getters, dispatch },
-    { view, table, fields, primary, values = {}, before = null }
+    { view, table, fields, values = {}, before = null }
   ) {
     // Fill the not provided values with the empty value of the field type so we can
     // immediately commit the created row to the state.
     const valuesForApiRequest = {}
-    const allFields = [primary].concat(fields)
-    allFields.forEach((field) => {
+    fields.forEach((field) => {
       const name = `field_${field.id}`
       const fieldType = this.$registry.get('field', field._.type.type)
       if (!(name in values)) {
@@ -1353,7 +1351,7 @@ export const actions = {
         order: data.order,
         values: data,
       })
-      dispatch('onRowChange', { view, row, fields, primary })
+      dispatch('onRowChange', { view, row, fields })
       dispatch('fetchAllFieldAggregationData', {
         view,
       })
@@ -1369,15 +1367,15 @@ export const actions = {
    */
   createdNewRow(
     { commit, getters, dispatch },
-    { view, fields, primary, values, metadata }
+    { view, fields, values, metadata }
   ) {
     const row = clone(values)
     populateRow(row, metadata)
 
     // Check if the row belongs into the current view by checking if it matches the
     // filters and search.
-    dispatch('updateMatchFilters', { view, row, fields, primary })
-    dispatch('updateSearchMatchesForRow', { row, fields, primary })
+    dispatch('updateMatchFilters', { view, row, fields })
+    dispatch('updateSearchMatchesForRow', { row, fields })
 
     // If the row does not match the filters or the search then we don't have to add
     // it at all.
@@ -1392,8 +1390,7 @@ export const actions = {
     const sortFunction = getRowSortFunction(
       this.$registry,
       view.sortings,
-      fields,
-      primary
+      fields
     )
     allRowsCopy.sort(sortFunction)
     const index = allRowsCopy.findIndex((r) => r.id === row.id)
@@ -1427,7 +1424,7 @@ export const actions = {
    */
   async moveRow(
     { commit, dispatch, getters },
-    { table, grid, fields, primary, getScrollTop, row, before = null }
+    { table, grid, fields, getScrollTop, row, before = null }
   ) {
     const oldOrder = row.order
 
@@ -1447,7 +1444,7 @@ export const actions = {
 
     // In order to make changes feel really fast, we optimistically
     // updated all the field values that provide a onRowMove function
-    const fieldsToCallOnRowMove = [...fields, primary]
+    const fieldsToCallOnRowMove = fields
     const optimisticFieldValues = {}
     const valuesBeforeOptimisticUpdate = {}
 
@@ -1471,7 +1468,6 @@ export const actions = {
     dispatch('updatedExistingRow', {
       view: grid,
       fields,
-      primary,
       row,
       values: { order, ...optimisticFieldValues },
     })
@@ -1494,14 +1490,12 @@ export const actions = {
       dispatch('fetchByScrollTopDelayed', {
         scrollTop: getScrollTop(),
         fields,
-        primary,
       })
       dispatch('fetchAllFieldAggregationData', { view: grid })
     } catch (error) {
       dispatch('updatedExistingRow', {
         view: grid,
         fields,
-        primary,
         row,
         values: { order: oldOrder, ...valuesBeforeOptimisticUpdate },
       })
@@ -1515,7 +1509,7 @@ export const actions = {
    */
   async updateRowValue(
     { commit, dispatch },
-    { table, view, row, field, fields, primary, value, oldValue }
+    { table, view, row, field, fields, value, oldValue }
   ) {
     // Immediately updated the store with the updated row field
     // value.
@@ -1528,7 +1522,7 @@ export const actions = {
     // in case we need to rollback changes
     valuesBeforeOptimisticUpdate[`field_${field.id}`] = oldValue
 
-    let fieldsToCallOnRowChange = [...fields, primary]
+    let fieldsToCallOnRowChange = fields
 
     // We already added the updated field values to the store
     // so we can remove the field from our fieldsToCallOnRowChange
@@ -1555,7 +1549,7 @@ export const actions = {
       row,
       values: { ...optimisticFieldValues },
     })
-    dispatch('onRowChange', { view, row, fields, primary })
+    dispatch('onRowChange', { view, row, fields })
 
     const fieldType = this.$registry.get('field', field._.type.type)
     const newValue = fieldType.prepareValueForUpdate(field, value)
@@ -1569,7 +1563,7 @@ export const actions = {
         values
       )
       commit('UPDATE_ROW_IN_BUFFER', { row, values: updatedRow.data })
-      dispatch('onRowChange', { view, row, fields, primary })
+      dispatch('onRowChange', { view, row, fields })
       dispatch('fetchAllFieldAggregationData', {
         view,
       })
@@ -1579,7 +1573,7 @@ export const actions = {
         values: { ...valuesBeforeOptimisticUpdate },
       })
 
-      dispatch('onRowChange', { view, row, fields, primary })
+      dispatch('onRowChange', { view, row, fields })
       throw error
     }
   },
@@ -1590,7 +1584,7 @@ export const actions = {
    */
   async updateDataIntoCells(
     { getters, commit, dispatch },
-    { table, view, primary, fields, getScrollTop, data, rowIndex, fieldIndex }
+    { table, view, fields, getScrollTop, data, rowIndex, fieldIndex }
   ) {
     // If the origin origin row and field index are not provided, we need to use the
     // head indexes of the multiple select.
@@ -1703,7 +1697,6 @@ export const actions = {
       await dispatch('updatedExistingRow', {
         view,
         fields,
-        primary,
         row,
         values,
       })
@@ -1714,7 +1707,6 @@ export const actions = {
     await dispatch('fetchByScrollTopDelayed', {
       scrollTop: getScrollTop(),
       fields,
-      primary,
     })
     dispatch('fetchAllFieldAggregationData', { view })
   },
@@ -1725,29 +1717,28 @@ export const actions = {
    */
   updatedExistingRow(
     { commit, getters, dispatch },
-    { view, fields, primary, row, values, metadata }
+    { view, fields, row, values, metadata }
   ) {
     const oldRow = clone(row)
     const newRow = Object.assign(clone(row), values)
     populateRow(oldRow, metadata)
     populateRow(newRow, metadata)
 
-    dispatch('updateMatchFilters', { view, row: oldRow, fields, primary })
-    dispatch('updateSearchMatchesForRow', { row: oldRow, fields, primary })
+    dispatch('updateMatchFilters', { view, row: oldRow, fields })
+    dispatch('updateSearchMatchesForRow', { row: oldRow, fields })
 
-    dispatch('updateMatchFilters', { view, row: newRow, fields, primary })
-    dispatch('updateSearchMatchesForRow', { row: newRow, fields, primary })
+    dispatch('updateMatchFilters', { view, row: newRow, fields })
+    dispatch('updateSearchMatchesForRow', { row: newRow, fields })
 
     const oldRowExists = oldRow._.matchFilters && oldRow._.matchSearch
     const newRowExists = newRow._.matchFilters && newRow._.matchSearch
 
     if (oldRowExists && !newRowExists) {
-      dispatch('deletedExistingRow', { view, fields, primary, row })
+      dispatch('deletedExistingRow', { view, fields, row })
     } else if (!oldRowExists && newRowExists) {
       dispatch('createdNewRow', {
         view,
         fields,
-        primary,
         values: newRow,
         metadata,
       })
@@ -1767,8 +1758,7 @@ export const actions = {
       const sortFunction = getRowSortFunction(
         this.$registry,
         view.sortings,
-        fields,
-        primary
+        fields
       )
       const allRows = getters.getAllRows
       const index = allRows.findIndex((r) => r.id === row.id)
@@ -1858,7 +1848,7 @@ export const actions = {
    */
   async deleteExistingRow(
     { commit, dispatch, getters },
-    { table, view, row, fields, primary, getScrollTop }
+    { table, view, row, fields, getScrollTop }
   ) {
     commit('SET_ROW_LOADING', { row, value: true })
 
@@ -1867,14 +1857,12 @@ export const actions = {
       await dispatch('deletedExistingRow', {
         view,
         fields,
-        primary,
         row,
         getScrollTop,
       })
       await dispatch('fetchByScrollTopDelayed', {
         scrollTop: getScrollTop(),
         fields,
-        primary,
       })
       dispatch('fetchAllFieldAggregationData', { view })
     } catch (error) {
@@ -1887,7 +1875,7 @@ export const actions = {
    */
   async deleteSelectedRows(
     { dispatch, getters },
-    { table, view, fields, primary, getScrollTop }
+    { table, view, fields, getScrollTop }
   ) {
     if (!getters.isMultiSelectActive) {
       return
@@ -1913,7 +1901,6 @@ export const actions = {
       await dispatch('deletedExistingRow', {
         view,
         fields,
-        primary,
         row,
         getScrollTop,
       })
@@ -1922,7 +1909,6 @@ export const actions = {
     await dispatch('fetchByScrollTopDelayed', {
       scrollTop: getScrollTop(),
       fields,
-      primary,
     })
     dispatch('fetchAllFieldAggregationData', { view })
   },
@@ -1930,16 +1916,13 @@ export const actions = {
    * Called after an existing row has been deleted, which could be by the user or
    * via another channel.
    */
-  deletedExistingRow(
-    { commit, getters, dispatch },
-    { view, fields, primary, row }
-  ) {
+  deletedExistingRow({ commit, getters, dispatch }, { view, fields, row }) {
     row = clone(row)
     populateRow(row)
 
     // Check if that row was visible in the view.
-    dispatch('updateMatchFilters', { view, row, fields, primary })
-    dispatch('updateSearchMatchesForRow', { row, fields, primary })
+    dispatch('updateMatchFilters', { view, row, fields })
+    dispatch('updateSearchMatchesForRow', { row, fields })
 
     // If the row does not match the filters or the search then did not exist in the
     // view, so we don't have to do anything.
@@ -1965,8 +1948,7 @@ export const actions = {
     const sortFunction = getRowSortFunction(
       this.$registry,
       view.sortings,
-      fields,
-      primary
+      fields
     )
     allRowsCopy.sort(sortFunction)
     const index = allRowsCopy.findIndex((r) => r.id === row.id)
@@ -1984,20 +1966,17 @@ export const actions = {
    * Triggered when a row has been changed, or has a pending change in the provided
    * overrides.
    */
-  onRowChange({ dispatch }, { view, row, fields, primary, overrides = {} }) {
-    dispatch('updateMatchFilters', { view, row, fields, primary, overrides })
-    dispatch('updateMatchSortings', { view, row, fields, primary, overrides })
-    dispatch('updateSearchMatchesForRow', { row, fields, primary, overrides })
+  onRowChange({ dispatch }, { view, row, fields, overrides = {} }) {
+    dispatch('updateMatchFilters', { view, row, fields, overrides })
+    dispatch('updateMatchSortings', { view, row, fields, overrides })
+    dispatch('updateSearchMatchesForRow', { row, fields, overrides })
   },
   /**
    * Checks if the given row still matches the given view filters. The row's
    * matchFilters value is updated accordingly. It is also possible to provide some
    * override values that not actually belong to the row to do some preliminary checks.
    */
-  updateMatchFilters(
-    { commit },
-    { view, row, fields, primary, overrides = {} }
-  ) {
+  updateMatchFilters({ commit }, { view, row, fields, overrides = {} }) {
     const values = JSON.parse(JSON.stringify(row))
     Object.assign(values, overrides)
 
@@ -2008,7 +1987,7 @@ export const actions = {
           this.$registry,
           view.filter_type,
           view.filters,
-          primary === null ? fields : [primary, ...fields],
+          fields,
           values
         )
     commit('SET_ROW_MATCH_FILTERS', { row, value: matches })
@@ -2022,7 +2001,6 @@ export const actions = {
     { commit, dispatch, getters, state },
     {
       fields,
-      primary = null,
       activeSearchTerm = state.activeSearchTerm,
       hideRowsNotMatchingSearch = state.hideRowsNotMatchingSearch,
       refreshMatchesOnClient = true,
@@ -2034,7 +2012,6 @@ export const actions = {
         dispatch('updateSearchMatchesForRow', {
           row,
           fields,
-          primary,
           forced: true,
         })
       )
@@ -2047,7 +2024,7 @@ export const actions = {
    */
   updateSearchMatchesForRow(
     { commit, getters, rootGetters },
-    { row, fields, primary = null, overrides, forced = false }
+    { row, fields = null, overrides, forced = false }
   ) {
     // Avoid computing search on table loading
     if (getters.getActiveSearchTerm || forced) {
@@ -2055,7 +2032,7 @@ export const actions = {
         row,
         getters.getActiveSearchTerm,
         getters.isHidingRowsNotMatchingSearch,
-        [primary, ...fields],
+        fields,
         this.$registry,
         overrides
       )
@@ -2070,7 +2047,7 @@ export const actions = {
    */
   updateMatchSortings(
     { commit, getters },
-    { view, row, fields, primary = null, overrides = {} }
+    { view, row, fields, overrides = {} }
   ) {
     const values = clone(row)
     Object.assign(values, overrides)
@@ -2079,9 +2056,7 @@ export const actions = {
     const currentIndex = getters.getAllRows.findIndex((r) => r.id === row.id)
     const sortedRows = clone(allRows)
     sortedRows[currentIndex] = values
-    sortedRows.sort(
-      getRowSortFunction(this.$registry, view.sortings, fields, primary)
-    )
+    sortedRows.sort(getRowSortFunction(this.$registry, view.sortings, fields))
     const newIndex = sortedRows.findIndex((r) => r.id === row.id)
 
     commit('SET_ROW_MATCH_SORTINGS', { row, value: currentIndex === newIndex })
@@ -2092,7 +2067,7 @@ export const actions = {
    */
   async refreshRow(
     { dispatch, commit, getters },
-    { grid, row, fields, primary, getScrollTop }
+    { grid, row, fields, getScrollTop }
   ) {
     const rowShouldBeHidden = !row._.matchFilters || !row._.matchSearch
     if (row._.selectedBy.length === 0 && rowShouldBeHidden) {
@@ -2101,7 +2076,6 @@ export const actions = {
       await dispatch('updatedExistingRow', {
         view: grid,
         fields,
-        primary,
         row,
         values: row,
       })
@@ -2110,7 +2084,6 @@ export const actions = {
     dispatch('fetchByScrollTopDelayed', {
       scrollTop: getScrollTop(),
       fields,
-      primary,
     })
   },
   updateRowMetadata(
@@ -2130,7 +2103,7 @@ export const actions = {
    */
   async clearValuesFromMultipleCellSelection(
     { getters, dispatch },
-    { table, view, primary, fields, getScrollTop }
+    { table, view, fields, getScrollTop }
   ) {
     const [minFieldIndex, maxFieldIndex] =
       getters.getMultiSelectFieldIndexSorted
@@ -2156,7 +2129,6 @@ export const actions = {
     await dispatch('updateDataIntoCells', {
       table,
       view,
-      primary,
       fields,
       getScrollTop,
       data,
diff --git a/web-frontend/modules/database/utils/field.js b/web-frontend/modules/database/utils/field.js
new file mode 100644
index 000000000..46d680629
--- /dev/null
+++ b/web-frontend/modules/database/utils/field.js
@@ -0,0 +1,10 @@
+/**
+ * Find the primary field in a list of fields.
+ * If no primary field is found, return the first field.
+ * @param fields
+ * @returns {*}
+ */
+export function getPrimaryOrFirstField(fields) {
+  const primaryField = fields.find((field) => field.primary)
+  return primaryField || fields[0]
+}
diff --git a/web-frontend/modules/database/utils/view.js b/web-frontend/modules/database/utils/view.js
index 2e7094145..b782d541c 100644
--- a/web-frontend/modules/database/utils/view.js
+++ b/web-frontend/modules/database/utils/view.js
@@ -5,20 +5,12 @@ import { maxPossibleOrderValue } from '@baserow/modules/database/viewTypes'
 /**
  * Generates a sort function based on the provided sortings.
  */
-export function getRowSortFunction(
-  $registry,
-  sortings,
-  fields,
-  primary = null
-) {
+export function getRowSortFunction($registry, sortings, fields) {
   let sortFunction = firstBy()
 
   sortings.forEach((sort) => {
     // Find the field that is related to the sort.
-    let field = fields.find((f) => f.id === sort.field)
-    if (field === undefined && primary !== null && primary.id === sort.field) {
-      field = primary
-    }
+    const field = fields.find((f) => f.id === sort.field)
 
     if (field !== undefined) {
       const fieldName = `field_${field.id}`
diff --git a/web-frontend/modules/database/viewTypes.js b/web-frontend/modules/database/viewTypes.js
index 9d4227ba2..d15558e77 100644
--- a/web-frontend/modules/database/viewTypes.js
+++ b/web-frontend/modules/database/viewTypes.js
@@ -170,7 +170,6 @@ export class ViewType extends Registerable {
     context,
     view,
     fields,
-    primary,
     storePrefix = '',
     includeFieldOptions = false
   ) {}
@@ -228,38 +227,21 @@ export class ViewType extends Registerable {
    * via a real time event by another user. It can be used to check if data in an store
    * needs to be updated.
    */
-  rowCreated(
-    context,
-    tableId,
-    fields,
-    primary,
-    values,
-    metadata,
-    storePrefix
-  ) {}
+  rowCreated(context, tableId, fields, values, metadata, storePrefix) {}
 
   /**
    * Event that is called when a row is updated from an outside source, so for example
    * via a real time event by another user. It can be used to check if data in an store
    * needs to be updated.
    */
-  rowUpdated(
-    context,
-    tableId,
-    fields,
-    primary,
-    row,
-    values,
-    metadata,
-    storePrefix
-  ) {}
+  rowUpdated(context, tableId, fields, row, values, metadata, storePrefix) {}
 
   /**
    * Event that is called when a row is deleted from an outside source, so for example
    * via a real time event by another user. It can be used to check if data in an store
    * needs to be updated.
    */
-  rowDeleted(context, tableId, fields, primary, row, storePrefix) {}
+  rowDeleted(context, tableId, fields, row, storePrefix) {}
 
   /**
    * Event that is called when a piece of metadata is updated for a particular row.
@@ -357,11 +339,10 @@ export class GridViewType extends ViewType {
     return 'database-public-grid-view'
   }
 
-  async fetch({ store }, view, fields, primary, storePrefix = '') {
+  async fetch({ store }, view, fields, storePrefix = '') {
     await store.dispatch(storePrefix + 'view/grid/fetchInitial', {
       gridId: view.id,
       fields,
-      primary,
     })
   }
 
@@ -369,14 +350,12 @@ export class GridViewType extends ViewType {
     { store },
     view,
     fields,
-    primary,
     storePrefix = '',
     includeFieldOptions = false
   ) {
     await store.dispatch(storePrefix + 'view/grid/refresh', {
       view,
       fields,
-      primary,
       includeFieldOptions,
     })
   }
@@ -460,7 +439,6 @@ export class GridViewType extends ViewType {
       storePrefix + 'view/grid/updateSearch',
       {
         fields: rootGetters['field/getAll'],
-        primary: rootGetters['field/getPrimary'],
       },
       {
         root: true,
@@ -482,7 +460,6 @@ export class GridViewType extends ViewType {
     { store },
     tableId,
     fields,
-    primary,
     values,
     metadata,
     storePrefix = ''
@@ -491,14 +468,12 @@ export class GridViewType extends ViewType {
       await store.dispatch(storePrefix + 'view/grid/createdNewRow', {
         view: store.getters['view/getSelected'],
         fields,
-        primary,
         values,
         metadata,
       })
       await store.dispatch(storePrefix + 'view/grid/fetchByScrollTopDelayed', {
         scrollTop: store.getters[storePrefix + 'view/grid/getScrollTop'],
         fields,
-        primary,
       })
       store.dispatch(storePrefix + 'view/grid/fetchAllFieldAggregationData', {
         view: store.getters['view/getSelected'],
@@ -510,7 +485,6 @@ export class GridViewType extends ViewType {
     { store },
     tableId,
     fields,
-    primary,
     row,
     values,
     metadata,
@@ -520,7 +494,6 @@ export class GridViewType extends ViewType {
       await store.dispatch(storePrefix + 'view/grid/updatedExistingRow', {
         view: store.getters['view/getSelected'],
         fields,
-        primary,
         row,
         values,
         metadata,
@@ -528,7 +501,6 @@ export class GridViewType extends ViewType {
       await store.dispatch(storePrefix + 'view/grid/fetchByScrollTopDelayed', {
         scrollTop: store.getters[storePrefix + 'view/grid/getScrollTop'],
         fields,
-        primary,
       })
       store.dispatch(storePrefix + 'view/grid/fetchAllFieldAggregationData', {
         view: store.getters['view/getSelected'],
@@ -536,18 +508,16 @@ export class GridViewType extends ViewType {
     }
   }
 
-  async rowDeleted({ store }, tableId, fields, primary, row, storePrefix = '') {
+  async rowDeleted({ store }, tableId, fields, row, storePrefix = '') {
     if (this.isCurrentView(store, tableId)) {
       await store.dispatch(storePrefix + 'view/grid/deletedExistingRow', {
         view: store.getters['view/getSelected'],
         fields,
-        primary,
         row,
       })
       await store.dispatch(storePrefix + 'view/grid/fetchByScrollTopDelayed', {
         scrollTop: store.getters[storePrefix + 'view/grid/getScrollTop'],
         fields,
-        primary,
       })
       store.dispatch(storePrefix + 'view/grid/fetchAllFieldAggregationData', {
         view: store.getters['view/getSelected'],
@@ -584,11 +554,10 @@ class BaseBufferedRowView extends ViewType {
     return {}
   }
 
-  async fetch({ store }, view, fields, primary, storePrefix = '') {
+  async fetch({ store }, view, fields, storePrefix = '') {
     await store.dispatch(`${storePrefix}view/${this.getType()}/fetchInitial`, {
       viewId: view.id,
       fields,
-      primary,
     })
   }
 
@@ -596,13 +565,11 @@ class BaseBufferedRowView extends ViewType {
     { store },
     view,
     fields,
-    primary,
     storePrefix = '',
     includeFieldOptions = false
   ) {
     await store.dispatch(storePrefix + 'view/' + this.getType() + '/refresh', {
       fields,
-      primary,
       includeFieldOptions,
     })
   }
@@ -679,7 +646,6 @@ class BaseBufferedRowView extends ViewType {
     { store },
     tableId,
     fields,
-    primary,
     values,
     metadata,
     storePrefix = ''
@@ -690,7 +656,6 @@ class BaseBufferedRowView extends ViewType {
         {
           view: store.getters['view/getSelected'],
           fields,
-          primary,
           values,
         }
       )
@@ -701,7 +666,6 @@ class BaseBufferedRowView extends ViewType {
     { store },
     tableId,
     fields,
-    primary,
     row,
     values,
     metadata,
@@ -713,7 +677,6 @@ class BaseBufferedRowView extends ViewType {
         {
           view: store.getters['view/getSelected'],
           fields,
-          primary,
           row,
           values,
         }
@@ -721,14 +684,13 @@ class BaseBufferedRowView extends ViewType {
     }
   }
 
-  async rowDeleted({ store }, tableId, fields, primary, row, storePrefix = '') {
+  async rowDeleted({ store }, tableId, fields, row, storePrefix = '') {
     if (this.isCurrentView(store, tableId)) {
       await store.dispatch(
         storePrefix + 'view/' + this.getType() + '/afterExistingRowDeleted',
         {
           view: store.getters['view/getSelected'],
           fields,
-          primary,
           row,
         }
       )
@@ -797,7 +759,6 @@ export class GalleryViewType extends BaseBufferedRowView {
       storePrefix + 'view/gallery/updateSearch',
       {
         fields: rootGetters['field/getAll'],
-        primary: rootGetters['field/getPrimary'],
       },
       {
         root: true,
@@ -871,7 +832,6 @@ export class FormViewType extends ViewType {
     { store },
     view,
     fields,
-    primary,
     storePrefix = '',
     includeFieldOptions = false
   ) {
@@ -913,7 +873,7 @@ export class FormViewType extends ViewType {
     )
   }
 
-  async fetch({ store }, view, fields, primary, storePrefix = '') {
+  async fetch({ store }, view, fields, storePrefix = '') {
     await store.dispatch(storePrefix + 'view/form/fetchInitial', {
       formId: view.id,
     })
diff --git a/web-frontend/test/unit/database/components/view/__snapshots__/viewFilterForm.spec.js.snap b/web-frontend/test/unit/database/components/view/__snapshots__/viewFilterForm.spec.js.snap
index e14bfdcc8..54f33a0e9 100644
--- a/web-frontend/test/unit/database/components/view/__snapshots__/viewFilterForm.spec.js.snap
+++ b/web-frontend/test/unit/database/components/view/__snapshots__/viewFilterForm.spec.js.snap
@@ -135,7 +135,6 @@ exports[`ViewFilterForm component Full view filter component 1`] = `
                   <!---->
                 </a>
               </li>
-               
               <li
                 class="select__item"
               >
@@ -502,7 +501,6 @@ exports[`ViewFilterForm component Full view filter component 1`] = `
                   <!---->
                 </a>
               </li>
-               
               <li
                 class="select__item active"
               >
@@ -805,7 +803,6 @@ exports[`ViewFilterForm component Test rating filter 1`] = `
                   <!---->
                 </a>
               </li>
-               
               <li
                 class="select__item active"
               >
@@ -1108,7 +1105,6 @@ exports[`ViewFilterForm component Test rating filter 2`] = `
                   <!---->
                 </a>
               </li>
-               
               <li
                 class="select__item active"
               >
diff --git a/web-frontend/test/unit/database/components/view/gallery/galleryViewDecoration.spec.js b/web-frontend/test/unit/database/components/view/gallery/galleryViewDecoration.spec.js
index 5ec1e1c04..02e9a5026 100644
--- a/web-frontend/test/unit/database/components/view/gallery/galleryViewDecoration.spec.js
+++ b/web-frontend/test/unit/database/components/view/gallery/galleryViewDecoration.spec.js
@@ -127,22 +127,20 @@ describe('GalleryView component with decoration', () => {
     })
     mockServer.createFields(application, table, fieldData)
     await store.dispatch('field/fetchAll', table)
-    const primary = store.getters['field/getPrimary']
     const fields = store.getters['field/getAll']
 
     mockServer.createGalleryRows(view, fields, rows)
     await store.dispatch('page/view/gallery/fetchInitial', {
       viewId: 1,
       fields,
-      primary,
     })
     await store.dispatch('view/fetchAll', { id: 1 })
 
-    return { application, table, primary, fields, view }
+    return { application, table, fields, view }
   }
 
   test('Default component with first_cell decoration', async () => {
-    const { application, table, primary, fields, view } = await populateStore([
+    const { application, table, fields, view } = await populateStore([
       {
         type: 'fake_decorator',
         value_provider_type: 'fake_value_provider_type',
@@ -165,7 +163,6 @@ describe('GalleryView component with decoration', () => {
       database: application,
       table,
       view,
-      primary,
       fields,
       readOnly: false,
       storePrefix: 'page/',
@@ -175,7 +172,7 @@ describe('GalleryView component with decoration', () => {
   })
 
   test('Default component with row wrapper decoration', async () => {
-    const { application, table, primary, fields, view } = await populateStore([
+    const { application, table, fields, view } = await populateStore([
       {
         type: 'fake_decorator',
         value_provider_type: 'fake_value_provider_type',
@@ -214,7 +211,6 @@ describe('GalleryView component with decoration', () => {
       database: application,
       table,
       view,
-      primary,
       fields,
       readOnly: false,
       storePrefix: 'page/',
@@ -224,7 +220,7 @@ describe('GalleryView component with decoration', () => {
   })
 
   test('Default component with unavailable decoration', async () => {
-    const { application, table, primary, fields, view } = await populateStore([
+    const { application, table, fields, view } = await populateStore([
       {
         type: 'fake_decorator',
         value_provider_type: 'fake_value_provider_type',
@@ -244,7 +240,6 @@ describe('GalleryView component with decoration', () => {
       database: application,
       table,
       view,
-      primary,
       fields,
       readOnly: false,
       storePrefix: 'page/',
diff --git a/web-frontend/test/unit/database/components/view/grid/gridViewDecoration.spec.js b/web-frontend/test/unit/database/components/view/grid/gridViewDecoration.spec.js
index 6b3a5fa25..15ca26d4a 100644
--- a/web-frontend/test/unit/database/components/view/grid/gridViewDecoration.spec.js
+++ b/web-frontend/test/unit/database/components/view/grid/gridViewDecoration.spec.js
@@ -137,11 +137,11 @@ describe('GridView component with decoration', () => {
       primary,
     })
     await store.dispatch('view/fetchAll', { id: 1 })
-    return { application, table, primary, fields, view }
+    return { application, table, fields, view }
   }
 
   test('Default component with first_cell decoration', async () => {
-    const { application, table, primary, fields, view } = await populateStore([
+    const { application, table, fields, view } = await populateStore([
       {
         type: 'fake_decorator',
         value_provider_type: 'fake_value_provider_type',
@@ -164,7 +164,6 @@ describe('GridView component with decoration', () => {
       database: application,
       table,
       view,
-      primary,
       fields,
       readOnly: false,
       storePrefix: 'page/',
@@ -174,7 +173,7 @@ describe('GridView component with decoration', () => {
   })
 
   test('Default component with row wrapper decoration', async () => {
-    const { application, table, primary, fields, view } = await populateStore([
+    const { application, table, fields, view } = await populateStore([
       {
         type: 'fake_decorator',
         value_provider_type: 'fake_value_provider_type',
@@ -213,7 +212,6 @@ describe('GridView component with decoration', () => {
       database: application,
       table,
       view,
-      primary,
       fields,
       readOnly: false,
       storePrefix: 'page/',
@@ -223,7 +221,7 @@ describe('GridView component with decoration', () => {
   })
 
   test('Default component with unavailable decoration', async () => {
-    const { application, table, primary, fields, view } = await populateStore([
+    const { application, table, fields, view } = await populateStore([
       {
         type: 'fake_decorator',
         value_provider_type: 'fake_value_provider_type',
@@ -243,7 +241,6 @@ describe('GridView component with decoration', () => {
       database: application,
       table,
       view,
-      primary,
       fields,
       readOnly: false,
       storePrefix: 'page/',
diff --git a/web-frontend/test/unit/database/components/view/viewDecoratorContext.spec.js b/web-frontend/test/unit/database/components/view/viewDecoratorContext.spec.js
index 8260a7f16..a95cb115a 100644
--- a/web-frontend/test/unit/database/components/view/viewDecoratorContext.spec.js
+++ b/web-frontend/test/unit/database/components/view/viewDecoratorContext.spec.js
@@ -163,7 +163,7 @@ describe('GridViewRows component with decoration', () => {
       primary,
     })
     await store.dispatch('view/fetchAll', { id: table.id })
-    return { application, table, primary, fields, view }
+    return { application, table, fields, view }
   }
 
   const mountComponent = async (props) => {
@@ -181,7 +181,7 @@ describe('GridViewRows component with decoration', () => {
   }
 
   test('Default component', async () => {
-    const { application, table, primary, fields, view } = await populateStore()
+    const { application, table, fields, view } = await populateStore()
 
     const fakeDecorator = new FakeDecoratorType({ app: testApp })
     const fakeValueProvider = new FakeValueProviderType({ app: testApp })
@@ -193,7 +193,6 @@ describe('GridViewRows component with decoration', () => {
       database: application,
       view,
       table,
-      primary,
       fields,
       readOnly: false,
     })
@@ -202,7 +201,7 @@ describe('GridViewRows component with decoration', () => {
   })
 
   test('View with decoration configured', async () => {
-    const { application, table, primary, fields, view } = await populateStore({
+    const { application, table, fields, view } = await populateStore({
       decorations: [
         {
           type: 'fake_decorator',
@@ -229,7 +228,6 @@ describe('GridViewRows component with decoration', () => {
       database: application,
       view,
       table,
-      primary,
       fields,
       readOnly: false,
     })
@@ -238,7 +236,7 @@ describe('GridViewRows component with decoration', () => {
   })
 
   test('Should show unavailable decorator tooltip', async () => {
-    const { application, table, primary, fields, view } = await populateStore()
+    const { application, table, fields, view } = await populateStore()
 
     const fakeDecorator = new FakeDecoratorType({ app: testApp })
     const fakeValueProvider = new FakeValueProviderType({ app: testApp })
@@ -252,7 +250,6 @@ describe('GridViewRows component with decoration', () => {
       database: application,
       view,
       table,
-      primary,
       fields,
       readOnly: false,
     })
@@ -265,7 +262,7 @@ describe('GridViewRows component with decoration', () => {
   })
 
   test('Should show cant add decorator tooltip', async () => {
-    const { application, table, primary, fields, view } = await populateStore()
+    const { application, table, fields, view } = await populateStore()
 
     const fakeDecorator = new FakeDecoratorType({ app: testApp })
     const fakeValueProvider = new FakeValueProviderType({ app: testApp })
@@ -279,7 +276,6 @@ describe('GridViewRows component with decoration', () => {
       database: application,
       view,
       table,
-      primary,
       fields,
       readOnly: false,
     })
diff --git a/web-frontend/test/unit/database/components/view/viewFilterForm.spec.js b/web-frontend/test/unit/database/components/view/viewFilterForm.spec.js
index ebf85636e..40a025d00 100644
--- a/web-frontend/test/unit/database/components/view/viewFilterForm.spec.js
+++ b/web-frontend/test/unit/database/components/view/viewFilterForm.spec.js
@@ -1,19 +1,18 @@
 import { TestApp } from '@baserow/test/helpers/testApp'
 import ViewFilterForm from '@baserow/modules/database/components/view/ViewFilterForm'
 
-const primary = {
-  id: 1,
-  name: 'Name',
-  order: 0,
-  type: 'text',
-  primary: true,
-  text_default: '',
-  _: {
-    loading: false,
-  },
-}
-
 const fields = [
+  {
+    id: 1,
+    name: 'Name',
+    order: 0,
+    type: 'text',
+    primary: true,
+    text_default: '',
+    _: {
+      loading: false,
+    },
+  },
   {
     id: 2,
     table_id: 196,
@@ -91,7 +90,6 @@ describe('ViewFilterForm component', () => {
 
   const mountViewFilterForm = async (
     props = {
-      primary: {},
       fields: [],
       view: { filters: [], _: {} },
       readOnly: false,
@@ -112,7 +110,6 @@ describe('ViewFilterForm component', () => {
 
   test('Full view filter component', async () => {
     const wrapper = await mountViewFilterForm({
-      primary,
       fields,
       view,
       readOnly: false,
@@ -150,7 +147,6 @@ describe('ViewFilterForm component', () => {
     // Mounting the component
     const wrapper = await mountViewFilterForm(
       {
-        primary,
         fields,
         view: viewClone,
         readOnly: false,
diff --git a/web-frontend/test/unit/database/store/view/bufferedRows.spec.js b/web-frontend/test/unit/database/store/view/bufferedRows.spec.js
index ffe91d15f..f46b0336e 100644
--- a/web-frontend/test/unit/database/store/view/bufferedRows.spec.js
+++ b/web-frontend/test/unit/database/store/view/bufferedRows.spec.js
@@ -373,13 +373,14 @@ describe('Buffered rows view store helper', () => {
       filters: [],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -414,7 +415,6 @@ describe('Buffered rows view store helper', () => {
     let index = await store.dispatch('test/findIndexOfNotExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 0,
         order: '0.00000000000000000000',
@@ -426,7 +426,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfNotExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 5,
         order: '3.50000000000000000000',
@@ -438,7 +437,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfNotExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 5,
         order: '5.00000000000000000000',
@@ -450,7 +448,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfNotExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 13,
         order: '13.50000000000000000000',
@@ -462,7 +459,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfNotExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 100,
         order: '100.00000000000000000000',
@@ -480,13 +476,14 @@ describe('Buffered rows view store helper', () => {
       filters: [],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -523,7 +520,6 @@ describe('Buffered rows view store helper', () => {
     let index = await store.dispatch('test/findIndexOfNotExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 4,
         order: '4.00000000000000000000',
@@ -535,7 +531,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfNotExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 2,
         order: '2.00000000000000000000',
@@ -547,7 +542,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfNotExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 13,
         order: '13.00000000000000000000',
@@ -559,7 +553,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfNotExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 100,
         order: '100.00000000000000000000',
@@ -577,13 +570,14 @@ describe('Buffered rows view store helper', () => {
       filters: [],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -618,7 +612,6 @@ describe('Buffered rows view store helper', () => {
     let index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 1,
         order: '1.00000000000000000000',
@@ -630,7 +623,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 3,
         order: '3.00000000000000000000',
@@ -642,7 +634,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 4,
         order: '4.00000000000000000000',
@@ -654,7 +645,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 5,
         order: '5.00000000000000000000',
@@ -666,7 +656,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 10,
         order: '10.00000000000000000000',
@@ -678,7 +667,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 14,
         order: '14.00000000000000000000',
@@ -690,7 +678,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 15,
         order: '15.00000000000000000000',
@@ -709,13 +696,14 @@ describe('Buffered rows view store helper', () => {
       filters: [],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -752,7 +740,6 @@ describe('Buffered rows view store helper', () => {
     let index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 1,
         order: '1.00000000000000000000',
@@ -764,7 +751,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 0,
         order: '0.00000000000000000000',
@@ -776,7 +762,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 4,
         order: '4.00000000000000000000',
@@ -788,7 +773,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 6,
         order: '6.00000000000000000000',
@@ -800,7 +784,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 12,
         order: '12.00000000000000000000',
@@ -812,7 +795,6 @@ describe('Buffered rows view store helper', () => {
     index = await store.dispatch('test/findIndexOfExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 15,
         order: '15.00000000000000000000',
@@ -838,13 +820,14 @@ describe('Buffered rows view store helper', () => {
       ],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
 
     const testStore = bufferedRows({ service: null, populateRow: null })
     store.registerModule('test', testStore)
@@ -853,7 +836,6 @@ describe('Buffered rows view store helper', () => {
       await store.dispatch('test/rowMatchesFilters', {
         view,
         fields,
-        primary,
         row: { id: 12, order: '12.00000000000000000000', field_1: 'Value 12' },
       })
     ).toBe(true)
@@ -861,7 +843,6 @@ describe('Buffered rows view store helper', () => {
       await store.dispatch('test/rowMatchesFilters', {
         view,
         fields,
-        primary,
         row: {
           id: 12,
           order: '12.00000000000000000000',
@@ -873,7 +854,6 @@ describe('Buffered rows view store helper', () => {
       await store.dispatch('test/rowMatchesFilters', {
         view,
         fields,
-        primary,
         row: {
           id: 12,
           order: '12.00000000000000000000',
@@ -887,7 +867,6 @@ describe('Buffered rows view store helper', () => {
       await store.dispatch('test/rowMatchesFilters', {
         view,
         fields,
-        primary,
         row: {
           id: 12,
           order: '12.00000000000000000000',
@@ -905,13 +884,14 @@ describe('Buffered rows view store helper', () => {
       filters: [],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -945,7 +925,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterNewRowCreated', {
       view,
       fields,
-      primary,
       values: {
         id: 2,
         order: '2.00000000000000000000',
@@ -971,7 +950,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterNewRowCreated', {
       view,
       fields,
-      primary,
       values: {
         id: 4,
         order: '4.00000000000000000000',
@@ -998,7 +976,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterNewRowCreated', {
       view,
       fields,
-      primary,
       values: {
         id: 13,
         order: '13.00000000000000000000',
@@ -1025,7 +1002,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterNewRowCreated', {
       view,
       fields,
-      primary,
       values: {
         id: 16,
         order: '16.00000000000000000000',
@@ -1059,7 +1035,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterNewRowCreated', {
       view,
       fields,
-      primary,
       values: {
         id: 17,
         order: '17.00000000000000000000',
@@ -1093,7 +1068,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterNewRowCreated', {
       view,
       fields,
-      primary,
       values: {
         id: 0,
         order: '0.00000000000000000000',
@@ -1137,13 +1111,14 @@ describe('Buffered rows view store helper', () => {
       ],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -1177,7 +1152,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterNewRowCreated', {
       view,
       fields,
-      primary,
       values: {
         id: 4,
         order: '4.00000000000000000000',
@@ -1206,13 +1180,14 @@ describe('Buffered rows view store helper', () => {
       filters: [],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -1252,7 +1227,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 5,
         order: '5.00000000000000000000',
@@ -1281,7 +1255,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 5,
         order: '5.00000000000000000000',
@@ -1308,7 +1281,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 5,
         order: '6.50000000000000000000',
@@ -1334,7 +1306,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 5,
         order: '7.50000000000000000000',
@@ -1374,13 +1345,14 @@ describe('Buffered rows view store helper', () => {
       ],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -1415,7 +1387,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 1,
         order: '1.00000000000000000000',
@@ -1443,7 +1414,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 4,
         order: '4.00000000000000000000',
@@ -1471,7 +1441,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 4,
         order: '4.00000000000000000000',
@@ -1498,7 +1467,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 15,
         order: '15.00000000000000000000',
@@ -1537,13 +1505,14 @@ describe('Buffered rows view store helper', () => {
         },
       ],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -1570,7 +1539,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 3,
         order: '3.00000000000000000000',
@@ -1589,7 +1557,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 3,
         order: '3.00000000000000000000',
@@ -1607,7 +1574,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 3,
         order: '3.00000000000000000000',
@@ -1625,7 +1591,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 3,
         order: '3.00000000000000000000',
@@ -1643,7 +1608,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 3,
         order: '3.00000000000000000000',
@@ -1661,7 +1625,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 3,
         order: '3.00000000000000000000',
@@ -1679,7 +1642,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 3,
         order: '3.00000000000000000000',
@@ -1710,13 +1672,14 @@ describe('Buffered rows view store helper', () => {
         },
       ],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -1747,7 +1710,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowUpdated', {
       view,
       fields,
-      primary,
       row: {
         id: 7,
         order: '7.00000000000000000000',
@@ -1776,13 +1738,14 @@ describe('Buffered rows view store helper', () => {
       filters: [],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -1817,7 +1780,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowDeleted', {
       view,
       fields,
-      primary,
       row: {
         id: 1,
         order: '1.00000000000000000000',
@@ -1840,7 +1802,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowDeleted', {
       view,
       fields,
-      primary,
       row: {
         id: 15,
         order: '15.00000000000000000000',
@@ -1861,7 +1822,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowDeleted', {
       view,
       fields,
-      primary,
       row: {
         id: 9,
         order: '9.00000000000000000000',
@@ -1881,7 +1841,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowDeleted', {
       view,
       fields,
-      primary,
       row: {
         id: 5,
         order: '5.00000000000000000000',
@@ -1900,7 +1859,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowDeleted', {
       view,
       fields,
-      primary,
       row: {
         id: 14,
         order: '14.00000000000000000000',
@@ -1932,13 +1890,14 @@ describe('Buffered rows view store helper', () => {
       ],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const populateRow = (row) => {
       row._ = {}
       return row
@@ -1973,7 +1932,6 @@ describe('Buffered rows view store helper', () => {
     await store.dispatch('test/afterExistingRowDeleted', {
       view,
       fields,
-      primary,
       row: {
         id: 100,
         order: '100.00000000000000000000',
@@ -2072,8 +2030,7 @@ describe('Buffered rows search', () => {
     store.registerModule(storeName, bufferedRowsModule)
 
     await store.dispatch(`${storeName}/refresh`, {
-      fields: [],
-      primary: createPrimaryField(),
+      fields: [createPrimaryField()],
     })
 
     const rowsInStore = store.getters[`${storeName}/getRows`]
@@ -2097,8 +2054,7 @@ describe('Buffered rows search', () => {
 
     await store.dispatch(`${storeName}/afterNewRowCreated`, {
       view,
-      fields: [],
-      primary: createPrimaryField(),
+      fields: [createPrimaryField()],
       values: newMatchingRow,
     })
 
@@ -2124,7 +2080,6 @@ describe('Buffered rows search', () => {
     await store.dispatch(`${storeName}/afterNewRowCreated`, {
       view,
       fields: [],
-      primary: createPrimaryField(),
       values: newNotMatchingRow,
     })
 
@@ -2152,8 +2107,7 @@ describe('Buffered rows search', () => {
 
     await store.dispatch(`${storeName}/afterExistingRowUpdated`, {
       view,
-      fields: [],
-      primary: createPrimaryField(),
+      fields: [createPrimaryField()],
       row: matchingRow,
       values: newValues,
     })
diff --git a/web-frontend/test/unit/database/store/view/grid.spec.js b/web-frontend/test/unit/database/store/view/grid.spec.js
index 5f2354e71..09f979810 100644
--- a/web-frontend/test/unit/database/store/view/grid.spec.js
+++ b/web-frontend/test/unit/database/store/view/grid.spec.js
@@ -110,13 +110,11 @@ describe('Grid view store', () => {
       sortings: [],
     }
     const fields = []
-    const primary = {}
     const getScrollTop = () => 0
 
     await store.dispatch('grid/createdNewRow', {
       view,
       fields,
-      primary,
       values: { id: 1, order: '1.00000000000000000000' },
       getScrollTop,
     })
@@ -129,7 +127,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/createdNewRow', {
       view,
       fields,
-      primary,
       values: { id: 8, order: '4.50000000000000000000' },
       getScrollTop,
     })
@@ -143,7 +140,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/createdNewRow', {
       view,
       fields,
-      primary,
       values: { id: 102, order: '102.00000000000000000000' },
       getScrollTop,
     })
@@ -166,7 +162,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/createdNewRow', {
       view,
       fields,
-      primary,
       values: { id: 2, order: '2.00000000000000000000' },
       getScrollTop,
     })
@@ -194,13 +189,14 @@ describe('Grid view store', () => {
         ],
         sortings: [],
       },
-      fields,
-      primary: {
-        id: 1,
-        name: 'Test 1',
-        type: 'text',
-        primary: true,
-      },
+      fields: [
+        {
+          id: 1,
+          name: 'Test 1',
+          type: 'text',
+          primary: true,
+        },
+      ],
       values: { id: 16, order: '11.50000000000000000000', field_1: 'value' },
       getScrollTop,
     })
@@ -250,19 +246,19 @@ describe('Grid view store', () => {
       ],
       sortings: [],
     }
-    const fields = []
-    const primary = {
-      id: 1,
-      name: 'Test 1',
-      type: 'text',
-      primary: true,
-    }
+    const fields = [
+      {
+        id: 1,
+        name: 'Test 1',
+        type: 'text',
+        primary: true,
+      },
+    ]
     const getScrollTop = () => 0
 
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 2, order: '2.00000000000000000000', field_1: 'Value 2' },
       values: { field_1: 'Value 2 updated' },
       getScrollTop,
@@ -282,7 +278,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 1, order: '1.00000000000000000000', field_1: 'Value 1' },
       values: { field_1: 'Value 1 updated' },
       getScrollTop,
@@ -301,7 +296,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 3, order: '3.00000000000000000000', field_1: 'Value 3' },
       values: { field_1: 'Value 3 updated' },
       getScrollTop,
@@ -320,7 +314,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 4, order: '4.00000000000000000000', field_1: 'empty' },
       values: { field_1: 'Value 4 updated' },
       getScrollTop,
@@ -341,7 +334,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 4,
         order: '4.00000000000000000000',
@@ -378,7 +370,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 10, order: '10.00000000000000000000', field_1: 'Value 10' },
       values: { field_1: 'Value 10 updated' },
       getScrollTop,
@@ -403,7 +394,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 15, order: '15.00000000000000000000', field_1: 'Value 15' },
       values: { field_1: 'Value 15 updated' },
       getScrollTop,
@@ -425,7 +415,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 12, order: '12.00000000000000000000', field_1: 'Value 12' },
       values: {
         order: '13.50000000000000000000',
@@ -451,7 +440,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 12,
         order: '13.50000000000000000000',
@@ -478,7 +466,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 13,
         order: '13.00000000000000000000',
@@ -502,7 +489,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 2,
         order: '2.00000000000000000000',
@@ -527,7 +513,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 2,
         order: '20.99999999999999999999',
@@ -565,7 +550,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 11,
         order: '14.99999999999999999996',
@@ -610,7 +594,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: {
         id: 11,
         order: '14.99999999999999999999',
@@ -673,13 +656,11 @@ describe('Grid view store', () => {
       sortings: [],
     }
     const fields = []
-    const primary = {}
     const getScrollTop = () => 0
 
     await store.dispatch('grid/deletedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 3, order: '3.00000000000000000000' },
       getScrollTop,
     })
@@ -697,7 +678,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/deletedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 20, order: '20.00000000000000000000' },
       getScrollTop,
     })
@@ -715,7 +695,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/deletedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 13, order: '13.00000000000000000000' },
       getScrollTop,
     })
@@ -747,13 +726,14 @@ describe('Grid view store', () => {
         ],
         sortings: [],
       },
-      fields,
-      primary: {
-        id: 1,
-        name: 'Test 1',
-        type: 'text',
-        primary: true,
-      },
+      fields: [
+        {
+          id: 1,
+          name: 'Test 1',
+          type: 'text',
+          primary: true,
+        },
+      ],
       row: { id: 16, order: '11.50000000000000000000', field_1: 'value' },
       getScrollTop,
     })
@@ -783,13 +763,11 @@ describe('Grid view store', () => {
       sortings: [],
     }
     const fields = []
-    const primary = {}
     const getScrollTop = () => 0
 
     await store.dispatch('grid/createdNewRow', {
       view,
       fields,
-      primary,
       values: { id: 1, order: '1.00000000000000000000' },
       metadata: { test: 'test' },
       getScrollTop,
@@ -801,7 +779,6 @@ describe('Grid view store', () => {
     await store.dispatch('grid/updatedExistingRow', {
       view,
       fields,
-      primary,
       row: { id: 1, order: '1.00000000000000000000' },
       values: { field_1: 'Value updated' },
       metadata: { test: 'test updated' },
diff --git a/web-frontend/test/unit/database/utils/field.spec.js b/web-frontend/test/unit/database/utils/field.spec.js
new file mode 100644
index 000000000..9bee173d0
--- /dev/null
+++ b/web-frontend/test/unit/database/utils/field.spec.js
@@ -0,0 +1,42 @@
+import { getPrimaryOrFirstField } from '@baserow/modules/database/utils/field'
+
+describe('test field utils', () => {
+  it('should find the primary field in a list of fields', () => {
+    const fields = [
+      {
+        name: 'id',
+        type: 'integer',
+        primary: true,
+      },
+      {
+        name: 'name',
+        type: 'string',
+        primary: false,
+      },
+    ]
+    const primaryField = getPrimaryOrFirstField(fields)
+    expect(primaryField).toEqual(fields[0])
+  })
+
+  it('should return the first field if no primary field is found', () => {
+    const fields = [
+      {
+        name: 'id',
+        type: 'integer',
+        primary: false,
+      },
+      {
+        name: 'name',
+        type: 'string',
+        primary: false,
+      },
+    ]
+    const primaryField = getPrimaryOrFirstField(fields)
+    expect(primaryField).toEqual(fields[0])
+  })
+
+  it('should return undefined if no fields are provided', () => {
+    const primaryField = getPrimaryOrFirstField([])
+    expect(primaryField).toBeUndefined()
+  })
+})
diff --git a/web-frontend/test/unit/database/viewFilters.spec.js b/web-frontend/test/unit/database/viewFilters.spec.js
index 624ae221f..b0aedd333 100644
--- a/web-frontend/test/unit/database/viewFilters.spec.js
+++ b/web-frontend/test/unit/database/viewFilters.spec.js
@@ -58,7 +58,6 @@ describe('View Filter Tests', () => {
     await store.dispatch('page/view/grid/fetchInitial', {
       gridId: 1,
       fields: [field],
-      primary: {},
     })
     await store.dispatch('view/fetchAll', { id: 1 })
   }
@@ -100,12 +99,13 @@ describe('View Filter Tests', () => {
   async function editFieldWithoutSavingNewValue(row, newValue) {
     await store.dispatch('page/view/grid/updateMatchFilters', {
       view: store.getters['view/first'],
-      fields: [],
-      primary: {
-        id: 1,
-        type: 'file',
-        primary: true,
-      },
+      fields: [
+        {
+          id: 1,
+          type: 'file',
+          primary: true,
+        },
+      ],
       row,
       overrides: {
         field_1: newValue,