svelte-formula icon indicating copy to clipboard operation
svelte-formula copied to clipboard

How would you use svelte-formula with "componized" input elements

Open maku opened this issue 3 years ago • 6 comments

Assuming that the input elements are abstracted into their own svelte components, how can you use the lib?

maku avatar Mar 11 '21 10:03 maku

@maku Good question - and maybe one I don't have an answer to yet?

When I was building this library I saw it more as something you would always use on top of HTML5 forms - so you would build your form, apply Formula - the form itself would be the component and use an event dispatcher to pass any data up to parent components.

If you have a component that's custom, it would have to adhere to some kind of API that matches an input - maybe it would work with bind:value and a custom validator passed to formula()

I just knocked together a quick demo - maybe something like this might work? https://svelte.dev/repl/57fbdfeebe8840ef86b0b855a40f86cf

tanepiper avatar Mar 11 '21 13:03 tanepiper

@tanepiper thank you for answering. I never use "pure" HTML5 forms. (maybe because I worked mainly in big Angular apps). But when I think about it, I realized that either you use a JS-Lib and integrate it into svelte or you use a CSS Lib like tailwind. In both ways you are rather forced to create your own components or use components already build from the lib.

For my use case, in a side project which is based on tailwind, every input component has a value property, which seems to be enough to work with formula (according to your example app)

Nonetheless, thank you for your work ...

maku avatar Mar 11 '21 13:03 maku

@maku Can you provide an example of a component you might use? Although that was the initial goal, I don't see why the library can't support custom components?

tanepiper avatar Mar 11 '21 16:03 tanepiper

@maku Outside of knowing your specific needs I've added some ability to do custom events https://formula.svelte.codes/docs/examples/custom-event

I also made an example with a third-party component and some hidden fields (which I've supported in 0.10.0) https://svelte.dev/repl/32d7417f604a49559464257dec35d6a4?version=3.31.2 - it's not idea and it still requires another field for now to trigger the change event (which I can fix in the next release)

tanepiper avatar Mar 12 '21 00:03 tanepiper

@tanepiper Here is a very simple example of wrapping a textfield of material components web (https://github.com/material-components/material-components-web/tree/master/packages/mdc-textfield).

I tried to use this component with formula and I had no problems with basic functionality. Of course there are many areas to address but I think it is rather manageable when you wrap a js lib yourself.

e.g.

<div use:form style="border: 1px solid silver; padding: 20px;">
  <UiInput name="name" label="Name" bind:value={customer.name} /> <br />

  <UiInput name="email" label="Email" bind:value={customer.email} />
</div>

UiInput.svelte

<script lang="ts">
  import { MDCTextField } from '@material/textfield';
  import { onDestroy, onMount } from 'svelte';

  let element: HTMLElement;
  export let value = '';
  export let label: string;
  export let name = '';

  let textField: MDCTextField;

  onMount(() => {
    textField = new MDCTextField(element);
  });

  onDestroy(() => {
    textField.destroy();
  });
</script>

<label bind:this={element} class="mdc-text-field mdc-text-field--outlined">
  <span class="mdc-notched-outline">
    <span class="mdc-notched-outline__leading" />
    <span class="mdc-notched-outline__notch">
      <span class="mdc-floating-label" id="{name}-label">{label}</span>
    </span>
    <span class="mdc-notched-outline__trailing" />
  </span>
  <input
    name={name}
    type="text"
    class="mdc-text-field__input"
    aria-labelledby="{name}-label"
    bind:value
  />
</label>

Probably it would be harder using a lib like https://github.com/hperrin/svelte-material-ui which provides the wrapping where you do not have the full control of the components...

maku avatar Mar 12 '21 08:03 maku

Thanks for building this plugin @tanepiper, really well designed API. I struggled for a while trying to figure out why I couldn't get my Formula form to detect values from https://github.com/rob-balfre/svelte-select.

  let selectValue = "";
  let hiddenSelectInput;

  function handleSelect(event) {
    selectValue = event.detail.value;
    hiddenSelectInput.dispatchEvent(new Event('customEvent'))
  }

  function clearSelect() {
    selectValue = "";
    hiddenSelectInput.dispatchEvent(new Event('customEvent'))
  }
<label for="primary-language" class="leading-7 text-sm text-gray-600">Primary Language</label>
<input type="text" id="primary-language" name="primaryLanguage" hidden=true bind:value={selectValue} bind:this={hiddenSelectInput} data-formula-bind='customEvent'/>
<Select {items} selectedValue={selectedValue.label} on:select={handleSelect} on:clear={clearSelect}></Select>

I figured out that there needed to be an input with a name attribute, but it wasn't obvious to me that the input needed to emit an event for Formula to detect changes. Would be great if the above setup wasn't necessary somehow.

benwoodward avatar Jun 13 '21 23:06 benwoodward