1

I'm looking to sanitise user input on the fly. Consider this Svelte REPL example where we attempt to remove all x's that the user types. If you type an "x", the sanitised version is the same as the original, so it doesn't update, but the "x" is still displayed in the input field. Once you type another character, there is a change, so the field is updated with the "x" removed. Compare this to this React sandbox where the state is always properly reflected.

How do I get React's behaviour in Svelte?

One could technically work around this issue by writing to value in the toy example (e.g. by having a two-way binding instead: bind:value={value}). That would cause Svelte to update value twice, first with the wrong value which then does trigger the invalidation code and then a second time with the right value. In the scenario I'm dealing with, I'm reading from an Observable which are read-only, so that hack is not an option. You can play around with such an example in this Svelte REPL.

2 Answers 2

1

You need to prevent the event's default behaviour:

<script>
  let value = 'test';

  function sanitize(e) {
    e.preventDefault();
    value = e.target.value = e.target.value.replace(/x/g, '');
  }
</script>

<input
  value={value}
  on:input={sanitize}
/>

Demo here.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer, Rich. I'm afraid that doesn't help. 1) the input event is not a cancelable event, so preventDefault does nothing here. (You might be confusing with keypress?) 2) The value = e.target.value part is what causes the invalidation here, which I explicitly stated I didn't want since I'm dealing with an Observable in my real case. Thank you though!
Did you try the linked REPL demo? I assure you the input event is cancelable! And if the problem you're trying to solve relates to an Observable, include that in the provided repro and code sample, otherwise I'm not sure how much help people are going to be able to give you.
Thank you for the feedback. I've updated the question. I hope it's more clear now. I did try the REPL demo. You can observe that the preventDefault here doesn't achieve its goal by removing the value = e.target.value from your example. I'm not sure if you were referring to something Svelte does on top of the normal event processing, but the normal input event in the web standards is most certainly not cancelable. (See MDN.) Thank you for thinking this through with me!
@RichHarris This works, but why isn't it enough to assign the sanitized input to the value variable? Is this a bug?
0

You can use beforeinput event:

<script>
    let value = 'test';

    function sanitize(e) {
        if (e.data.includes('x')) e.preventDefault();
    }
</script>

<input
    value={value}
    on:beforeinput={sanitize}
/>

Demo

You can actually use the same pattern for any input to get behavior like in react, here is the example of controlled input

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.