SolidJSS
SolidJSโ€ข3y agoโ€ข
2 replies
lars

Manually mounting SolidJS component within HTML component via `render`

I'm on an adventure of doing some truly weird shit. I'm parsing YAML and dynamically creating HTML and inserting SolidJS components based on the template properties below:
group/main:
  template: |
    <div class="main">
      {{ widgets }}
    </div>
  widgets:
    - type: 'clock'
      template: |
        <div class="clock">
          {{ hours }}:{{ minutes }}
        </div>

(The user is the one who writes the YAML and runs the app, so it doesn't matter if it's insecure and dangerous)
How I'm getting this to work currently:
export function ClockWidget(props) {
  const [date, setDate] = createSignal(new Date());

  const minutes = createMemo(() => date().getMinutes());
  const hours = createMemo(() => date().getHours());
  const interval = setInterval(() => setDate(new Date()), 1000);

  // Create an `HTMLElement` from `props.template`.
  const element = getParsedTemplate();

  createEffect(
    on(
      () => [hours(), minutes()],
      // When the hours/minutes change, re-parse the template and mutate
      // the original HTMLElement in-place to match the new template. Maybe there's
      // some better way to do this?
      () => diffAndMutate(element, getParsedTemplate()),
    ),
  );

  function getParsedTemplate() {
    return parseTemplate(props.template, { // props.template is a string `<div class="clock">{{ hours }} ...`
      bindings: {
        strings: {
          hours: hours(),
          minutes: minutes(),
        },
      },
    });
  }

  return element; // This does not return JSX; it returns a regular `HTMLElement`.
}

export function Group(props) {
  // Create an `HTMLElement` from `props.template`.
  return parseTemplate(props.template, {
    bindings: {
      components: {
        // Hardcode clock widget to be the only widget for this example.
        widgets: () => (
          <ClockWidget template={props.widgets[0].template} />
        ),
      },
    },
  });
}
Was this page helpful?