How to pass a selected data to modal via props in VueJS using bootstrap Modal

Viewed 22

After hours of finding answers, i decided to write this because i couldn't find any solution. My problem is:

I have BookView.vue which is a parent component

<template>
    <div class="container">
        <div class="row">
            <book-details
            v-for="book in books" :key="book.id" :book="book"
            class="col-4 box"
            />
            
        </div>
        
    </div>
</template>

<script>
import BookDetails from "../components/BookDetails.vue";

import axios from "axios";

export default {
  components: { BookDetails },
  name: "book-view",
  data() {
    return {
      books: [],
    };
  },
  beforeCreate: function() {
    document.body.className = "book";
  },
  created() {
    axios
      .get(
        'https://www.googleapis.com/books/v1/volumes?q=inauthor:"Stephen+King"&key=AIzaSyBELf7aWJmgECK8XccZA6i8CnIT_rOxWVo'+'&maxResults=40'
      )
      .then((response) => {
        console.log(response.data.items)
        this.books = response.data.items;
      })
      .catch((e) => {
        this.errors.push(e);
      });
  },
  
};
</script>

<style>
.box {
  padding-top: 50px;
  
}
</style>

and a BookDetails.vue which is a child components

<template>
  <div class="container">
    <div class="card text-white bg-dark border-dark">
      <img
        class="card-img-top"
        :src="volumeInfo.imageLinks.thumbnail"
        alt="Card image cap"
      />
      <div class="card-body">
        <h2 class="card-title">{{ volumeInfo.title }}</h2>
        <span class="card-subtitle">{{ volumeInfo.subtitle }}</span>
        <div class="card-text">
          {{ volumeInfo.description }}
        </div>
      </div>
      <button
        @click="getBook(book)"
        type="button"
        class="btn btn-danger position-absolute"
        data-bs-toggle="modal"
        :data-bs-target="'#exampleModal-' + bookChosen.id"
      >
        Preview
      </button>
    </div>

  <modal-comp
  :bookChosen="bookChosen"
   />
   
  </div>
</template>

<script>
import ModalComp from './ModalComp.vue';
export default {
  components: { ModalComp },
  name: "book-details",
  data() {
    return {
      bookChosen: 
        {
          id: null,
          thumbnail: null,
          description: null,
          previewLink: null
        }
      
    }
  },
  props: {
    book: { type: Object, default: null },
  },
  computed: {
    volumeInfo() {
      // console.log(this.book.volumeInfo)
      return this.book.volumeInfo;
    },
    
  },
  methods: {
    getBook(bookdata) {
      console.log(bookdata)
      this.bookChosen.description = bookdata.volumeInfo.description
      this.bookChosen.thumbnail = bookdata.volumeInfo.imageLinks.thumbnail
      this.bookChosen.previewLink = bookdata.volumeInfo.previewLink
      this.bookChosen.id = bookdata.id
      console.log(this.bookChosen)
      console.log(this.bookChosen.description)
      console.log(this.bookChosen.previewLink)
    },
      
  },
};
</script>

<style>
.card {
  top: 0;
  transition: top ease 0.5s;
  text-align: left;
  overflow: hidden;
  max-height: 800px;
}
.card:hover {
  top: -50px;
}
</style>

I create bookChosen null data to receive specific data whenever i click an element, and props down to this ModalComp.vue

<template>
  <div class="container">
    <!-- Modal -->
    <div
      class="modal fade"
      :id="'exampleModal-' + bookChosen.id"
      aria-labelledby="exampleModalLabel"
      aria-hidden="true"
      tabindex="-1"
    >
      <div class="modal-dialog modal-dialog-scrollable">
        <div class="modal-content">
          <div class="modal-header">
            <img
              class="card-img-top"
              :src="bookChosen.thumbnail"
              alt="Card image cap"
            />
            <button
              type="button"
              class="btn-close"
              data-bs-dismiss="modal"
              aria-label="Close"
            ></button>
          </div>
          <div class="modal-body">
            {{ bookChosen.description }}
          </div>
          <div class="modal-footer">
            <a
              :href="bookChosen.previewLink"
              type="button"
              class="btn btn-primary"
              >Details</a
            >
            <button
              type="button"
              class="btn btn-secondary"
              data-bs-dismiss="modal"
            >
              Close
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "modal-comp",
  props: {
    bookChosen: { type: Object, default: null },
  },
  // watch: {
  //   displayed: function(newValue) {
  //     this.bookChosen = newValue
  //     console.log('new val', this.bookChosen)
  //   }
  // }
  
};
</script>

<style>
</style>

My problem is the modal only display either null or only the 1st element of books(if i decide to click it), after that its value do not change. I logged all the value of bookChosen and they're all good but Modal doesnt react at all.

I might find a solution because of this line:

 <button
        @click="getBook(book)"
        type="button"
        class="btn btn-danger position-absolute"
        data-bs-toggle="modal"
        **data-bs-target="#exampleModal"**
      >
        Preview
  </button>

which is only 1 modal with id=exampleModal is being rendered, so i change the modal id + with bookchosen id but didnt get too far.

One more thing is it might work if i use the normal @click event with v-if to toggle the modal? Thanks for helping

0 Answers
Related