0

Ninox 4 – Custom Component reading linked records makes the form jump on record change. Best practice?

Hi everyone,

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!

4 Antworten

null
    • Customer Support Ninox
    • uwe_groegor
    • vor 7 Stunden
    • Gemeldet - anzeigen

    Hallo  
    Als Hinweis:
    Das ist das deutsche Forum. Bitte erstelle deine Beiträge hier auf deutsch.
    Wenn du auf english schreiben willst, kannst du dafür das englische Forum nutzen.

    Zu deiner Anfrage:
    Ich habe deine Anforderung in einer BeispielApp auf einfache Art nachgebaut.
    Ich kann das von dir beschriebene Verhalten bei Linkfeldern bei 'benutzerdefinierten Komponenten' nicht als grundsätzlich nachvollziehen.
    Die 'benutzerdefinierte Komponente' löst ja die html-Funktion, welche in Ninox3 in Berechnungsfeldern genutzt wurde ab.
    In wieweit in 'benutzerdefinierten Komponenten' umfangreiches Scripting betrieben wird liegt ja bei dem Anwender selbst.
    Meine Tests haben ergeben, dass bei einfachen html-Script der Formularaufbau beim Wechsel zwischen Records grundsätzlich keine Verzögerung mit sich bringt.
    Der Inhalt des Feldes 'benutzerdefinierte Komponente' wird vollständig und sofort angezeigt.

    Ich füge ein Screenvideo bei, welches meinen Nachbau in einfacher Form zeigt und das Script, welches ich für die 'benutzerdefinierte Komponente' verwendet habe.

    Script verwendete 'benutzerdefinierte Komponente'

    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>
      • Rafael_Sanchis
      • vor 6 Stunden
      • Gemeldet - anzeigen

       

      Hello Uwe,

      Thank you very much for taking the time to recreate it and for the recording – very helpful.

      I agree with your result: with simple text fields from linked tables, the component renders immediately. I tested it again and the difference in my case came from two things your example doesn't include:

      1. Images: my header showed team logos with <img src="…"> using shareFile() URLs from the linked table. The browser loads the images after the component is drawn, and without fixed sizes the layout moved.

      2. Heavier scripting: several select … where queries and aggregations (leader, totals, form) on other tables inside the component.

      After simplifying the headers to text only (no images, values pre-calculated by a button and stored in fields), the form no longer jumps. So, as you say, it depends on how much scripting is put inside the component.

      Thanks also for the function Row(…) pattern and the bg-content1 / text-foreground classes – I'll use them to simplify my components.

       

      Best regards,

      Rafael

      • Rafael_Sanchis
      • vor 5 Stunden
      • Gemeldet - anzeigen

       

      Simple example

      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 items-center gap-6 p-4 rounded-lg bg-content1 text-foreground shadow"

      >

      <div style="width:56px;height:56px;flex-shrink:0">

      { if text(logo_link) != "" then

      <img src={ text(logo_link) } style="width:56px;height:56px;object-fit:contain"/>

      end }

      </div>

      <Row label="Company" value={ company }/>

      <Row label="Projects" value={ cnt(table_a) }/>

      <Row label="Cities" value={ join(unique(table_a.table_c.ort), ", ") }/>

      </div>

      The script en header Table B

      • Rafael_Sanchis
      • vor 4 Stunden
      • Gemeldet - anzeigen

      What I observed:

      - In Table C, the custom component header contains only text: the city name, the number of projects and the list of companies. These values are read through the reverse relation (cnt(table_a), unique(table_a.tableb.company)).

      - When switching records (for example, from Paris to Caracas), the header disappears for a moment and a loading spinner appears. The rest of the form moves up. Then the header renders and pushes the form down again.

      - The related-records subtable (Table A) also appears with a delay: first empty, then filled.

      - Table B shows the same behaviour, and its header also uses the reverse relation.

      So the shift happens even without images. My conclusion, which I'd like you to confirm, is:

      - Reading N:1 links "upwards" (tableb.company, tablec.ort), as in your example, renders immediately.

      - Reading 1:N reverse relations or using select inside the component makes the component wait until the related records are loaded. Because its space is not reserved in the meantime, the form shifts.

      Your example only uses N:1 links, which would explain why you didn't see the delay. I will add your exact script to Table A and record it next to the Table C header to compare both cases directly.

      Is this the expected behaviour for reverse relations? And is there a recommended way to avoid the shift, such as reserving the component height, or pre-calculating these values into fields of the record?

       

      Best regards,

      Rafael

Content aside

  • vor 4 StundenZuletzt aktiv
  • 4Antworten
  • 12Ansichten
  • 2 Folge bereits