Search code examples
vue.jsvuejs3kentico-kontentkontent-ai

Kentico Kontent and Vue 3


I'm searching for a simple example on how to create a component in Vue 3 using data out of Kontent. More specifically, I'm trying to list items of a certain content type. I tried to refactor the Vue sample app that Kentico provided, but I'm quite new to programming and Vue and I can't seem to figure it out...

The following code gives an error saying Cannot read property 'name' of undefined:

<template v-for="(item, index) in eventsData" :key="index">
  <p>{{ item.name }}</p>
</template>

<script>
import { Client } from "../Client"; //seperated this, the connection works

export default {
  name: 'Test',
  setup() {
    const data = Client
    .items()
    .type("event")
    .toObservable()
    .subscribe(response => {
      console.log(response) //this works, data is displayed in the console
      return response.items;
    });

    return {data};
  },
  computed: { 
    eventsData: function() {
      return this.data.map(event => ({
        name: event.name
      }));
    }
  },
}
</script>

Edit2: Based on eyeslandic's hint I tried to improve my code, but I'm stuck again. The variables inside setup() are not accessable outside of it, so how do I get the outcome to data()?

This is what I have now:

<template>
  <div class="test-div">
    <template v-for="(item, index) in eventsData" :key="index">
      <p>{{item.name}}</p>
    </template>
  </div>
</template>

<script>
import { Client } from "../Client";

export default {
  name: 'Test',
  setup() {
    let events = [];

    const kontent = Client
    .items()
    .type("event")
    .toObservable()
    .subscribe(response => {
      console.log(response);//this works
      events = response.items;
      console.log("events inside kontent variable: " + events)//[object object][object object]
    });

    console.log("events outside kontent variable: " + events);//nothing
    console.log("kontent inside setup: " + kontent)//[object object]

    return {
      events,
      kontent
    };
  },  
  data() {
    return {
      eventList: events, //error: undefined,
      eventList2: kontent //error: undefined
    }
  },
  computed: {
    eventsData: function() {
      return this.eventList.map(event => ({
        name: event.name.value
      }));
    }
  }
}
</script>

Solution

  • events needs to be a ref or reactive for it to be reactive. Also, you could use the Composition API's computed to create a computed property from setup():

    <template>
      <p v-for="(name, index) in eventList" :key="index">
        {{ name }}
      </p>
    </template>
    
    <script>
    import { computed, reactive } from 'vue'
    
    export default {
      setup() {
        const events = ref([])
      
        Client.items()
          .type('event')
          .toObservable()
          .subscribe(response => events.value = response.items)
    
        return {
          eventList: computed(() => events.value.map(event => ({ name: event.name.value }))
        }
      }
    }
    </script>
    

    There's no need to return events or kontent from setup(), since they're not used anywhere in the template. I see your attempt at referencing kontent in data(), but eventList and eventList2 are also unused. The template you've shown could rely exclusively on setup() with the solution shown above.