Ninox 4 – Custom Component reading linked records makes the form jump on record change. Best practice?
Hi
I'd like to understand how Custom Components render in Ninox 4 when they read data from linked tables.
Generic setup:
- Table A has N:1 links to Table B and Table C.
- At the top of Table A's form there is a Custom Component (header) that displays values from the linked records, for example an image URL from B (linkB.image_url) and a name from C (linkC.name), together with some fields of the current record.
What happens:
When navigating between records in Table A (up/down arrows), the component disappears for a moment, the whole form shifts up, then the component renders without the linked data, and finally the linked values/images appear and the layout moves again. Using a fixed height on the component container and fixed-size placeholders for images did not prevent the shift.
Workaround that fixed it:
I added Text fields in Table A to store copies of the linked values, filled them with a script, and changed the component to read only fields of the current record. Now the form stays stable and only the images load in place.
Questions:
1. Is it expected that a Custom Component waits for linked records to load before rendering, without reserving its space?
2. Is copying linked values into local fields (denormalising) the recommended practice in Ninox 4, or is there a better approach, e.g. a setting, a loading placeholder, or a more efficient way to read linked records inside a component?
3. Is reading through a relation (e.g. linkB.field or a reverse relation) faster than using select … where inside a component, and does it affect rendering?
Thanks in advance for any insights!
3 replies
-
Hello
I have recreated your requirements in a simple example app.
I cannot confirm that the behavior you described regarding link fields in 'custom components' is a general issue.
'Custom components' are intended to replace the `html()` function that was used in calculation fields in Ninox 3.
The extent to which extensive scripting is implemented within 'custom components' is entirely up to the user.
My tests have shown that, when using simple HTML scripts, there is no noticeable delay in form rendering when switching between records.
The content of the 'custom component' field is displayed completely and immediately.I have attached a screen recording showing my simplified recreation, along with the script I used for the 'custom component'.
Script used for the 'custom component'
function Row(label: string, value: any) do <div class="flex flex-col"> <span class="text-xs text-default-500"> { label } </span> <span class="text-lg font-semibold"> { value } </span> </div> end; <div class="flex flex-col gap-3 p-4 rounded-lg bg-content1 text-foreground shadow"> <Row label="FieldTblA:" value={ name }/> <Row label="FieldTblB:" value={ tableb.company }/> <Row label="FieldTblC:" value={ tablec.ort }/> </div> -
I have now recreated it, including a logo.
I don’t see any major differences.
When displaying 1:n relationships, there is always a brief delay while all the data records load.
It remains to be seen how it performs with a very large number of records.
I cannot replicate the issue where elements shift during the form-loading process.
Based on my tests, the rendering of the 'custom component' also depends on how the logo is generated.
Using the `sharefile()` function within the script takes longer than using a pre-saved URL for the file.
In general, the presence of an image causes an initial time delay; however, this disappears on subsequent loads, presumably because the browser cache kicks in.Attached is the script for the 'custom component' used, along with a screen recording of the revised app.
'Cusom component' TblAfunction Row(label: string, value: any) do <div class="flex flex-col"> <span class="text-xs text-default-500"> { label } </span> <span class="text-lg font-semibold"> { value } </span> </div> end; <div class="flex flex-row items-center gap-4 p-4 rounded-lg bg-content1 text-foreground shadow" > <img src={ shareurl } alt="Bild" class="w-16 h-16 rounded-lg object-cover"/> <div class="flex flex-col gap-3"> <Row label="FieldTblA:" value={ name }/> <Row label="FieldTblB:" value={ tableb.company }/> <Row label="FieldTblC:" value={ tablec.ort }/> </div> </div>'Custom component' TblB
function Row(label: string, value: any) do <div class="flex flex-col"> <span class="text-xs text-default-500"> { label } </span> <span class="text-lg font-semibold"> { value } </span> </div> end; <div class="flex flex-row items-center gap-4 p-4 rounded-lg bg-content1 text-foreground shadow" > <img src={ shareurltblb } alt="Bild" class="w-16 h-16 rounded-lg object-cover"/> <div class="flex flex-col gap-3"> <Row label="FieldTblB:" value={ company }/> </div> </div>
Content aside
- 3 hrs agoLast active
- 3Replies
- 19Views
-
2
Following
