VueJs select binding is not working - vuejs2

I have a categories component that looks like this:
<template>
<div>
<select v-model="categories">
<option v-for="category in categories" v-bind:value="category\.id">
{{category.name}}
</option>
</select>
</div>
</template>
<script>
export default {
data(){
return{
categories: []
}
},
created(){
this.showCategories();
},
methods: {
showCategories(){
axios.get('/app/categories').then(response => {
this.categories = response.data.categories;
});
}
}
}
</script>
I import this component inside my posts componen because I want to be able to choose a category when adding a new post, however, the categories for some reason do not show.
If it helps, my posts component looks like this:
<template>
<div class="container">
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Add Post</button>
<div class="form-group">
<input type="text" v-model="search" class="form-control" id="search">
</div>
<categories></categories>
<table class="table">
<thead class="thead-dark">
<tr>
<th>ID</th>
<th>Title</th>
<th>Body</th>
<th>Owner</th>
<th>Category</th>
<th>Created At</th>
<th>Updated At</th>
</tr>
</thead>
<tbody>
<tr v-for="post in filteredPosts">
<td>{{ post.id }}</td>
<td>{{ post.title }}</td>
<td>{{ post.body | snippet }}</td>
<td>{{ post.user.name }}</td>
<td>{{ post.category.name }}</td>
<td>{{ post.created_at }}</td>
<td>{{ post.updated_at }}</td>
<td><button class="btn btn-primary">Edit</button></td>
<td><button class="btn btn-danger">Delete</button></td>
</tr>
</tbody>
</table>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label>Title</label>
<input type="text" v-model="post.title" class="form-control">
</div>
<div class="form-group">
<label>Body</label>
<textarea v-model="post.body" class="form-control"></textarea>
</div>
</div>
<div class="modal-footer">
<button #click.prevent="addPost" type="button" class="btn btn-primary" data-dismiss="modal">Submit</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return{
posts: [],
post: {
title: "",
body: ""
},
search: ""
//categories: []
}
},
created(){
this.showPosts();
//this.showCategories();
},
methods: {
/*showCategories(){
axios.get('/app/categories').then(response => {
this.categories = response.data.categories;
});
},*/
showPosts(){
axios.get('/app/posts').then(response => {
this.posts = response.data.posts;
});
},
addPost(){
axios.post('/app/posts', {
title: this.post.title,
body: this.post.body,
})
.then(response => {
this.showPosts();
//console.log('Added');
})
.catch(function (error) {
console.log(error);
});
}
},
computed: {
filteredPosts: function(){
return this.posts.filter((post) => {
return post.title.match(this.search);
});
}
}
}
</script>
OBS: If I use an li tag like this inside the categories component I manage to see all the categories:
<li v-for="category in categories">{{category.name}}</li>
How can I show my categories inside the posts component using the select binding?

In your Select element you are binding v-model to array categories instead bind another variable selectedCategory in v-model like this
<select v-model="selectedCategory">
<option v-for="category in categories" v-bind:value="category.id">
{{category.name}}
</option>
</select>
<script>
export default {
data(){
return{
selectedCategory:null,
categories: []
}
},
created(){
this.showCategories();
},
methods: {
showCategories(){
axios.get('/app/categories').then(response => {
this.categories = response.data.categories;
});
}
}
}
</script>

Related

Props passed to child component do not render well

