Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Fetch data from API to inject data into Vue ref and use in html template

I’m new to the front end and just trying things out. I followed the tutorial and vue examples to create a simple web app. I want to populate the dropdown select box with data fetched from the backend now. But whatever I tried it just didn’t work and fails with TheSandbox.vue:18 Uncaught (in promise) TypeError: Cannot set properties of undefined (setting 'sendOptions'). Unfortunately, all the vue examples in the tutorial are for the static data set. What am I missing here? The code is below:

App.vue

<script setup>
import TheHeader from './components/TheHeader.vue'
import TheSandbox from './components/TheSandbox.vue';
</script>

<template>
  <header>
    <img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />

    <div class="wrapper">
      <TheHeader msg="You did it!" />
    </div>
  </header>

  <main>
    <TheSandbox />
  </main>
</template>

TheSandbox.vue

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

const sendAmount = ref('')
const sendSelected = ref('')
const sendOptions = ref([])

async function fetchItems() {
    return fetch('<MYURL>', {
        method: 'GET',
        headers: {
            "Content-Type": "application/json",
        },
    }).then(response => {
        console.log(response)

        response.json().then(data => {
            this.sendOptions = data.map(item => ({
                value: item.code, // actual value for the option
                text: item.name, // display text for the option
            }))

            console.log(data)
        });
    }).catch(err => {
        console.error(err);
    });
}

import { onMounted } from 'vue'
import { nextTick } from 'vue'

onMounted(async () => {
    // Fetch the data first
    await fetchItems();

    // Use await nextTick to wait until the DOM is updated
    await nextTick();

    // Now, you can interact with the DOM if necessary (e.g., selecting a default option)
    console.log('DOM updated and options are rendered');
})
</script>

<template>
    <div class="item">
        <div class="details">
            <h3>
                You send {{ sendAmount }} {{ sendSelected }}
            </h3>
            <input v-model="sendAmount" placeholder="0" />
            <select v-model="sendSelected">
                <option v-for="option in sendOptions" :key="option.value" :value="option.value">
                    {{ option.text }}
                </option>
            </select>
        </div>
    </div>
</template>

Thanks!

>Solution :

refer to sendOptions with sendOptions.value since it’s declared with ref:

sendOptions.value = data.map(item => ({
        value: item.code, // actual value for the option
         text: item.name, // display text for the option
      }))

this refers to the global scope (window) which doesn’t have the property sendOptions.

Try to restructure your code in this way :

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

const sendAmount = ref("");
const sendSelected = ref("");
const sendOptions = ref([]);

async function fetchItems() {
  try {
    const response = await fetch("<MYURL>", {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      },
    });

    const data = await response.json();
    sendOptions.value = data.map((item) => ({
      value: item.code, // actual value for the option
      text: item.name, // display text for the option
    }));

    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

onMounted(async () => {
  // Fetch the data first
  await fetchItems();

  // Use await nextTick to wait until the DOM is updated
  await nextTick();

  // Now, you can interact with the DOM if necessary (e.g., selecting a default option)
  console.log("DOM updated and options are rendered");
});
</script>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading