Stencil: renderer: how to render 3rd party widget/how to get node reference

Created on 7 Oct 2017  路  5Comments  路  Source: ionic-team/stencil

I'm submitting a ... (check one with "x")
[ ] bug report
[ ] feature request
[x] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or https://stencil-worldwide.slack.com

Current behavior:

stencil's implementation of VDom is not following Vdom "standards" for getting rendered node references via ref property.

Is this how stencil renderer should work or a missing feature?

If former, how should consumer get ref to VDom instance in which he wants to render 3rd party widget ?

Expected behavior:

Support ref + provide guide within docs

Related code:

// this doesn't work

render(){
  return <div ref={node => this.renderDatePicker(node)}>hello</div>
}
enhancement question

Most helpful comment

yeah having ref would mean having definitely less churn and imperative code, which is always a win win :)

All 5 comments

So I found a way how to do it via @Element() decorator which is IMHO too much churn and imperative code. Is this the recommended approach by stencil ?

TL;DR code:

class Datepicker {
  private flatpickr: flatpickr
  @Element() host: HTMLElement

 render() {
    return (
          <input is-datepicker />
    )
  }

   componentDidLoad() {
      const container = this.host.querySelector('[is-datepicker]') as HTMLInputElement
      this.flatpickr = new flatpickr(container, this.options)
    }
}

Whole example:

import { Component, Prop, Element, PropWillChange } from '@stencil/core'
import flatpickr from 'flatpickr'

export type Options = flatpickr.Options

@Component({
  tag: 'my-datepicker',
  styleUrl: 'my-datepicker.scss',
})
export class Datepicker {
  private static defaultOptions: flatpickr.Options = {
    wrap: false,
    mode: 'single',
    enableTime: false,
  }

  @Prop()
  options = {
    ...Datepicker.defaultOptions,
  } as flatpickr.Options
  @Element() host: HTMLElement

  private flatpickr: flatpickr

  @PropWillChange('options')
  handleOptionsChange(options: flatpickr.Options) {
    const newOptions = {
      ...Datepicker.defaultOptions,
      ...options,
    } as flatpickr.Options

    for (const setting of Object.keys(newOptions)) {
      this.flatpickr.set(setting, newOptions[setting])
    }
  }

  render() {
    return (
      <div>
        Flatpickr:
        <pre>{JSON.stringify(this.options, null, 2)}</pre>
        <div>
          <input is-datepicker />
        </div>
      </div>
    )
  }
  componentDidLoad() {
    const container = this.host.querySelector('[is-datepicker]') as HTMLInputElement
    this.flatpickr = new flatpickr(container, this.options)
  }
}

Thanks for opening an issue with us @Hotell ! The current recommended approach is to use our @Element decorator as your second example shows. Based on your feedback we can investigate the possibility of implementing a ref system. Ill leave this issue open for now.

yeah having ref would mean having definitely less churn and imperative code, which is always a win win :)

We've been trying not to add ref, but you have a good point and if JSX devs are familiar with this then we should probably add it. Thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

harshabonthu picture harshabonthu  路  3Comments

mitchellsimoens picture mitchellsimoens  路  3Comments

kensodemann picture kensodemann  路  3Comments

ryanmunger picture ryanmunger  路  3Comments

ckrack picture ckrack  路  3Comments