How do I include custom references to items in a table?

Hi,

I am learning Typst (explains probable beginners mistakes below) and I am writing a template that includes writing tables of requirements.

I would like to be able to reference individual requirements, i.e., put a label on selected requirements and be able to reference them like
@req_ui implies ... => Req. 2 implies

I have tried with creating a custom kind (in a figure function call) as I understand Reference Function – Typst Documentation, but I can’t really get it to work with the table.

My question is then simply: What is the (best) way to achieve this functionality?

The table below is a minimal example similar to what I am aiming for:

#let req_counter = counter("req")
#req_counter.update(1)

#table(columns: (auto, auto, auto),
  align: (center, left, center),
  stroke: none,
  table.hline(stroke: 0.75pt, position: bottom),
  table.header([*No*], [*Requirement*], [*Priority*]),
    [#context req_counter.display() #req_counter.step()], 
     [A requirement on computational load], 
     [1],
    [#context req_counter.display() #req_counter.step()], 
     [A requirement on UI], 
     [2],
)

Best,
Erik

Edit:
I tried something like this (with a custom show rule)

#figure(kind: "req", supplement: "Req.", context req_counter.display())<b>
@b

and then the reference is OK but I can’t get this to work with the table of requirements.

With many tricks, it’s possible to achieve something that would be a reasonable way to do this. You had all the elements at hand!!

Basically:

  • You need figure elements to handle your numbering for you when referencing requirements
  • We are still using the req_counter, although I’d probably replace it with counter(figure.where(kind: "req")) if that causes issues (it probably wouldn’t)
  • “invisible” figures have the unfortunate side effect of adding a block, so we can just style them to only show an empty body

Putting all that together, we generate a label for each requirement (figure), and … that’s it!

#let req_counter = counter("req")
#req_counter.update(1)
#show figure.where(kind: "req"): it => it.body // remove block
#let Req(text, priority) = {
  let no = () => req_counter.display() + req_counter.step()
  let number = () => req_counter.get().at(0)
  let req() = figure(
    kind: "req",
    supplement: "Req.",
    numbering: "1.",
  )[]
  return (
    context [#no()#req()#label("req:" + str(number()))],
    text,
    priority,
  )
}

#table(
  columns: (auto, auto, auto),
  align: (center, left, center),
  stroke: none,
  table.hline(stroke: 0.75pt, position: bottom),
  table.header([*No*], [*Requirement*], [*Priority*]),
  ..Req([A requirement on computational load], [1]),
  ..Req([A requirement on UI], [2])
)

@req:1

@req:2
1 Like

This worked really well, thanks a lot!

1 Like

Slightly shortened:

#show figure.where(kind: "req"): it => it.body // remove block

#let req-counter = counter("req")
#req-counter.update(1)
#let Req(text, priority) = {
  let no() = req-counter.display() + req-counter.step()
  let number() = req-counter.get().first()
  let req() = figure(kind: "req", supplement: "Req.", numbering: "1.")[]
  (context [#no()#req()#label("req:" + str(number()))], text, priority)
}

#table(
  columns: 3,
  align: (center, left, center),
  stroke: none,
  table.hline(stroke: 0.75pt, position: bottom),
  table.header[*No*][*Requirement*][*Priority*],
  ..Req[A requirement on computational load][1],
  ..Req[A requirement on UI][2],
)

@req:1

@req:2

1 Like

Hi @Erik_Frisk, could you maybe try to revise your post’s title to be a complete question as per the question guidelines:

Good titles are questions you would ask your friend about Typst.

We hope by adhering to this, we make the information in this forum easy to find in the future.

Also, don’t forget to tick :ballot_box_with_check: one of the responses if you got a satisfying answer. The answer you choose should usually be the response that you found most correct/helpful/comprehensive for the question you asked. Thanks!

Sure!

I’ve ticked the solution that helped me.

I would be happy to revise the OP title, but I’m not sure where to click to edit.