1

I want to have full control over the content of <input> element.

With React, I can do that like:

import { useState } from "react";

function Form() {
  const [value, setValue] = useState("");

  const onSubmit = (event) => {
    event.preventDefault();
    // Do something with `value`
  };

  const onChange = (event) => {
    const { value } = event.target;
    // For example, users can type only uppercase letters
    if (value === value.toUpperCase()) {
      setValue(value);
    }
  };

  return (
    <form onSubmit={onSubmit}>
      <input onChange={onChange} value={value} />
      <button type="submit">Submit</button>
    </form>
  );
}

export default Form;

In Vue, however, I cannot control <input> like:

<script setup>
import { ref } from "vue";

const value = ref("");

const onSubmit = () => {
  // Do something with `value`
};

const onInput = (event) => {
  // For example, users can type only uppercase letters
  if (event.target.value === event.target.value.toUpperCase()) {
    value.value = event.target.value;
  }
};
</script>

<template>
  <form v-on:submit.prevent="onSubmit">
    <input v-on:input="onInput" v-bind:value="value" />
    <button type="submit">Submit</button>
  </form>
</template>

It looks Vue doesn't control the <input> element's value attribute and Vue's value ref differs from value in DOM.

How can I do the same thing as React in Vue? Thank you in advance.

1
  • it's worth saying that vuejs documentation is excellent Commented Jul 23, 2022 at 17:07

1 Answer 1

2

If you want the input element content to be only updated on a specific condition.

One solution is on input event, you need to reset the input element value with the ref value, if the condition doesn't match.

Ex:

<script setup>
import { ref } from 'vue'

const inputValue = ref('')
const onSubmit = () => {
  console.log(inputValue.value)
  // Do something with `value`
}

const onInput = (event) => {
  // For example, users can type only uppercase letters
  const value = event.target.value
  if (value === value.toUpperCase()) {
    inputValue.value = value
  } else {
    event.target.value = inputValue.value
  }
}
</script>

<template>
  <form v-on:submit.prevent="onSubmit">
    <input @input="onInput" :value="inputValue" />
    <button type="submit">Submit</button>
  </form>
</template>

This is a live code example of what you are looking for.

https://stackblitz.com/edit/vue3-script-setup-with-vite-ze8fvb?file=src/App.vue

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

4 Comments

Thank you for answering. I know v-model does simple two-way data binding and it works well for most cases. In this case, however, I want to check what users have typed on <input>. The content in <input> should be updated, only when users have typed an acceptable input.
if you want more control, use :value and @input="fn" - then you have control in the function fn
I originally used v-bind and v-on combination as described in the question but failed to control what users can type in <input>. The string shown in <input> is updated as the user types even if value ref is not updated in the handler.
@tmsick, I just update the answer, with a live code example, please check and let me know if that is what you are looking for.

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.