0

I have read everything I can find, but there is a confusing amount of variability between approaches. I want to use the "setup" form of the Vue3 composition API, which I believe is the recommended approach for future compatibility.

I have a form with elements like this:

<form @submit.prevent="update">
        <div class="grid grid-cols-1 gap-6 mt-4 sm:grid-cols-2">
          <div>
            <label class="text-gray-700" for="accountID">ID</label>
            <input disabled id="accountID" v-model="accountID"
                   class="bg-slate-100 cursor-not-allowed w-full mt-2 border-gray-200 rounded-md focus:border-indigo-600 focus:ring focus:ring-opacity-40 focus:ring-indigo-500"
                   type="text"
            />
          </div>

I want to load the current values with Ajax. If the user submits the form then I want to save the changed fields with a PATCH request.

I cannot work out how to change the form value with the result of the Ajax request and still maintain the binding.

Vue3 blocks changing the props directly (which makes sense), so the code below does not work:

<script setup lang="ts">    
import { ref, onMounted, computed } from "vue";
import axios from "axios";
import { useUserStore } from "@/stores/userStore";
const userStore = useUserStore();

const props = defineProps({
    accountID: String,
});

const emit = defineEmits(['update:accountID'])

const accountID = computed({
get() {
    return props.accountID;
},
set (value) {
    return emit('update:accountID')
},
})

onMounted(async () => {    
    let response = await axios.get("http://localhost:8010/accounts", { headers: { "Authorization": "Bearer " + userStore.jws } });    
    // This is a readonly variable and cannot be reassigned
    props.accountID = response.data.ID;    
});

function update() {
    console.log("Form submitted")
}
</script>

How can I set the form value with the result of the Ajax request?

1 Answer 1

1

Instead of trying to assign props.accountID, update the accountID computed prop, which updates the corresponding v-model:accountID via the computed setter. That v-model update is then reflected back to the component through the binding:

onMounted(async () => {
  let response = await axios.get(…)
  // props.accountID = response.data.ID ❌ cannot update readonly prop
  accountID.value = response.data.ID    ✅
})

Also note that your computed setter needs to emit the new value:

const accountID = computed({
  get() {
    return props.accountID
  },
  set(value) {
    // return emit('update:accountID')     ❌ missing value
    return emit('update:accountID', value) ✅
  },
})

demo

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

1 Comment

Thanks! This was amazingly helpful. I also forgot to use the binding when including the component like you do in App.vue - without that the elements still don't load

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.