Andy
Andy

Reputation: 2140

Vue3 Composition API - How to load default values from Ajax?

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?

Upvotes: 0

Views: 2217

Answers (1)

tony19
tony19

Reputation: 138326

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

Upvotes: 1

Related Questions