Delay a DataSource until another is ready

Use the when prop to chain DataSources so one waits for another to finish loading before it fires.

When a dropdown needs data from two endpoints — users and departments — and the display label combines values from both, you must ensure the second DataSource doesn't fire until the first has resolved. Bind the second DataSource's when to the first's loaded property to create a sequential chain.

<App var.selectedId="" var.nonce="{0}">
  <DataSource
    id="users_for_ds_dependency"
    url="/api/users_for_ds_dependency?nonce"
    inProgressNotificationMessage="Loading users..."
    when="{ nonce > 0 }"
    />

  <DataSource
    id="departments_with_ds_dependency"
    url="/api/departments_with_ds_dependency"
    when="{ users_for_ds_dependency.loaded }"
    inProgressNotificationMessage="Loading departments..."
  />

  <Select
    id="usersForDsDepencency"
    data="{users_for_ds_dependency}"
    when="{departments_with_ds_dependency.loaded}"
    onDidChange="(newVal) => selectedId = newVal"
  >
    <Items data="{users_for_ds_dependency}">
      <Option
        value="{$item.id}"
        label="{$item.name} ({departments_with_ds_dependency.value
          .find(d => d.id === $item.departmentId)?.name})"
     />
    </Items>
  </Select>

  <Button label="Run" onClick="{nonce++}"/>
</App>
Load departments only after users are ready
<App var.selectedId="" var.nonce="{0}">
  <DataSource
    id="users_for_ds_dependency"
    url="/api/users_for_ds_dependency?nonce"
    inProgressNotificationMessage="Loading users..."
    when="{ nonce > 0 }"
    />

  <DataSource
    id="departments_with_ds_dependency"
    url="/api/departments_with_ds_dependency"
    when="{ users_for_ds_dependency.loaded }"
    inProgressNotificationMessage="Loading departments..."
  />

  <Select
    id="usersForDsDepencency"
    data="{users_for_ds_dependency}"
    when="{departments_with_ds_dependency.loaded}"
    onDidChange="(newVal) => selectedId = newVal"
  >
    <Items data="{users_for_ds_dependency}">
      <Option
        value="{$item.id}"
        label="{$item.name} ({departments_with_ds_dependency.value
          .find(d => d.id === $item.departmentId)?.name})"
     />
    </Items>
  </Select>

  <Button label="Run" onClick="{nonce++}"/>
</App>

Key points

when prevents the DataSource from fetching until the condition is truthy: In the example, when="{users_for_ds_dependency.loaded}" ensures the departments request doesn't fire until users have arrived.

You can chain multiple DataSources: DataSource A's when can reference DataSource B's loaded, and DataSource C can wait for both. This creates a sequential loading pipeline.

when on the DataSource is different from when on a UI element: On a DataSource, when suppresses the HTTP request entirely. On a Select or Fragment, when controls rendering but the request may have already fired.

inProgressNotificationMessage provides loading feedback per step: Assign a different message to each DataSource in the chain so users know which step is in progress.


See also