Skip to content

How to wrap Ionic components for use as higher order components (HOC)? #109

Open
@ptmkenny

Description

@ptmkenny

I'm trying to make an Ionic Svelte app, coming from Ionic React.

In React, I wrapped the ion-button component like this:

export type CustomIonButtonWrapper = {
  children: StringOrElementOrNumber | StringOrElementOrNumber[];
  onClick?:
    | ((event: React.FormEvent) => void)
    | (() => Promise<void>)
    | (() => void);
  routerLink?: string;
  id?: string;
  color?: 'danger' | 'tertiary' | 'warning' | 'success';
  type?: 'submit';
  href?: string;
  className?: string;
  fill?: 'outline';
  disabled?: boolean;
  role?: 'button' | 'link';
};

const ButtonStandard: React.FC<CustomIonButtonWrapper> = (
  props: IonicButtonWrapper,
) => {
  const { children, ...otherProps } = props;
  return (
    <IonButton size="small" {...otherProps}>
      {children}
    </IonButton>
  );
};

Here, I restricted the number of props that can be provided to ion-button by adding the CustomIonButtonWrapper type, and then set the button size to small.

This allows me to use the <ButtonStandard> component to control the ion-button component, ensuring I only use the specified props throughout my app.

How can I do something similar in Svelte? Specifically,

  1. Wrap ion-button in a Svelte component
  2. Enforce a custom type for my ButtonStandard component (do not accept all the props that ion-button does).

I came up with the following but it seems verbose compared to React. Is there a better way?

<script lang="ts">
	export let onClick:
		| ((event: MouseEvent) => void)
		| (() => Promise<void>)
		| (() => void)
		| undefined = undefined;
	export let id: string | undefined = undefined;
	export let color: 'danger' | 'tertiary' | 'warning' | 'success' | undefined = undefined;
	export let type: 'submit' | undefined = undefined;
	export let href: string | undefined = undefined;
	export let className: string | undefined = undefined;
	export let fill: 'outline' | undefined = undefined;
	export let role: 'button' | 'link' | undefined = undefined;
	export let disabled: boolean = false;
</script>

{#if id}
	<ion-button
		size="small"
		on:click={onClick}
		{id}
		{color}
		{type}
		{href}
		class={className}
		{fill}
		{role}
		{disabled}
	>
		<slot />
	</ion-button>
{:else}
	<!-- 
    If id is set to undefined, then Svelte sets id to the string "undefined".
    So if id has not been set, then do not set id (to avoid setting it to the string "undefined").
   -->
	<ion-button
		size="small"
		on:click={onClick}
		{color}
		{type}
		{href}
		class={className}
		{fill}
		{role}
		{disabled}
	>
		<slot />
	</ion-button>
{/if}

Related to https://github.com/Tommertom/svelte-ionic-app/issues/93 and https://github.com/Tommertom/svelte-ionic-app/issues/88.

This is an issue because this project offers ion-button as a web component rather than a Svelte component. I imagine it would be a lot of work (and painful maintenance) to make Svelte components for all the Ionic components. So I'm wondering if there's another way to wrap the web components to use them as HOC without creating Svelte components?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions