diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.spec.ts b/frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.spec.ts
index e7274fbf1..70f8737fc 100644
--- a/frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.spec.ts
+++ b/frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.spec.ts
@@ -22,4 +22,76 @@ describe('DbTableRowViewComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ describe('getForeignKeyValue', () => {
+ const baseRow = {
+ foreignKeys: {
+ user_id: {
+ column_name: 'user_id',
+ constraint_name: 'fk_user',
+ referenced_column_name: 'id',
+ referenced_table_name: 'users',
+ },
+ },
+ };
+
+ it('returns null when record field is null', () => {
+ component.selectedRow = { ...baseRow, record: { user_id: null } } as any;
+ expect(component.getForeignKeyValue('user_id')).toBeNull();
+ });
+
+ it('returns null when record field is undefined', () => {
+ component.selectedRow = { ...baseRow, record: {} } as any;
+ expect(component.getForeignKeyValue('user_id')).toBeNull();
+ });
+
+ it('returns identity column value when FK object has one', () => {
+ component.selectedRow = {
+ ...baseRow,
+ record: { user_id: { id: 42, name: 'alice' } },
+ } as any;
+ expect(component.getForeignKeyValue('user_id')).toBe('alice');
+ });
+
+ it('returns primitive FK value as-is (including 0)', () => {
+ component.selectedRow = { ...baseRow, record: { user_id: 0 } } as any;
+ expect(component.getForeignKeyValue('user_id')).toBe(0);
+ });
+
+ it('returns primitive FK value as-is (including empty string)', () => {
+ component.selectedRow = { ...baseRow, record: { user_id: '' } } as any;
+ expect(component.getForeignKeyValue('user_id')).toBe('');
+ });
+ });
+
+ describe('getForeignKeyQueryParams', () => {
+ const baseRow = {
+ foreignKeys: {
+ user_id: {
+ column_name: 'user_id',
+ constraint_name: 'fk_user',
+ referenced_column_name: 'id',
+ referenced_table_name: 'users',
+ },
+ },
+ };
+
+ it('returns {} when record field is null', () => {
+ component.selectedRow = { ...baseRow, record: { user_id: null } } as any;
+ expect(component.getForeignKeyQueryParams('user_id')).toEqual({});
+ });
+
+ it('returns referenced column param when FK is an object', () => {
+ component.selectedRow = {
+ ...baseRow,
+ record: { user_id: { id: 42, name: 'alice' } },
+ } as any;
+ expect(component.getForeignKeyQueryParams('user_id')).toEqual({ id: 42 });
+ });
+
+ it('returns referenced column param when FK is a primitive', () => {
+ component.selectedRow = { ...baseRow, record: { user_id: 7 } } as any;
+ expect(component.getForeignKeyQueryParams('user_id')).toEqual({ id: 7 });
+ });
+ });
});
diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.ts b/frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.ts
index d89a69f08..50a96305c 100644
--- a/frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.ts
+++ b/frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.ts
@@ -257,33 +257,23 @@ export class DbTableRowViewComponent implements OnInit, OnDestroy {
}
getForeignKeyValue(field: string) {
- if (this.selectedRow && typeof this.selectedRow.record[field] === 'object') {
- const identityColumnName = Object.keys(this.selectedRow.record[field]).find(
- (key) => key !== this.selectedRow.foreignKeys[field].referenced_column_name,
- );
+ const cell = this.selectedRow?.record?.[field];
+ if (cell == null) return null;
+ if (typeof cell === 'object') {
const referencedColumnName = this.selectedRow.foreignKeys[field].referenced_column_name;
- if (identityColumnName) {
- return this.selectedRow.record[field][identityColumnName];
- }
- if (referencedColumnName) {
- return this.selectedRow.record[field][referencedColumnName];
- }
- return this.selectedRow.record[field] || '';
+ const identityColumnName = Object.keys(cell).find((key) => key !== referencedColumnName);
+ if (identityColumnName) return cell[identityColumnName];
+ if (referencedColumnName && cell[referencedColumnName] != null) return cell[referencedColumnName];
+ return null;
}
- return this.selectedRow.record[field] || '';
+ return cell;
}
getForeignKeyQueryParams(field: string) {
- if (this.selectedRow) {
- const referencedColumnName = this.selectedRow.foreignKeys[field]?.referenced_column_name;
-
- if (typeof this.selectedRow.record[field] === 'object') {
- return { [referencedColumnName]: this.selectedRow.record[field][referencedColumnName] };
- } else {
- return { [referencedColumnName]: this.selectedRow.record[field] };
- }
- }
- return {};
+ const cell = this.selectedRow?.record?.[field];
+ const referencedColumnName = this.selectedRow?.foreignKeys?.[field]?.referenced_column_name;
+ if (cell == null || !referencedColumnName) return {};
+ return { [referencedColumnName]: typeof cell === 'object' ? cell[referencedColumnName] : cell };
}
isWidget(columnName: string) {
diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.spec.ts b/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.spec.ts
index aadb22473..11fba7e69 100644
--- a/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.spec.ts
+++ b/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.spec.ts
@@ -241,4 +241,31 @@ describe('DbTableViewComponent', () => {
const value = component.getCellValue(foreignKey, cell);
expect(value).toEqual('John');
});
+
+ it('should return null (not throw) when foreign key cell is null', () => {
+ const foreignKey = {
+ autocomplete_columns: ['FirstName'],
+ column_name: 'CustomerId',
+ column_default: null,
+ constraint_name: 'Orders_ibfk_2',
+ referenced_column_name: 'Id',
+ referenced_table_name: 'Customers',
+ };
+
+ expect(component.getCellValue(foreignKey, null)).toBeNull();
+ expect(component.getCellValue(foreignKey, undefined)).toBeNull();
+ });
+
+ it('should not throw in isForeignKeySelected when record is null', () => {
+ const foreignKey = {
+ autocomplete_columns: ['FirstName'],
+ column_name: 'CustomerId',
+ column_default: null,
+ constraint_name: 'Orders_ibfk_2',
+ referenced_column_name: 'Id',
+ referenced_table_name: 'Customers',
+ };
+
+ expect(component.isForeignKeySelected(null, foreignKey)).toBe(false);
+ });
});
diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.ts b/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.ts
index d16e7399c..bad975c84 100644
--- a/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.ts
+++ b/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.ts
@@ -417,6 +417,7 @@ export class DbTableViewComponent implements OnInit, OnChanges {
}
getCellValue(foreignKey: TableForeignKey, cell) {
+ if (cell == null) return null;
const identityColumnName = Object.keys(cell).find((key) => key !== foreignKey.referenced_column_name);
if (identityColumnName) {
return cell[identityColumnName];
@@ -680,6 +681,7 @@ export class DbTableViewComponent implements OnInit, OnChanges {
}
isForeignKeySelected(record, foreignKey: TableForeignKey) {
+ if (record == null) return false;
const primaryKeyValue = record[foreignKey.referenced_column_name];
if (this.selectedRowType === 'foreignKey' && this.selectedRow && this.selectedRow.record !== null) {
diff --git a/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html b/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html
index 74a7e9cd0..52589d951 100644
--- a/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html
+++ b/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html
@@ -125,6 +125,7 @@
required: tableRowRequiredValues[value],
readonly: (!canEditRow() && pageAction !== 'dub') || pageMode === 'view',
disabled: isReadonlyField(value),
+ structure: tableRowStructure[value],
widgetStructure: tableWidgets[value],
relations: tableTypes[value] === 'foreign key' ? getRelations(value) : undefined,
rowPrimaryKey: keyAttributesFromURL
diff --git a/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.css b/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.css
index c015b0116..648d1b63f 100644
--- a/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.css
+++ b/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.css
@@ -52,3 +52,8 @@
margin-left: auto;
margin-top: 12px;
}
+
+.foreign-key__null-option {
+ font-style: italic;
+ color: var(--mat-sys-on-surface-variant, rgba(0, 0, 0, 0.6));
+}
diff --git a/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.html b/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.html
index 65519179d..9678159c9 100644
--- a/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.html
+++ b/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.html
@@ -1,5 +1,3 @@
-
-
{{normalizedLabel()}}
@@ -14,7 +12,7 @@
@for (suggestion of suggestions(); track suggestion.fieldValue) {
{{suggestion.displayString}}
@@ -24,19 +22,17 @@
here
-
-
- open_in_new
-
-
+ @if (currentFieldValue != null) {
+
+
+ open_in_new
+
+
+ }
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.spec.ts b/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.spec.ts
index 0277a802d..9b42774ba 100644
--- a/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.spec.ts
+++ b/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.spec.ts
@@ -438,4 +438,116 @@ describe('ForeignKeyEditComponent', () => {
},
]);
});
+
+ describe('nullable column', () => {
+ const nullableStructure = {
+ column_name: 'userId',
+ column_default: null,
+ data_type: 'integer',
+ isExcluded: false,
+ isSearched: false,
+ auto_increment: false,
+ allow_null: true,
+ character_maximum_length: null,
+ };
+
+ it('appends a "— empty" null option when structure.allow_null is true', async () => {
+ vi.spyOn(tablesService, 'fetchTable').mockReturnValue(of(usersTableNetwork));
+
+ component.connectionID = '12345678';
+ fixture.componentRef.setInput('value', '');
+ fixture.componentRef.setInput('structure', nullableStructure);
+
+ await component.ngOnInit();
+ fixture.detectChanges();
+
+ expect(component.allowsNull()).toBe(true);
+ const suggestions = component.suggestions();
+ expect(suggestions).toHaveLength(4);
+ expect(suggestions[suggestions.length - 1]).toEqual({
+ displayString: '— empty',
+ fieldValue: null,
+ isNullOption: true,
+ });
+ });
+
+ it('appends a null option when widget_params.allow_null is true', async () => {
+ vi.spyOn(tablesService, 'fetchTable').mockReturnValue(of(usersTableNetwork));
+
+ component.connectionID = '12345678';
+ fixture.componentRef.setInput('value', '');
+ fixture.componentRef.setInput('widgetStructure', {
+ field_name: 'userId',
+ widget_type: 'Foreign_key',
+ widget_params: { ...fakeRelations, allow_null: true },
+ name: '',
+ description: '',
+ });
+
+ await component.ngOnInit();
+ fixture.detectChanges();
+
+ expect(component.allowsNull()).toBe(true);
+ const suggestions = component.suggestions();
+ expect(suggestions[suggestions.length - 1].isNullOption).toBe(true);
+ });
+
+ it('does NOT append a null option when the column is not nullable', async () => {
+ vi.spyOn(tablesService, 'fetchTable').mockReturnValue(of(usersTableNetwork));
+
+ component.connectionID = '12345678';
+ fixture.componentRef.setInput('value', '');
+ fixture.componentRef.setInput('structure', { ...nullableStructure, allow_null: false });
+
+ await component.ngOnInit();
+ fixture.detectChanges();
+
+ expect(component.allowsNull()).toBe(false);
+ expect(component.suggestions().some((s) => s.isNullOption)).toBe(false);
+ });
+
+ it('keeps the null option present when search returns no rows', async () => {
+ fixture.componentRef.setInput('structure', nullableStructure);
+ component.connectionID = '12345678';
+
+ vi.spyOn(tablesService, 'fetchTable').mockReturnValue(of({ rows: [] }));
+ component.currentDisplayedString = 'nomatches';
+ await component.fetchSuggestions();
+
+ expect(component.suggestions()).toEqual([
+ { displayString: 'No field starts with "nomatches" in foreign entity.' },
+ { displayString: '— empty', fieldValue: null, isNullOption: true },
+ ]);
+ });
+
+ it('emits null and clears the related link when the null option is selected', () => {
+ const emitSpy = vi.spyOn(component.onFieldChange, 'emit');
+ component.suggestions.set([
+ { displayString: '— empty', fieldValue: null, isNullOption: true },
+ { displayString: 'Alex | Taylor', primaryKeys: { id: 33 }, fieldValue: 33 },
+ ]);
+ component.currentFieldQueryParams = { id: 33 };
+ component.currentFieldValue = 33;
+
+ component.updateRelatedLink({ option: { value: '— empty' } } as any);
+
+ expect(component.currentFieldValue).toBeNull();
+ expect(component.currentFieldQueryParams).toBeUndefined();
+ expect(emitSpy).toHaveBeenCalledWith(null);
+ });
+
+ it('fetchSuggestions emits null when the current display string matches the null option', async () => {
+ const emitSpy = vi.spyOn(component.onFieldChange, 'emit');
+ component.suggestions.set([
+ { displayString: '— empty', fieldValue: null, isNullOption: true },
+ { displayString: 'Alex | Taylor', primaryKeys: { id: 33 }, fieldValue: 33 },
+ ]);
+ component.currentDisplayedString = '— empty';
+
+ await component.fetchSuggestions();
+
+ expect(component.currentFieldValue).toBeNull();
+ expect(emitSpy).toHaveBeenCalledWith(null);
+ });
+ });
});
diff --git a/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.ts b/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.ts
index 0ba4e4d31..84b1ca9b3 100644
--- a/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.ts
+++ b/frontend/src/app/components/ui-components/record-edit-fields/foreign-key/foreign-key.component.ts
@@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
-import { Component, inject, model, signal } from '@angular/core';
+import { Component, computed, inject, model, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field';
@@ -24,8 +24,17 @@ interface Suggestion {
displayString: string;
primaryKeys?: Record;
fieldValue?: unknown;
+ isNullOption?: boolean;
}
+const NULL_OPTION_LABEL = '— empty';
+
+const nullSuggestion: Suggestion = {
+ displayString: NULL_OPTION_LABEL,
+ fieldValue: null,
+ isNullOption: true,
+};
+
@Component({
selector: 'app-edit-foreign-key',
templateUrl: './foreign-key.component.html',
@@ -59,6 +68,11 @@ export class ForeignKeyEditComponent extends BaseEditFieldComponent {
public fkRelations: TableForeignKey = null;
+ public allowsNull = computed(() => {
+ const ws = this.widgetStructure();
+ return !!ws?.widget_params?.allow_null || !!this.structure()?.allow_null;
+ });
+
private _debounceTimer: ReturnType;
async ngOnInit(): Promise {
@@ -121,25 +135,27 @@ export class ForeignKeyEditComponent extends BaseEditFieldComponent {
this.identityColumn = suggestionsRes.identity_column;
this.suggestions.set(
- suggestionsRes.rows.map((row) => {
- const modifiedRow = this.getModifiedRow(row);
- return {
- displayString: this.identityColumn
- ? `${row[this.identityColumn]} (${Object.values(modifiedRow)
- .filter((value) => value)
- .join(' | ')})`
- : Object.values(modifiedRow)
- .filter((value) => value)
- .join(' | '),
- primaryKeys: Object.assign(
- {},
- ...suggestionsRes.primaryColumns.map((primaeyKey) => ({
- [primaeyKey.column_name]: row[primaeyKey.column_name],
- })),
- ),
- fieldValue: row[this.fkRelations.referenced_column_name],
- };
- }),
+ this.withNullOption(
+ suggestionsRes.rows.map((row) => {
+ const modifiedRow = this.getModifiedRow(row);
+ return {
+ displayString: this.identityColumn
+ ? `${row[this.identityColumn]} (${Object.values(modifiedRow)
+ .filter((value) => value)
+ .join(' | ')})`
+ : Object.values(modifiedRow)
+ .filter((value) => value)
+ .join(' | '),
+ primaryKeys: Object.assign(
+ {},
+ ...suggestionsRes.primaryColumns.map((primaeyKey) => ({
+ [primaeyKey.column_name]: row[primaeyKey.column_name],
+ })),
+ ),
+ fieldValue: row[this.fkRelations.referenced_column_name],
+ };
+ }),
+ ),
);
this.fetching.set(false);
} catch (error) {
@@ -181,32 +197,36 @@ export class ForeignKeyEditComponent extends BaseEditFieldComponent {
this.identityColumn = res.identity_column;
if (res.rows.length === 0) {
- this.suggestions.set([
- {
- displayString: `No field starts with "${this.currentDisplayedString}" in foreign entity.`,
- },
- ]);
+ this.suggestions.set(
+ this.withNullOption([
+ {
+ displayString: `No field starts with "${this.currentDisplayedString}" in foreign entity.`,
+ },
+ ]),
+ );
} else {
this.suggestions.set(
- res.rows.map((row) => {
- const modifiedRow = this.getModifiedRow(row);
- return {
- displayString: this.identityColumn
- ? `${row[this.identityColumn]} (${Object.values(modifiedRow)
- .filter((value) => value)
- .join(' | ')})`
- : Object.values(modifiedRow)
- .filter((value) => value)
- .join(' | '),
- primaryKeys: Object.assign(
- {},
- ...res.primaryColumns.map((primaeyKey) => ({
- [primaeyKey.column_name]: row[primaeyKey.column_name],
- })),
- ),
- fieldValue: row[this.fkRelations.referenced_column_name],
- };
- }),
+ this.withNullOption(
+ res.rows.map((row) => {
+ const modifiedRow = this.getModifiedRow(row);
+ return {
+ displayString: this.identityColumn
+ ? `${row[this.identityColumn]} (${Object.values(modifiedRow)
+ .filter((value) => value)
+ .join(' | ')})`
+ : Object.values(modifiedRow)
+ .filter((value) => value)
+ .join(' | '),
+ primaryKeys: Object.assign(
+ {},
+ ...res.primaryColumns.map((primaeyKey) => ({
+ [primaeyKey.column_name]: row[primaeyKey.column_name],
+ })),
+ ),
+ fieldValue: row[this.fkRelations.referenced_column_name],
+ };
+ }),
+ ),
);
}
this.fetching.set(false);
@@ -239,8 +259,17 @@ export class ForeignKeyEditComponent extends BaseEditFieldComponent {
}
updateRelatedLink(e: MatAutocompleteSelectedEvent) {
- this.currentFieldQueryParams = this.suggestions().find(
- (suggestion) => suggestion.displayString === e.option.value,
- ).primaryKeys;
+ const selected = this.suggestions().find((suggestion) => suggestion.displayString === e.option.value);
+ if (selected?.isNullOption) {
+ this.currentFieldValue = null;
+ this.currentFieldQueryParams = undefined;
+ this.onFieldChange.emit(null);
+ return;
+ }
+ this.currentFieldQueryParams = selected?.primaryKeys;
+ }
+
+ private withNullOption(suggestions: Suggestion[]): Suggestion[] {
+ return this.allowsNull() ? [...suggestions, nullSuggestion] : suggestions;
}
}
diff --git a/frontend/src/app/components/ui-components/record-view-fields/foreign-key/foreign-key.component.html b/frontend/src/app/components/ui-components/record-view-fields/foreign-key/foreign-key.component.html
index a5b804a17..d9083c910 100644
--- a/frontend/src/app/components/ui-components/record-view-fields/foreign-key/foreign-key.component.html
+++ b/frontend/src/app/components/ui-components/record-view-fields/foreign-key/foreign-key.component.html
@@ -1,8 +1,12 @@
-
- {{displayValue()}}
- visibility
-
+@if (displayValue() == null) {
+ —
+} @else {
+
+ {{displayValue()}}
+ visibility
+
+}
diff --git a/frontend/src/app/components/ui-components/record-view-fields/foreign-key/foreign-key.component.spec.ts b/frontend/src/app/components/ui-components/record-view-fields/foreign-key/foreign-key.component.spec.ts
index ede913808..518b9ade1 100644
--- a/frontend/src/app/components/ui-components/record-view-fields/foreign-key/foreign-key.component.spec.ts
+++ b/frontend/src/app/components/ui-components/record-view-fields/foreign-key/foreign-key.component.spec.ts
@@ -27,4 +27,49 @@ describe('ForeignKeyRecordViewComponent', () => {
component.ngOnInit();
expect(component.foreignKeyURLParams).toEqual({ id: 1, mode: 'view' });
});
+
+ it('should render a dash when displayValue is null', () => {
+ fixture.componentRef.setInput('link', '/foo');
+ fixture.componentRef.setInput('primaryKeysParams', { id: 1 });
+ fixture.componentRef.setInput('displayValue', null);
+ fixture.detectChanges();
+
+ const anchor = fixture.nativeElement.querySelector('a.foreign-key-link');
+ const span = fixture.nativeElement.querySelector('span.field-view-value');
+ expect(anchor).toBeFalsy();
+ expect(span?.textContent?.trim()).toBe('—');
+ });
+
+ it('should render a dash when displayValue is undefined', () => {
+ fixture.componentRef.setInput('link', '/foo');
+ fixture.componentRef.setInput('primaryKeysParams', { id: 1 });
+ fixture.componentRef.setInput('displayValue', undefined);
+ fixture.detectChanges();
+
+ const anchor = fixture.nativeElement.querySelector('a.foreign-key-link');
+ const span = fixture.nativeElement.querySelector('span.field-view-value');
+ expect(anchor).toBeFalsy();
+ expect(span?.textContent?.trim()).toBe('—');
+ });
+
+ it('should render the link (not a dash) when displayValue is 0', () => {
+ fixture.componentRef.setInput('link', '/foo');
+ fixture.componentRef.setInput('primaryKeysParams', { id: 1 });
+ fixture.componentRef.setInput('displayValue', 0 as unknown as string);
+ fixture.detectChanges();
+
+ const anchor = fixture.nativeElement.querySelector('a.foreign-key-link');
+ expect(anchor).toBeTruthy();
+ expect(anchor.querySelector('span').textContent.trim()).toBe('0');
+ });
+
+ it('should render the link (not a dash) when displayValue is empty string', () => {
+ fixture.componentRef.setInput('link', '/foo');
+ fixture.componentRef.setInput('primaryKeysParams', { id: 1 });
+ fixture.componentRef.setInput('displayValue', '');
+ fixture.detectChanges();
+
+ const anchor = fixture.nativeElement.querySelector('a.foreign-key-link');
+ expect(anchor).toBeTruthy();
+ });
});
diff --git a/frontend/src/app/components/ui-components/table-display-fields/foreign-key/foreign-key.component.html b/frontend/src/app/components/ui-components/table-display-fields/foreign-key/foreign-key.component.html
index f44d3699a..66853cc22 100644
--- a/frontend/src/app/components/ui-components/table-display-fields/foreign-key/foreign-key.component.html
+++ b/frontend/src/app/components/ui-components/table-display-fields/foreign-key/foreign-key.component.html
@@ -1,6 +1,8 @@
- @if (relations() && value()) {
+ @if (value() == null) {
+ —
+ } @else if (relations()) {