Halogen: How to pass in custom HTML into component

In Halogen, I have a table component. It receives basically an Array (Array Json) and then renders this into a, HTML table.

Now I want to have an (optional) custom column for “Actions” in each table row. An example would be “Delete this row”. My question is really simple: how do I pass the HTML for this custom column as an input?

My attempt looks like this:

type Input = { rows :: Array (Array Json), actionsColumn :: Maybe (forall w i. HTML w i)  }

render state = HH.table_ [ 
  HH.tr_ [ 
    maybe [] (\actions -> HH.td_ [ actions ]) state.actionsColumn 
    ] 
  ]

However, this gives me:

  Could not match type
      
    w1
      
  with type
      
    w0
      

while trying to match type HTML w1
  with type HTML w0

So it’s got something do to with the forall w i part. Which I basically guessed.

How do I do this properly? I’d love the “actions” column to contain buttons that then raise outputs so I can react to it in the parent component.

Not sure but I think this is another instance of a problem you can get with forall inside records - is it viable for you to move the forall w i outside the record?


I’ve seen something like this in a Reddit question a few days back. In the discussion @natefaubion pointed out this issue here: Typechecking failure with `$` (`apply`) and single-argument polymorphic functions as record fields · Issue #4140 · purescript/purescript · GitHub and it seems to be related here as well I think.

I don’t know much about Halogen, but try changing

type Input = { rows :: Array (Array Json), actionsColumn :: Maybe (forall w i. HTML w i)  }

to

type Input w i = { rows :: Array (Array Json), actionsColumn :: Maybe (HTML w i)  }

The difference between those is in the former, if you have a value of type Input, the compiler isn’t allowed to know anything about what type of HTML it contains. So when you say [ actions ], you’re creating an Array (forall w i. HTML w i) (as in each element is allowed to have whatever w and i it wants). With the latter, you have an Input w i and the w and i are “locked in” by the compiler. When you say [ actions ], then, it’s a forall w i. Array (HTML w i), which is what the td_ function expects.

1 Like

Maybe a little late to the party but I had the same challenge.

The problem was that the mkComponent needs render to return a:
HTML (ComponentSlot slots m i) i
The input is an array of:

HTML w i
This doesn’t work because, if it would, the caller of component can determine the w to be anything, while it has to be at least the ComponentSlot…

So changing the input array to

Array (HTML (ComponentSlot slots m i) i)
or the shorthand variant
(Array (H.ComponentHTML i slots m))

should fix your issue