I am attempting to pass user id's fetched from an API trough props from parent (App) to child (Modal). The problem is that when I pass the props down to the modal they don't render as they should in the div with the modal-body class, in fact all of them display an id of 1.
App.vue:
<template>
<div class="container mt-3">
<table class="table">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Username</th>
</tr>
</thead>
<tbody v-for="user in users" :key="user.id">
<tr>
<th scope="row">{{ user.id }}</th>
<td>{{ user.name }}</td>
<td>{{ user.username }}</td>
<td>
<Modal :id="user.id" />
</td>
</tr>
</tbody>
</table>
</div>
<pre>{{ user }}</pre>
</template>
<script>
import axios from "axios";
import Modal from "#/components/Modal.vue";
export default {
name: "App",
components: {
Modal,
},
data() {
return {
users: null,
};
},
methods: {
async load_users() {
try {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/users"
);
this.users = data;
} catch (error) {
console.log("error");
}
},
},
mounted() {
this.load_users();
},
};
</script>
Modal.vue:
<template>
<!-- Button trigger modal -->
<button
type="button"
class="btn btn-danger"
data-bs-toggle="modal"
data-bs-target="#exampleModal"
>
Delete
</button>
<!-- Modal -->
<div
class="modal fade"
id="exampleModal"
tabindex="-1"
aria-labelledby="exampleModalLabel"
aria-hidden="true"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
Are you sure you want to delete user: {{ id }}
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Modal",
props: ["id"],
};
</script>
The page preview is the following:
It does not matter on which Delete button I click the id is always 1.
But when I inspect the props in the Vue Devtools they are different, for the second for example it appears 2 as it should:
Any help is appreciated.
Thank you.
You are rendering 10 modals each with the same id - exampleModal, so it's always the first one which is opened. This is why you are experiencing the behaviour you describe.
However - the real problem is with your structure.
Why are you rendering 10 modals? Why not render one and pass in the respective props?
Something like this:
<template>
<Modal v-if="modal.isActive" :id="modal.userId" />
<tbody v-for="user in users" :key="user.id">
<tr>
<th scope="row">{{ user.id }}</th>
<td>{{ user.name }}</td>
<td>{{ user.username }}</td>
<td>
<button
type="button"
class="btn btn-danger"
#click="onClick(user.id)"
>
Delete
</button>
</td>
</tr>
</tbody>
</template>
<script>
import Modal from '#/components/Modal.vue'
export default {
name: 'App',
components: {
Modal,
},
data() {
return {
users: null,
modal: {
isActive: false,
userId: null,
},
}
},
methods: {
onClick(userId) {
Object.assign(this.modal, { isActive: true, userId })
},
},
}
</script>

Vue shopping cart add to cart not working

