Skip to content

List-value binding: render multi-value cells as per-item markup #5

@tkuhn

Description

@tkuhn

Problem

Query results sometimes have fields that hold multiple values, typically as a single string of space-separated URIs (or a separator chosen by the query author via group_concat). For example, get-3pff-events returns Facilitators as one literal such as:

https://orcid.org/0009-0003-5409-652X https://orcid.org/0000-0003-1062-5576

Today the binding system in <nanopub-list>, <nanopub-table> (now also with <template> support via #3 / #4), and <nanopub-item> is strictly single-value: data-bind sets textContent, data-bind-[attr] sets one attribute, data-bind-html sets innerHTML. There's no way to say "render one <a> per token in this field" without the author either:

  1. reshaping the query to emit pre-built HTML (<a href=…>…</a>) and binding with data-bind-html — leaks presentation into the query and depends on DOMPurify sanitisation to keep working; or
  2. post-processing the DOM with a custom script — one-off hack per page.

Proposal

Add a list-iteration binding that clones a template fragment once per token in a field. Two reasonable shapes:

(a) Nested-template form — most expressive:

<td>
  <template data-bind-each="Facilitators" data-separator=" ">
    <a data-bind-href="." data-bind="."></a>
  </template>
</td>

data-bind-each="Field" on a <template> element iterates tokens of row[Field] split by data-separator (default a whitespace regex), clones the template content per token, and makes the current token available as "." to the existing data-bind* directives (so data-bind-href="." sets the href to the token and data-bind="." sets the text to the token). Other fields from the parent row remain accessible by name, allowing per-token markup to also reference row-level values.

(b) Shorthand form on a single element — cheaper but less flexible:

<td>
  <a data-bind-each-href="Facilitators" data-bind-each="Facilitators"></a>
</td>

…where the element is cloned per token and the -each-* bindings take the token as the value. This covers the common case (a flat list of links) without a nested template, but can't express richer per-token markup.

(a) subsumes (b), so (a) is probably the right target. (b) could be added as syntactic sugar later if demand exists.

Bonus

Pairs nicely with the ?things_multi_iri / ?things_label_multi convention on the query side (paired whitespace-separated URIs and newline-separated labels): data-bind-each could accept a sibling label field so that each cloned token exposes both its IRI and its human label to bindings, e.g.

<template data-bind-each="things_multi_iri" data-bind-each-label="things_label_multi">
  <a data-bind-href="." data-bind=".label"></a>
</template>

Workaround today

Variant queries that pre-emit HTML strings and bind via data-bind-html. Works (DOMPurify keeps it safe) but couples presentation to the query. Example of this workaround in the wild: https://w3id.org/np/RAGv30LZ_1y4y_yPpIjpheQiRAWlLFzYk2QuqQPOSN7ZQ (get-3pff-events-html), a variant of get-3pff-events where Organizers/Facilitators/More_Info are pre-rendered as comma-separated <a> strings.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions