Hi, I am trying to wrap blueprintjs to kotlinjs .....
# javascript
d
Hi, I am trying to wrap blueprintjs to kotlinjs ... @blueprintjs/core package works fine so far, but I got stuck on the select package. I used dukat to generate all the "wrapping" parts and now try to use the select component of blueprintjs following https://codesandbox.io/s/blueprint-sandbox-et9xy?file=/src/SelectExample.tsx
Copy code
public render() {
    const buttonText = this.state.film.title;
    return (
      <Example header="Select Sandbox">
        <FilmSelect
          items={Films.TOP_100_FILMS}
          itemPredicate={Films.filterFilm}
          itemRenderer={Films.renderFilm}
          noResults={<MenuItem disabled={true} text="No results." />}
          onItemSelect={this.handleValueChange}
        >
          <Button text={buttonText} rightIcon="caret-down" />
        </FilmSelect>
      </Example>
    );
  }
my try is:
Copy code
val FilmSelect = Select.ofType<Film>()

val exampleSelect = functionalComponent <SelectExampleProps> { props ->
        val (selectExampleState, setSelectExampleState) = useState(SelectExampleState(TOP_100_FILMS[0]))

        child(genericCard("Select Sandbox")) {
            child(FilmSelect::class) {
                attrs.items =  TOP_100_FILMS
                attrs.itemPredicate = filterFilm
                attrs.itemRenderer = renderFilm
                attrs.noResults = noResultsFunc
                attrs.onItemSelect = handleValueChange
                child(Button::class) {
                    attrs.text = selectExampleState.selectedFilm.title
                    attrs.rightIcon = "caret-down"
                }
            }
        }

    val handleValueChange = { film: Film, event: SyntheticEvent__1<HTMLElement> ->
        setSelectExampleState(SelectExampleState(film))
    }
}
so itemRenderer is
Copy code
typealias ItemRenderer<T> = (item: T, itemProps: IItemRendererProps) -> ReactElement?
how can I implement such a funtion returning a ReactElement but not being "in scope" ?? my try so far is:
Copy code
val renderFilm: ItemRenderer<Film> = { film: Film, itemProps: IItemRendererProps ->
    if (!itemProps.modifiers.matchesPredicate) {
        null;
    }
    val text = "${film.rank}. ${film.title}"
    child(MenuItem::class) {
        attrs.key = film.rank
        attrs.active = itemProps.modifiers.active
        attrs.disabled = itemProps.modifiers.disabled
        attrs.label = film.year.toString()
        attrs.onClick = itemProps.handleClick
        attrs.text = highlightText(text, itemProps.query)
    }
}

val filterFilm : ItemPredicate<Film> = { query: String, film: Film, index: Number, exactMatch: Boolean ->
    "${film.rank}. ${film.title.toLowerCase()} ${film.year}".indexOf(query.toLowerCase()) >= 0
}
but obviously the lambda has no `child(
MenuItem::class
)` method I can use ... how would I implement an ItemRenderer which returns the ReactElement ??
j
Hi, I think you're looking for the
buildElement
function, which takes a lambda that is run on a
RBuilder
receiver, so you can effectively build your element independently of a hierarchy.
d
how would I pass the RBuilder down to my function to use it?
j
You don't,
buildElement
does it for you:
Copy code
import react.buildElement

val elt = buildElement { // this: RBuilder
  // code can use RBuilder receiver here
}
This function is defined like this:
Copy code
inline fun buildElement(handler: RBuilder.() -> Unit): ReactElement =
    RBuilder().apply(handler)
        .childList.first()
        .unsafeCast<ReactElement>()
So you can see it creates the
RBuilder
on its own.
d
oh fu... ... it's you! (I left the same question in your seven wonders github repo as issue ...) Maybe slack is a better way to communicate than gthub issues ... I apologize again for any inconveniences 🙂
😄 1
j
Hey no problem at all, I also answered there 😉
In your specific case, I think you should be able to do this:
Copy code
val renderFilm: ItemRenderer<Film> = { film: Film, itemProps: IItemRendererProps ->
    if (!itemProps.modifiers.matchesPredicate) {
        null;
    }
    val text = "${film.rank}. ${film.title}"
    buildElement {
        child(MenuItem::class) {
            attrs.key = film.rank
            attrs.active = itemProps.modifiers.active
            attrs.disabled = itemProps.modifiers.disabled
            attrs.label = film.year.toString()
            attrs.onClick = itemProps.handleClick
            attrs.text = highlightText(text, itemProps.query)
        }
    }
}
d
on my way to try out ... I'll let you know 🙂
👍 1