Repository: directus/directus
File: app/src/interfaces/list-m2m/list-m2m.vue (Vue)

Code before:
			:disabled="disabled || (!updateAllowed && currentlyEditing !== null)"
			:collection="relationInfo.junctionCollection.collection"
			:primary-key="currentlyEditing || '+'"
			:related-primary-key="relatedPrimaryKey || '+'"
			:junction-field="relationInfo.junctionField.field"
			:edits="editsAtStart"
			:circular-field="relationInfo.reverseJunctionField.field"
			:junction-field-location="junctionFieldLocation"
			@input="stageEdits"
		/>

		<drawer-collection
			v-if="!disabled"
			v-model:active="selectModalActive"
			:collection="relationInfo.relatedCollection.collection"
			:filter="customFilter"
			multiple
			@input="select"
		/>

		<drawer-batch
			v-model:active="batchEditActive"
			:primary-keys="relatedPrimaryKeys"
			:collection="relationInfo.relatedCollection.collection"
			@refresh="batchRefresh"
		/>
	</div>
</template>

<style lang="scss">
.many-to-many {
	.bordered {
		.render-template {
			line-height: 1;
		}

		.no-last-border {
			tr.table-row:last-child td {
				border-bottom: none;
			}
		}

		tr.table-row {
			.append {
				position: sticky;
				right: 0;
				border-left: var(--theme--border-width) solid var(--theme--border-color-subdued);
			}
		}
	}
}

Review comment (performance):
The drawer-batch component will save the changes to the related items immediately, without staging them to the parent. This goes against how the rest of the app data handling works, where all changes are staged nested and only committed to the database on save of the root parent item. In order for this to work we should update the drawer batch component to return the changed values through an event on "save" instead of saving it to the API directly so this interface can set those changes like it would for 'single' nested updates 

Code after:
							>
								<v-icon name="launch" />
							</router-link>
							<v-icon
								v-if="!disabled && (deleteAllowed || isLocalItem(element))"
								v-tooltip="t(getDeselectTooltip(element))"
								class="deselect"
								:name="getDeselectIcon(element)"
								@click.stop="deleteItem(element)"
							/>
						</v-list-item>
					</template>
				</draggable>
			</template>

			<div class="actions" :class="layout">
				<template v-if="layout === LAYOUTS.TABLE">
					<template v-if="pageCount > 1">
						<v-pagination
							v-model="page"
							:length="pageCount"
							:total-visible="width.includes('half') ? 1 : 2"
							show-first-last
						/>

						<div class="spacer" />

						<div v-if="loading === false" class="per-page">
							<span>{{ t('per_page') }}</span>
							<v-select v-model="limit" :items="['10', '20', '30', '50', '100']" inline />
						</div>
					</template>
				</template>
				<template v-else>
					<v-button v-if="enableCreate && createAllowed" :disabled="disabled" @click="createItem">
						{{ t('create_new') }}
					</v-button>
					<v-button v-if="enableSelect && selectAllowed" :disabled="disabled" @click="selectModalActive = true">
						{{ t('add_existing') }}
					</v-button>
					<div class="spacer" />
					<v-pagination v-if="pageCount > 1" v-model="page" :length="pageCount" :total-visible="2" show-first-last />
				</template>
			</div>
		</div>

		<drawer-item
			v-model:active="editModalActive"
			:disabled="disabled || (!updateAllowed && currentlyEditing !== null)"
			:collection="relationInfo.junctionCollection.collection"
			:primary-key="currentlyEditing || '+'"