0

I am new to Vue and am using the Bootstrap modals to display product information. I have grid containers that each have a product picture, description, and two buttons. One of the buttons(More details >>), when clicked, would shoot a modal window that should show the very same product description and picture of the grid it was contained in.

<div id="myapp">
  <h1> {{ allRecords() }} </h1>
  <div class="wrapper" >
    <div class="grid-container" v-for="product in products" v-bind:key="product.ID">
      <div class="Area-1">
        <img class="product_image" src="https:....single_product.jpg"> 
      </div>
      <div class="Area-2">
        <div class = "amount">
          {{ product.amount }}
        </div>
        {{ product.Description }}
      </div>
      <div class="Area-3">
        <b-button size="sm" v-b-modal="'myModal'" product_item = "'product'">
          More Details >>
        </b-button>
        <b-modal id="myModal" >
          <h1> {{ product.Name }} </h1>
          <h3> {{ product.Description }} </h3>
        </b-modal>
      </div>
      <div class="Area-4">
        <br><button>Buy</button>
      </div>
    </div>
  </div>
</div>
var app = new Vue({
  'el': '#myapp',
  data: {
    products: "",
    productID: 0
  },
  methods: {
    allRecords: function(){
      axios.get('ajaxfile.php')
        .then(function (response) {
          app.products = response.data;
        })
        .catch(function (error) {
          console.log(error);
        });
    },
  }
})

Area 1, 2 and 4 work perfectly fine and they display the product data according to the v-for value and as expected respectively for each grid container. Area 3 is a problem here when I click the More details >> button, I just see a faded black screen. I am not sure what I am doing wrong here, would really appreciate some help.

Hiws
  • 8,230
  • 1
  • 19
  • 36
AlyssaAlex
  • 696
  • 2
  • 9
  • 33

3 Answers3

1

Add a property selectedProduct, then on More Details button click event, assign the current product to the selectedProduct member as below :

HTML

  <div class="Area-3">
    <b-button size="sm" v-b-modal="'myModal'" 
             @click="selectProduct(product)">More Details >> </b-button>    
    <b-modal id="myModal">
             <h1> {{ this.selectedProduct.Name }} </h1>
             <h3> {{ this.selectedProduct.Description }} </h3>
    </b-modal>
  </div>

Javascript:

var app = new Vue({
 'el': '#myapp',
 data: {
    products: "",
    productID: 0,
    selectedProduct: {Name: '', Description: '', Amount:0}
 },
 methods: {
   allRecords: function(){
   ...
   },
   selectProduct: function(product)
   {
       this.selectedProduct = product;
   }
   ...
 }
Samidjo
  • 2,315
  • 30
  • 37
  • This is a fine alternative, however you would need to place the `b-modal` outside of the `v-for`. – Hiws Sep 18 '19 at 13:05
  • I did what @Hiws mentioned, but I get an error in the console: ```TypeError: Cannot read property 'Name' of undefined``` – AlyssaAlex Sep 18 '19 at 13:44
  • Thanks a lot! Your solution worked. The problem was that I had a lot of script srcs and imports, cleared them step by step, it works well now. – AlyssaAlex Sep 19 '19 at 08:50
1

The reason you're just seeing a black screen is because you're not giving the b-modal in your v-for a unique ID. So when you click the button it's actually opening all the modals at the same time, and stacking the backdrop making it look very dark.

Instead you could use your product ID (I'm guessing it's unique) in your modal ID to make it unique

<div id="myapp">
  <h1> {{ allRecords() }} </h1>
  <div class="wrapper" >
    <div class="grid-container" v-for="product in products" v-bind:key="product.ID">
      <div class="Area-1">
        <img class="product_image" src="https:....single_product.jpg"> 
      </div>
      <div class="Area-2"><div class = "amount">{{ product.amount }} </div>
        {{ product.Description }}
      </div>
      <div class="Area-3">
        <b-button size="sm" v-b-modal="`myModal-${product.ID}`" product_item = "'product'">
          More Details >> 
        </b-button>
        <b-modal :id="`myModal-${product.ID}`" >
          <h1> {{ product.Name }} </h1>
          <h3> {{ product.Description }} </h3>
        </b-modal>
      </div>
      <div class="Area-4">
        <br><button>Buy</button>
      </div>
    </div>
  </div>
</div>

Example pen: https://codepen.io/Hiws/pen/qBWJjOZ?editors=1010

Hiws
  • 8,230
  • 1
  • 19
  • 36
  • Hi! Thanks for your answer! The screen looks less dark and I can see the components behind, but no modal window with the content expected. :( – AlyssaAlex Sep 18 '19 at 13:18
  • @AlyssaAlex This issue might be related if the backdrop is showing in front. https://stackoverflow.com/questions/10636667/bootstrap-modal-appearing-under-background You could also try exploring the DOM after you've opened the window, to see if the modal is actually there. I added a codepen of the above example which is working – Hiws Sep 18 '19 at 13:48
1

I can't replicate the issue. I created JSFiddle to test:

https://jsfiddle.net/4289wh0e/1/

However, I realized multiple modal elements are displayed when I click on the "More Details" button.

I suggest you add only one modal in the wrapper and store the chosen product in a data variable.

https://jsfiddle.net/4289wh0e/2/

<div id="myapp">
    <h1> {{ allRecords() }} </h1>

    <div class="wrapper">

        <div class="grid-container" v-for="product in products" v-bind:key="product.ID">

            <div class="Area-1"><img class="product_image" src="https:....single_product.jpg"> </div>

            <div class="Area-2">
                <div class="amount">{{ product.amount }} </div>
                {{ product.Description }}</div>

            <div class="Area-3">
                <b-button size="sm" v-b-modal="'productModal'" @click="chooseProduct(product)" product_item="'product'">More Details >> </b-button>

            </div>

            <div class="Area-4">
                <br>
                <button>Buy</button>
            </div>
        </div>

        <b-modal id="productModal" v-if="chosenProduct">
            <h1> {{ chosenProduct.Name }} </h1>
            <h3> {{ chosenProduct.Description }} </h3>
        </b-modal>
    </div>
</div>
Vue.use(BootstrapVue)

var app = new Vue({
    'el': '#myapp',
    data: {
        products: [],
        chosenProduct: null
    },
    methods: {
            chooseProduct: function (product) {
            this.chosenProduct = product
        },
        allRecords: function(){
                    this.products = [
            {
                ID: 1,
                Description: 'dek',
              Name: 'Name',
              amount: 100
            },
            {
                ID: 2,
                Description: 'dek 2',
              Name: 'Name 2',
              amount: 300
            }
          ]
        },
    }
})