Frappe-ui Vue.js Saving DocType

Hi there

Can someone with more experience please give me an example of how to save my doc type after changes are made

let Book = createDocumentResource({
doctype: ‘Book’,
name: ‘1’,
})

I want to save Book and the child table chapters after I change chapters.chapter?

Any good examples for changing value and saving using frappe-ui

Hi @benjamen:

This should work.

try { 
    
    const newBookData= {
      title: "How to kill with pancakes",
      chapter: [
        { title: 'Introduction', pages: 183 },
        { title: 'Epilogue', pages: 15 },
      ],
    };
    await book.setValue.submit(newBookData);
    console.log('Updated test data:', newBookData);

  } catch (error) {
    console.error('Error updating test data:', error);
  }

Hope this helps.

3 Likes

Thank you. I will try :slight_smile:

1 Like

Hi @avc I got this working but very complex!

<template>
  <div class="p-5 bg-white shadow rounded-lg">
    <div v-if="chapter">
      <h1 class="font-black text-gray-900 text-3xl mb-6">
        Chapter: 
        <input
          v-model="chapter.name"
          class="border p-2 rounded w-full"
          placeholder="Enter chapter name"
        />
      </h1>
            <label class="block mb-2">Chapter Topic:</label>
      <Select
        v-model="chapter.topic"
        :options="topics"
        class="border p-2 rounded w-full mb-4"
      />

      <label class="block mb-2">Chapter Content:</label>
      <textarea
        v-model="chapter.chapter"
        class="w-full p-2 border rounded-md"
        placeholder="Enter chapter content"
      ></textarea>



      <button
        @click="saveChapter"
        class="bg-blue-500 text-white px-4 py-2 rounded"
      >
        Save
      </button>
    </div>
    <p v-else class="text-gray-500">Loading chapter data...</p>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { createDocumentResource, call } from 'frappe-ui';
import { Select } from 'frappe-ui';

const route = useRoute();
const bookName = route.params.bookName;
const chapterName = route.params.chapterName;

const bookResource = createDocumentResource({
  doctype: "Book",
  name: bookName,
  auto: true,
});

const bookDoc = computed(() => bookResource.doc);
const chapter = ref(null);
const topics = ref([]);

const fetchTopics = async () => {
  try {
    const response = await call('frappe.client.get_list', {
      doctype: 'Topic',
      fields: ['topic', 'name'],
    });
    topics.value = response.map(t => ({ label: t.topic, value: t.name }));
    console.log("Fetched topics:", topics.value);
  } catch (error) {
    console.error("Error loading topics:", error);
  }
};

const loadChapterData = async () => {
  await bookResource.reload();
  if (bookDoc.value && bookDoc.value.chapters) {
    const selectedChapter = bookDoc.value.chapters.find(ch => ch.name.toString() === chapterName);
    if (selectedChapter) {
      chapter.value = { ...selectedChapter };
      console.log("Loaded chapter:", chapter.value);
    } else {
      console.error(`Chapter "${chapterName}" not found in book "${bookName}"`);
    }
  }
};

const saveChapter = async () => {
  if (!chapter.value || !bookDoc.value) return;
  try {
    const updatedChapters = bookDoc.value.chapters.map(ch =>
      ch.name.toString() === chapterName ? { ...chapter.value } : ch
    );

    const updatedBookData = {
      ...bookDoc.value,
      chapters: updatedChapters,
    };

    console.log('Saving updated book data:', updatedBookData); // Added log for debugging

    await call('frappe.client.save', {
      doc: updatedBookData,
    });

    console.log('Chapter saved successfully!');
    await loadChapterData(); // Reload the data after saving
  } catch (error) {
    console.error('Error updating book data:', error);
  }
};

onMounted(async () => {
  await loadChapterData();
  await fetchTopics();
});
</script>

<style scoped>
/* Optional styles */
</style>
````Preformatted text`