I cannot see what i have done wrong, i am trying to add my products to my cart but i am not having any luck. How do i add to cart? i can figure out the delete and clear from understanding how to add to cart. i have read through some documentation and managed to get this far but now i am stuck.
i am not sure if i am targeting wrong or i have named something wrong. I used a normal array and it worked alright but i am trying to do it with an api now, does this change the methods?
<section>
<div class ="container" >
<div id="app" >
<div class="row">
<div class="col-md-12" >
<div class="card">
<div class="card-body">
<!-- Cart -->
<table>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
<tr v-for="(product, index) in cart">
<td>{{ item.productName }}</td>
<td>{{ item.price }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price * item.quantity }} Coins</td>
</tr>
</table>
</div>
</div>
<!-- Shop -->
<div class="row">
<div class="col-md-3" v-for="product in products" :key="product.id" >
<div class="card" >
<div class="card-body">
<div class="product">
<img :src="product.productImage" alt="Product Img">
<h4 class="text-info">{{ product.productName }}</h4>
<h4 class="text-muted">{{ product.price }} Coins</h4>
<p class="text-muted">{{ product.productDescription }}</p>
<input type="number" name="quantity" class="form-control" value="1">
<input type="hidden" name="productName" value="{{productID}}">
<input type="hidden" name="price" value="{{productID.price}}">
<input type="submit" name="add_to_cart" #click="addToCart" class="btn btn-primary btn-block fa-lg gradient-custom-2 mb-3" value="Add to Cart">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
var app = new Vue({
el: '#app',
data: {
products: '',
cart: []
},
methods: {
getproducts: function () {
axios.get('http://localhost:8888/DevsDev2022/productAPI/products')
.then(function (response) {
app.products = response.data;
})
.catch(function (error) {
console.log(error);
});
},
addToCart: function (product) {
var cartItem = this.cart.find(item => item.productName === product.productName);
if (cartItem) {
cartItem.quantity++;
} else {
this.cart.push({
productName: product.productName,
price: product.price,
quantity: 1
});
}
},
removeFromCart: function (product) {
var cartItem = this.cart.find(item => item.productName === product.productName);
if (cartItem.quantity > 1) {
cartItem.quantity--;
} else {
this.cart.splice(this.cart.indexOf(cartItem), 1);
}
},
clearCart: function () {
this.cart = [];
}
},
mounted: function () {
this.getproducts();
}
});
</script>
You are missing your template tag around your template
Please take a look at following snippet:
new Vue({
el: '#app',
data() {
return {
products: [{id: 1, productName: 'aaa', price: 25, productDescription: 'rrrrrrr'}, {id: 2, productName: 'bbb', price: 35, productDescription: 'eeeee'}],
cart: []
}
},
methods: {
getproducts() {
/*axios.get('http://localhost:8888/DevsDev2022/productAPI/products')
.then(function (response) {
app.products = response.data;
})
.catch(function (error) {
console.log(error);
});*/
},
addToCart(product) {
var cartItem = this.cart.find(item => item.productName === product.productName);
if (cartItem) {
cartItem.quantity++;
} else {
this.cart.push({
productName: product.productName,
price: product.price,
quantity: 1
});
}
},
removeFromCart(product) {
var cartItem = this.cart.find(item => item.productName === product.productName);
if (cartItem.quantity > 1) {
cartItem.quantity--;
} else {
this.cart.splice(this.cart.indexOf(cartItem), 1);
}
},
clearCart() {
this.cart = [];
}
},
mounted: function () {
this.getproducts();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<section>
<div class ="container" >
<div class="row">
<div class="col-md-12" >
<div class="card">
<div class="card-body">
<!-- Cart -->
<table>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
<tr v-for="(product, index) in cart">
<td>{{ product.productName }}</td>
<td>{{ product.price }}</td>
<td>{{ product.quantity }}</td>
<td>{{ product.price * product.quantity }} Coins</td>
</tr>
</table>
</div>
</div>
<!-- Shop -->
<div class="row">
<div class="col-md-3" v-for="product in products" :key="product.id" >
<div class="card" >
<div class="card-body">
<div class="product">
<img :src="product.productImage" alt="Product Img">
<h4 class="text-info">{{ product.productName }}</h4>
<h4 class="text-muted">{{ product.price }} Coins</h4>
<p class="text-muted">{{ product.productDescription }}</p>
<input type="number" name="quantity" class="form-control" value="1">
<input type="hidden" name="productName" :value="product.name">
<input type="hidden" name="price" :value="product.price">
<input type="submit" name="add_to_cart" #click="addToCart(product)" class="btn btn-primary btn-block fa-lg gradient-custom-2 mb-3" value="Add to Cart">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>

ERROR 422 when update data inside modal with axios.put [laravel + vuejs 3]

I am using Laravel + VueJS 3 to build a small project,
I use axios.put method for update details for single user in a table row via a modal, but I have problems when I click on submit button of a form inside a modal with axios.put, even I filled all data for all inputs but It still said the errors below, can you guys show me how can I fix this please?
Thanks!
ERROR
My backend:
public function updateUser(Request $req, User $user)
{
$req->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email,' . $user->id,
'password' => 'same:confirmPassword|max:64',
'roles' => 'required',
]);
$input = $req->all();
if (!empty($input['password'])) {
$input['password'] = Hash::make($input['password']);
} else {
$input = Arr::except($input, 'password');
}
$user->update($input);
$user->syncRoles($input['roles']);
return $this->sendResponse($user, 'Updated!');
}
My JS Code:
import axios from "axios";
let API_URL = "http://localhost:8000";
export default {
name: "manageUsers",
components: {},
data() {
return {
users: [],
userInfo: {
id: 0,
name: "",
username: "",
phone: "",
email: "",
password: "",
},
};
},
methods: {
refreshUsers() {
axios.get(`${API_URL}/api/users/allusers`).then((res) => {
this.users = res.data.data;
});
},
getUserInfo(user) {
axios
.get(`${API_URL}/api/users/show/` + user.id)
.then((res) => {
this.userInfo.id = res.data.data.id;
this.userInfo.name = res.data.data.name;
this.userInfo.email = res.data.data.email;
this.userInfo.username = res.data.data.username;
this.userInfo.phone = res.data.data.phone;
})
.catch((error) => {
console.log("ERRRR:: ", error.response.data);
});
},
updateUser() {
axios
.put(`${API_URL}/api/users/update/${this.userInfo.id}`)
.then((res) => {
this.refreshUsers();
alert(res.data);
})
.catch((error) => {
console.log("ERRRR:: ", error.response.data);
});
},
},
mounted() {
this.refreshUsers();
},
};
My VueJS template code:
<template>
<table class="table table-striped" id="datatable">
<tbody>
<tr v-for="(user, id) in users" :key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.username }}</td>
<td class="text-right">
<button
class="btn btn-link btn-warning btn-icon btn-sm"
data-toggle="modal" data-target="#userEditModal"
#click="getUserInfo(user)">
<i class="tim-icons icon-pencil"></i>
</button>
</td>
</tr>
</tbody>
</table>
<!-- EDIT USER MODAL -->
<div class="modal modal-black fade" id="userEditModal" tabindex="-1" role="dialog"
aria-labelledby="userEditModal" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="userEditModal">
Edit user <strong class="text-primary">{{ userInfo.username }}</strong>
</h4>
<button type="button" class="close"
data-dismiss="modal" aria-hidden="true">
<i class="tim-icons icon-simple-remove"></i>
</button>
</div>
<form class="form-horizontal">
<div class="modal-body">
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Username</label>
<div class="col-md-9">
<div class="form-group">
<input type="text" class="form-control" name="username"
v-model="userInfo.username" />
</div>
</div>
</div>
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Name</label>
<div class="col-md-9">
<div class="form-group">
<input type="text" class="form-control" name="name"
v-model="userInfo.name" />
</div>
</div>
</div>
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Email</label>
<div class="col-md-9">
<div class="form-group">
<input type="email" name="email" class="form-control"
v-model="userInfo.email" />
</div>
</div>
</div>
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Roles</label>
<div class="col-md-9">
<div class="form-group">
<input type="roles" name="roles" class="form-control"
v-model="userInfo.roles" />
</div>
</div>
</div>
</div>
<div class="modal-footer d-flex flex-row">
<button type="button" class="btn btn-secondary" data-dismiss="modal">
Close
</button>
<button type="submit" class="btn btn-primary" data-dismiss="modal"
#click="updateUser()">
Save changes
</button>
</div>
</form>
</div>
</div>
</div>
<!-- END EDIT USER MODAL -->
</template>```
I think you're not passing any parameters to your put call. axios docs
example:
axios.put('https://httpbin.org/put', { hello: 'world' });
When an issue like this arises you can always check your network tab in your browser. to see what data is send to your server.

How to insert data form into table when press a button in Vuex?

I have two components called Form.vue and Table.vue
I want the data to be transferred to the table when the user fills out the form and clicks the submit button.
I know I made a mistake in the code.
I have very little experience in vue.
Please Help me.
You can see the code from this link:
https://codesandbox.io/s/condescending-matsumoto-w7fui
Here is a working code https://codesandbox.io/embed/naughty-chatterjee-6susb?fontsize=14&hidenavigation=1&theme=dark
First things first, you MUST use mutations to modify state values. second is that you may use data method in storing form values before submitting them.
Ive modified your store like this
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
tableData: []
},
mutations: {
addUser(state, payload) {
console.log(state);
state.tableData = state.tableData.concat(payload.data);
}
},
actions: {
addUser({ commit }, payload) {
commit("addUser", payload);
}
}
});
and in you Form, you must dispatch the addUser action once the form is submitted...
<template>
<div>
<form action>
<div class="form-group">
<label for="name">نام محصول:</label>
<input type="text" class="form-control" id="name" placeholder name="name" v-model="name">
</div>
<div class="form-group">
<label for="grouping">دسته بندی:</label>
<input
type="text"
class="form-control"
id="grouping"
placeholder
name="group"
v-model="category"
>
</div>
<div class="form-group">
<label class="code">کد محصول:</label>
<input type="text" class="form-control" id="coding" placeholder name="code" v-model="code">
</div>
<div class="form-group">
<label for="price">قیمت محصول</label>
<input
type="text"
class="form-control"
id="pricing"
placeholder
name="price"
v-model="price"
>
</div>
<!-- <button type="button" class="btn btn-success send" #click="updateName, updateCategory, updateCode, updatePrice, $store.state.show = true, send">ثبت اطلاعات</button>-->
<button type="button" class="btn btn-success send" #click.prevent="addUser">ثبت اطلاعات</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
name: "",
category: "",
code: "",
price: ""
};
},
methods: {
addUser() {
this.$store.dispatch("addUser", {
data: {
name: this.name,
category: this.category,
code: this.code,
price: this.price
}
});
}
}
};
</script>
<style scoped>
</style>
lastly, you must get the state tableData and iterate the items in your table...
<template>
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>کد</th>
<th>نام محصول</th>
<th>دسته</th>
<th>قیمت</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
<tr v-for="item in tableData" :key="item.name">
<td>{{ item.code }}</td>
<td>{{ item.name }}</td>
<td>{{ item.category }}</td>
<td>{{ item.price }}</td>
<td>
<button type="button" class="btn btn-primary mt">ویرایش</button>
<button type="button" class="btn btn-danger mt">حذف</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: {
...mapState(["tableData"])
}
};
</script>
<style scoped>
</style>
Here is the working code https://codesandbox.io/s/goofy-grass-c1ysg
You are on right path, most part of your code is correct, please modify your Form.vue as below to dispatch actions in your store.
<template>
<div>
<form action>
<div class="form-group">
<label for="name">نام محصول:</label>
<input type="text" class="form-control" id="name" placeholder name="name" v-model="name">
</div>
<div class="form-group">
<label for="grouping">دسته بندی:</label>
<input type="text" class="form-control" id="grouping" placeholder name="group" v-model="category">
</div>
<div class="form-group">
<label class="code">کد محصول:</label>
<input type="text" class="form-control" id="coding" placeholder name="code" v-model="code">
</div>
<div class="form-group">
<label for="price">قیمت محصول</label>
<input type="text" class="form-control" id="pricing" placeholder name="price" v-model="price">
</div>
<button type="button" class="btn btn-success send" #click.prevent="addUser">ثبت اطلاعات</button>
</form>
</div>
</template>
<script>
export default {
data(){ return { name: '', category: '', code: '', price: '', } },
methods: {
addUser() {
this.$store.dispatch('updateName', this.name)
this.$store.dispatch('updateCategory', this.category)
this.$store.dispatch('updateCode', this.code)
this.$store.dispatch('updatePrice', this.price)
},
}
};
</script>
<style scoped>
</style>
You are getting the values of form individually from store and rendering it to the input. This causes the problem that you cannot add rows to the table.
Have your store like
state: {
formData: {
name: "",
category: "",
code: "",
price: ""
},
show: false
},
Form.vue script
export default {
data() {
return { formData: this.$store.getters.formData }
},
// rest of the code
}
Change the template v-model bindings in the form to formData.name or formData.category.
So now the addUser method will have the following.
this.$store.commit("formData", this.formData);
This will update the store with submitted data.
UPDATE
Form.Vue
<template>
<div>
<form>
<div class="form-group">
<label for="name">نام محصول:</label>
<input
type="text"
class="form-control"
id="name"
placeholder
name="name"
v-model="formData.name"
>
</div>
<div class="form-group">
<label for="grouping">دسته بندی:</label>
<input
type="text"
class="form-control"
id="grouping"
placeholder
name="group"
v-model="formData.category"
>
</div>
<div class="form-group">
<label class="code">کد محصول:</label>
<input
type="text"
class="form-control"
id="coding"
placeholder
name="code"
v-model="formData.code"
>
</div>
<div class="form-group">
<label for="price">قیمت محصول</label>
<input
type="text"
class="form-control"
id="pricing"
placeholder
name="price"
v-model="formData.price"
>
</div>
<!-- <button type="button" class="btn btn-success send" #click="updateName, updateCategory, updateCode, updatePrice, $store.state.show = true, send">ثبت اطلاعات</button>-->
<button
type="submit"
class="btn btn-success send"
#click.prevent="addUser"
>submit</button>
</form>
{{this.$store.getters.fdata}}
</div>
</template>
<script>
export default {
data(){
return { formData: {} }
},
methods: {
addUser() {
this.$store.commit('updateFdata', {...this.formData})
}
}
};
</script>
Table.vue
<template>
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>کد</th>
<th>نام محصول</th>
<th>دسته</th>
<th>قیمت</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
<tr v-for="(fdata, index) in fData" :key=index>
<td>{{ fdata.code }}</td>
<td>{{ fdata.name }}</td>
<td>{{ fdata.category }}</td>
<td>{{ fdata.price }}</td>
<td>
<button type="button" class="btn btn-primary mt">ویرایش</button>
<button type="button" class="btn btn-danger mt">حذف</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
computed: mapGetters(['fData'])
}
</script>
Store.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
formData: {
name: "",
category: "",
code: "",
price: ""
},
show: false,
fData: []
},
getters: {
fData: state => state.fData
},
mutations: {
updateFdata: (state, payload) => {
state.fData = [ ...state.fData, payload]
}
}
});

Vue.js modal window not opening on click from another component

I'm new to Vue.js and struggling to understand how to open a modal window on click.
Basically when I call the modal from another component I want to open the modal itself and show the data I'm passing to it from an API call. The problem is that that the modal still not shown with an inline "display:none". I'm going crazy why I cannot make it "display:block" even if I'm setting to true the prop I'm passing to the modal.
Can anyone look at the code and advise something? I'm out of resources :/
Modal component below:
<template>
<div id="modal" class="modal fade show" v-show="modalVisible" aria-labelledby="myModalLabel">
<div class="container">
<img :src="movieDetails.Poster" />
<div class="copy">
<p>
<span>Title:</span>
{{ movieDetails.Title }}
</p>
<p>
<span>Year:</span>
{{ movieDetails.Released }}
</p>
<p>
<span>Genre:</span>
{{ movieDetails.Genre }}
</p>
<p>
<span>Director:</span>
{{ movieDetails.Director }}
</p>
<p>
<span>Actors:</span>
{{ movieDetails.Actors }}
</p>
<p>
<span>Plot:</span>
{{ movieDetails.Plot }}
</p>
<p>
<span>IMDB Rating:</span>
{{ movieDetails.imdbRating }}
</p>
</div>
<button class="btn btn-light" #click="$emit('close')">Close</button>
</div>
</div>
</template>
<script>
export default {
name: "Modal",
props: ["movieDetails", "modalVisible"]
};
</script>
Component I'm calling the modal from:
<template>
<div class="container">
<h3>Movies database</h3>
<div class="input-group w-50 mx-auto">
<input
class="form-control"
id="input-search"
type="text"
v-model="textSearch"
placeholder="Search movie by title"
/>
<span class="input-group-btn">
<button type="button" class="btn btn-primary" v-on:click="searchMovie">Go!</button>
</span>
</div>
<div class="list-results" v-if="resultsFeed && resultsFeed.length">
<table class="table table-hover text-left">
<thead class="thead-light">
<tr>
<th scope="col">Title</th>
<th scope="col">Year</th>
<th scope="col">Poster</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr v-for="result in resultsFeed" v-bind:key="result.imdbID" :data-id="result.imdbID">
<td>{{ result.Title }}</td>
<td>{{ result.Year }}</td>
<td>
<img alt="movie poster" :src="result.Poster" />
</td>
<td class="text-right">
<button class="btn btn-secondary" #click="moreMovieInfo(result)">Show info</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="list-message" v-else>No results!</div>
<modal v-if="modalVisible" #close="modalVisible = false" :movieDetails="extraInfoFeed" />
</div>
</template>
<script>
import axios from "axios";
import modal from "./Modal.vue";
export default {
name: "Search",
components: {
modal
},
data() {
return {
resultsFeed: [],
extraInfoFeed: [],
textSearch: "",
modalVisible: false,
modalData: null
};
},
methods: {
searchMovie() {
var that = this;
axios
.get(
`https://www.omdbapi.com/?s=${encodeURIComponent(
this.textSearch
)}&apikey=a56adf1b`
)
.then(function(response) {
that.resultsFeed = response.data.Search;
})
.catch(function(error) {
console.log(error);
});
},
moreMovieInfo: function(result) {
var that = this;
axios
.get(
`https://www.omdbapi.com/?i=${encodeURIComponent(
result.imdbID
)}&apikey=a56adf1b`
)
.then(function(response) {
that.extraInfoFeed = response.data;
that.modalVisible = true;
// document.getElementById("modal").style.display = "block";
})
.catch(function(error) {
console.log(error);
});
// this.modalData = result;
}
}
};
</script>
<modal v-if="modalVisible" #close="modalVisible = false" :movieDetails="extraInfoFeed" />
So you are using v-if here and your Model component is expecting modalVisible as a prop to work. So, even when modalVisible is true, v-if will allow Modal component to be created, but its internal v-show will hide it as its modalVisible prop is null.
This should work:
<modal :modal-visible="modalVisible" #close="modalVisible = false" :movieDetails="extraInfoFeed" />