Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

junik91's avatar

Passing data form v-for loop to modal component

Hi guys ! In my project I have simple v-for loop iterrating over an array of objects:

new Vue({
    el: '#root',
    data: {
       items: [
           {itemName: 'item1', desc: 'blabla', itemPrice: '10'},
           {itemName: 'item2', desc: 'lala', itemPrice: '20'},
           {itemName: 'item3', desc:'aaaaa', itemPrice: '30'}
       ]
    }
});

and in my html code

<div>
    <li v-for="item in items">
        <span>{{item.name}}</span>
        <span>{{item.itemPrice}}</span>
        <span><button>ShowMore</button></span>
    </li>
</div>

As far as I uderstand I need to create a 'modal' component but how on earth pass the data of clicked item from v-for loop to show modal with all the data from my initial array ?

0 likes
11 replies
jimmy0699's avatar
<div>
    <li v-for="item in items">
    <modal :item='item'></modal>
    </li>
</div>

where modal is your component

of you can pass just a key and take all items from parent controller

like so:

<li v-for="(item, key) in items"></li>
junik91's avatar

@jimmy0699 Could you please explain to me this second solution ?

Another problem is that if I click on open modal button the all 3 modals are showing how to isolate this ?

junik91's avatar

Guys I have to ask is this proper solution ? it's working but I've got this feeling that it's not how I should do this... HTML:

<body>
    <div id="root">
        <item v-for="(item, key) in items" :key="item" :item="item">
        </item>
    </div>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script src="main.js"></script>
</body>

JS:

Vue.component('modal-details', {
    props: ['price', 'title', 'desc'],
    template: `
    
        <transition name="modal">
    <div class="modal-mask">
      <div class="modal-wrapper">
        <div class="modal-container">

          <div class="modal-header">
            {{title}}
          </div>

          <div class="modal-body">
            <slot name="body">
              {{desc}}
            </slot>
          </div>

          <div class="modal-footer">
            <slot name="footer">
              {{price}}
              <button class="modal-default-button" @click="$emit('close')">
                OK
              </button>
            </slot>
          </div>
        </div>
      </div>
    </div>
  </transition>
    
    `

});

Vue.component('item', {
    props: ['item'],
    data() {
        return {
            showModal: false,

            offers: [{
                    name: 'offer1'
                },
                {
                    name: 'offer2'
                },
                {
                    name: 'offer3'
                }
            ]

        }
    },
    template: `

        <div>
            <h1>{{item.itemName}}</h1>
            <h2>{{item.itemPrice}}</h2>
             <button id="show-modal" @click="showModal = true">Show Modal</button>
            <modal-details v-if="showModal" @close="showModal = false" :price="item.itemPrice" :title="item.itemName" :desc="item.desc"></modal-details>
            <offers v-for="offer in offers" :key="offer" :offer="offer"></offers>
        </div>
    
    `
});

Vue.component('offers', {
    props: ['offer'],
    data() {
        return {
            showModal: false,
        }
    },
    template: `
        
            
           <div>
                {{offer.name}}
                <button id="show-modal" @click="showModal = true">Show Modal</button>
                <modal-details v-if="showModal" @close="showModal = false" :title="offer.name"></modal-details>
           </div>
            
         
    `
});

new Vue({
    el: '#root',
    data: {
        showModal: false,
        items: [{
                itemName: 'item1',
                desc: 'blabla',
                itemPrice: '10'
            },
            {
                itemName: 'item2',
                desc: 'lala',
                itemPrice: '20'
            },
            {
                itemName: 'item3',
                desc: 'aaaaa',
                itemPrice: '30'
            }
        ]
    }
});
khanvuthy's avatar

@silverxjohn , should try with new update of vue.


methods: {
        itemClicked(item) {
            this.name = item.itemName;
          this.description = item.desc;
          this.price = item.itemPrice;
                    $("#my-modal").modal('show');
        }
    }
silverxjohn's avatar

@khanvuthy That's actually an ES5 syntax. You would need a 'compiler' like Babel to make it work across browsers. If the OP uses it, then he could use that syntax. But I don't think he is.

junik91's avatar

Guys, How to use bootstrap modal in my Vue app ? I have problem with mixing bootsrap's js and vue syntax ;/

silverxjohn's avatar

@junik91

You just need to import Bootstrap's css and js file in your <head>.

Then, for simplicity, just copy your modal template right after the <body> section of your html.

I personally make my master layout like this:

#master.blade.php

<html lang="en">
<head>
    <title>@yield('title')</title>

    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    @yield('modals')

    <div class="container">
        @yield('content')
    </div>

    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>

And whenever I extend the master

@extends('layouts.master')

@section('title', 'My Page')

@section('modals')
<!-- here's a modal snippet copied from http://getbootstrap.com/javascript/ -->

<div id="myModal" class="modal fade" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
        <h4 class="modal-title">Modal title</h4>
      </div>
      <div class="modal-body">
        <h1>Hooray!</h1>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
@endsection

@section('content')
<h1>Welcome to my Page!</h1>
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
  Launch demo modal
</button>
@endsection

You can programmatically open a modal

$("#myModal").modal('show');

So for example you have a button

@section('content')
<div id="app">
    <button @click="OnButtonClicked" class="btn btn-default">Click me!</button>
</div>
@endsection
var vm = new Vue({
    el: '#app',
    methods: {
        OnButtonClicked: function (e) {
            e.preventDefault();

            $("#myModal").modal('show');
        }
    }
});
rassem's avatar

Guys, I'm also looking that kind of situation, but from modal there is a button. And that is calling another method. with that method i have to pass a parameter. can you guys help me with that?

silverxjohn's avatar

@rassem can you explain your situation more precisely? If it is okay for you, you can create a new thread with the details of your question then reply me the link here.

Thanks

chrisgrim's avatar

I did it a simpler way, though probably more of a work around. I created a new data called modalDelete. Then when I press delete on the list item I pass the list item to that modalDelete data.

showModal(event) {
                this.modalDelete = event;
                this.isModalVisible = true;
            },

Then in my modal I just call the data modalDelete.

Please or to participate in this conversation.