How to pass updated data to already child vue component rendered - laravel

I'm trying to update some vars into a component from parent. My situation is this:
I have a parent component:
import LugarListComponent from './LugarListComponent';
import LugarAddComponent from './LugarAddComponent'
export default {
components:{
'lugar-list-component' : LugarListComponent,
'lugar-add-component' : LugarAddComponent,
},
data(){
return {
show: false,
nombre: '',
desc : '',
}
},
methods:{
showComponent: function () {
this.show = true;
},
hideComponent: function () {
this.show = false;
},
setLugar: function(lugar){
this.show = true;
}
},
mounted() {
//console.log('Component mounted.')
}
}
<template>
<div class="container">
<h3>Lugares</h3>
<div style="text-align: right">
<button type="button" class="btn btn-primary" v-show="!show" v-on:click.prevent="showComponent"><i class="fa fa-plus"></i> Adicionar</button>
<button type="button" class="btn btn-success" v-show="show" v-on:click.prevent="hideComponent"><i class="fa fa-arrow-left"></i> Regresar</button>
</div>
<br>
<lugar-list-component v-show="!show" #setLugar="setLugar"></lugar-list-component>
<lugar-add-component v-show="show" #hideComponent="hideComponent"></lugar-add-component>
</div>
</template>
This component has two childs components, lugar-list for list places and lugar-add for add a place. I have a show var for control when I show one of this.
I want to edit a place, but I want to send data to lugar-add for show his values into this component, but I don't find any solution for update the vars into lugar-add. Here I show the code of this components.
For lugar-add
export default {
data(){
return {
image: '',
nombre: '',
desc : ''
}
},
methods: {
onImageChange(e) {
let files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
},
createImage(file) {
let reader = new FileReader();
let vm = this;
reader.onload = (e) => {
vm.image = e.target.result;
};
reader.readAsDataURL(file);
},
uploadImage(){
axios.post('/lugar',{
image: this.image,
nombre: this.nombre,
desc: this.desc
}).then(response => {
if(response.status == 200){
this.$emit('hideComponent')
}
});
},
setAttributes(lugarEdit){
console.log('disparado');
this.nombre = lugarEdit.nombre;
this.desc = lugarEdit.desc;
}
},
mounted() {
//console.log('Component mounted.');
this.$on(
'setAttributes',
function(lugar) {
this.nombre = lugar.nombre;
this.desc = lugar.desc;
}
);
}
<template>
<div class="container">
<div class="form-group">
<label>Nombre</label>
<input type="text" v-model="nombre" class="form-control" placeholder="Nombre del lugar">
</div>
<div class="form-group">
<label for="descTexArea">Descripción</label>
<textarea v-model="desc" class="form-control" id="descTexArea" rows="3"></textarea>
</div>
<div class="form-group">
<label for="exampleFormControlFile1">Subir imágenes</label>
<input type="file" v-on:change="onImageChange" class="form-control-file" id="exampleFormControlFile1">
</div>
<div class="form-group">
<button type="button" class="btn btn-primary" #click="uploadImage">Adicionar</button>
</div>
<div class="col-md-3" v-if="image">
<img :src="image" class="img-responsive" height="70" width="90">
</div>
</div>
</template>
Here I use event for hide this component and show the lugar-list component. Here is the code for lugar-list
export default {
name: 'lugar-list-component',
data:function(){
return {
listLugares : [],
id : '',
}
},
methods:{
getLugares: function () {
fetch('/lugar')
.then(response => response.json())
.then(res => {
this.listLugares = res;
})
},
setId: function(id){
this.id = id;
},
removeLugar: function(id){
this.id = id;
axios.delete('lugar/'+id)
.then(response => {
this.getLugares();
});
},
editLugar: function(id){
this.id = id;
axios.get('lugar/'+id)
.then(response => {
this.$emit('setLugar',response);
});
},
},
mounted() {
this.getLugares();
}
}
<template>
<div class="container">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Nombre</th>
<th scope="col">Desc.</th>
<th scope="col">Fecha</th>
<th scope="col">Acciones</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in listLugares">
<th scope="row">{{ index+1 }}</th>
<td>{{ item.nombre }}</td>
<td>{{ item.desc }}</td>
<td>{{ item.created_at }}</td>
<td>
<button type="button" class="btn btn-success" v-on:click.prevent="editLugar(item.id)"><i class="fa fa-edit"></i> Editar</button>
<button type="button" class="btn btn-danger" v-on:click.prevent="removeLugar(item.id)"><i class="fa fa-remove"></i> Eliminar</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
I hope that you can understand me. Thanks.

Emit an event from the 1st child component to update parent's prop. Then pass the value you want to update as a prop to the secund child element.

I don't find other solution that use routes with params, I believe that is the best solution.
Here is my routes
{
path: '/lugar', component: require('./components/lugar/LugarComponent').default,
children: [
{ path: '', component: LugarList },
{
path: 'add/:id?',
name: 'lugarAdd',
component: LugarAdd
},
{
path: 'list',
component: LugarList
}
]
}
The route for Add a place has an optional param.
Now, into the Add component I get the param with this code:
this.id = this.$route.params.id;
this.modeEdit = true;
axios.get('/lugar/'+this.id)
.then(response => {
this.nombre = response.data.nombre;
this.desc = response.data.desc;
for(let i = 0; i<response.data.images.length; i++){
this.image.push(response.data.images[i]);
}
});
When I get the place id I request for its information with axios.

Related

Laravel + Vue V-IF updating in the database but not in the view

I have a project when I'm using Laravel 7.3 + Vue.
I am trying to assign a company to an internal employee. When I click the "Assign Company" button everything is fine and I can select the company in a select box, but when I click the "Save Company" button now, I can see the change in my database, but I don not see the changes live in my view/template, I need to refresh the webpage to see the assigned company.
This is my File.vue between the <template>:
<td><h4 v-if="editEmpleado" class="text-black-50">{{EmpleadosInterno.empresa}}</h4>
<select v-else class="form-control" id="Cliente" v-model="ClienteSeleccionado">
<option v-for="Cliente in Clientes"
:key="Cliente.id"
:value="Cliente">{{Cliente.nombreempresa}}</option>
</select>
</td>
<td>
<a v-if="editEmpleado" type="button" class="btn btn-primary" v-on:click="onClickEdit()">
Assign Company
</a>
<button v-else type="button" class="btn btn-success" v-on:click="onClickUpdate()">
Save Company
</button>
</td>
And this is my script
export default {
props: ['EmpleadosInterno'],
data() {
return {
ClienteSeleccionado: {},
Clientes: [],
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
editEmpleado: true
}
},
mounted() {
axios.get('/Clientes').then((response) => {
this.Clientes = response.data;
},
);
},
methods: {
onClickEdit() {
this.editEmpleado = false;
},
onClickUpdate() {
const params = {
nombreempresa: this.ClienteSeleccionado.nombreempresa
}
axios.put(`/EmpleadosInternos/${this.EmpleadosInterno.id}`, params).then((response) => {
const EmpleadosInterno = response.data;
this.$emit('update', EmpleadosInterno);
this.editEmpleado = true;
});
},
This is my services.vue
<div class="container">
<div class="row justify-content-center text-center">
<div class="col-md-12">
<h2 class="text-primary">Empleados Registrados:</h2>
<table class="table table-bordred table-striped ">
<thead>
<tr>
<th>Nombre</th>
<th>Telefono</th>
<th>Empresa</th>
<th>Acción</th>
</tr>
</thead>
<tbody>
<empleadocomponente-component
v-for="(EmpleadosInterno, index) in EmpleadosInternos"
:key="EmpleadosInterno.id"
:EmpleadosInterno="EmpleadosInterno"
#update="updateEmpleadosInterno(index, ...arguments)"
#delete="deleteEmpleadosInterno(index)">
</empleadocomponente-component>
</tbody>
</table>
</div>
</div>
</div>
<script>
export default {
data(){
return {
EmpleadosInternos: [],
}
},
mounted() {
axios.get('/EmpleadosInternos').then((response) => {
this.EmpleadosInternos = response.data;
},
);
},
methods: {
updateEmpleadosInterno(index, EmpleadosInterno){
this.EmpleadosInternos[index] = EmpleadosInterno;
},
deleteEmpleadosInterno(index){
this.EmpleadosInternos.splice(index, 1);
}
}
}
</script>

csrf toke is not passing to vuejs in laravel 8

I am trying to make an file uploader using vuejs in laravel 8, I am using the following meta tag for this purpose :
<meta name="csrf-token" content="{{ csrf_token() }}">
But unfortunately I am still getting error 419. I am sharing screenshots of page source and console result bellow :
page source :
Console result :
My codes for axios is :
export default {
data(){
return{
}
},
methods:{
async callApi(method, url, dataobject){
try{
return await axios({
method: method,
url: url,
data: dataobject
});
}catch(e){
return e.response
}
}
}
}
The code in test.vue (where I want the uploader should be working ) :
<template>
<div>
<Button type="success" #click="addname=true">Add New Name</Button>
<table>
<tr>
<td>Name</td>
<td>Created At</td>
<td>Action</td>
</tr>
<tr v-for="(item, i) in array" :key="i" v-
if="array.length">
<td>{{ item.name}}</td>
<td>{{ item.created_at}}</td>
<td>
<Button type="info" size="small"
#click="showEditModal(item, i)">Edit</Button>
<Button type="error" size="small"
#click="showDeletingModal(item,i)"
:loading="item.isDeleting">Delete</Button>
</td>
</tr>
</table>
</div>
<!-- Add -->
<Modal v-model="addname" title="Add New Name" :mask-closable= "false"
:closable = "false" >
<Label>Your Name</Label>
<Input v-model ="data.name" type="text" />
<Upload
multiple
type="drag"
action="/upload">
<div style="padding: 20px 0">
<Icon type="ios-cloud-upload" size="52" style="color:
#3399ff"></Icon>
<p>Click or drag files here to upload</p>
</div>
</Upload>
<div slot="footer">
<Button type="error" #click="addname=false">Close</Button>
<Button type="success" #click="addData"
:disabled="isAdding" :loading="isAdding">{{isAdding ?
'Adding..' : 'Add Name'}}</Button>
</div>
</Modal>
<!-- Edit -->
<Modal v-model="editModal" title="Edit tag" :mask-closable= "false"
:closable= "false">
<Input v-model="edit_data.name" placeholder="Edit tag name"
/>
<div slot="footer">
<Button type="default" #click="editModal=
false">Cancel</Button>
<Button type="primary" #click="editData"
:disabled="isAdding" :loading="isAdding">{{isAdding ?
'Editing..' : 'Edit Name'}}</Button>
</div>
</Modal>
<!-- delete alert modal -->
<Modal v-model="showDeleteModal" width="360">
<p slot="header" style="color:#f60;text-align:center">
<Icon type="ios-information-circle"></Icon>
<span>Delete confirmation</span>
</p>
<div style="text-align:center">
<p>Are you sure you want to delete tag?.</p>
</div>
<div slot="footer">
<Button type="error" size="large" long :loading="isDeleting"
:disabled="isDeleting" #click="deleteName">Delete</Button>
</div>
</Modal>
</div>
</template>
<script>
export default {
data(){
return{
data: {
name : ''
},
addname : false,
editModal : false,
isAdding : false,
array: [],
edit_data : {
name : ''
},
index : -1,
showDeleteModal : false,
isDeleting : false,
deleteItem : {},
deletingIndex : -1,
}
},
methods: {
async addData(){
if(this.data.name.trim()=='') return this.e('Name is required !')
const hi = await this.callApi('post','add_data',this.data)
if(hi.status===201){
this.array.unshift(hi.data)
this.s('Name added successfully')
this.addname = false
this.data.name = ''
}else{
if(hi.status==422){
if(hi.data.errors.name){
this.i(hi.data.errors.name[0])
}
}else{
this.smr()
}
}
},
async editData(){
if(this.edit_data.name.trim()=='') return this.e('name is
required')
const hi = await this.callApi('post', 'edit_data',
this.edit_data)
if(hi.status===200){
this.array[this.index].name = this.edit_data.name
this.s('Name has been edited successfully!')
this.editModal = false
}else{
if(hi.status==422){
if(hi.edit_data.errors.name){
this.e(hi.edit_data.errors.name[0])
}
}else{
this.smr()
}
}
},
showEditModal(item, index){
let obj = {
id : item.id,
name : item.name
}
this.edit_data = obj
this.editModal = true
this.index = index
},
async deleteName(){
this.isDeleting = true
const hi = await this.callApi('post', 'delete_data',
this.deleteItem)
if(hi.status===200){
this.array.splice(this.i,1)
this.s('successfully Deleted')
}else{
this.smr()
}
this.isDeleting = false
this.showDeleteModal = false
},
showDeletingModal(item, i){
this.deleteItem = item
this.i = i
this.showDeleteModal= true
}
},
async created(){
const hi = await this.callApi('get','get_data')
if(hi.status===200){
this.array = hi.data
}else{
this.smr()
}
}
}
</script>
<style scoped>
.space{
width:100%;
height:5px;
}
</style>
You should manually pass CSRF token when making a request. Just push the following to every request:
_token: document.querySelector("meta[name='csrf-token']").getAttribute("content");

Update quantity of an existing product in shopping cart in laravel and vuejs

I am building a shopping cart in vuejs, when I add my product, someone who can help me insert it again instead of increasing the amount.
thanks.
COMPONENT 1
this is the body of my table where I render my cart
<tbody >
<tr v-for="(ProductCart, index) in carrito" :key="index.id">
<td>{{ProductCart.name}}</td>
<td>{{ProductCart.cantidad}}</td>
<td>{{ProductCart.precio}}</td>
<td>{{ProductCart.cantidad * ProductCart.precio}}</td>
<td>
<form method="post">
<input :value="csrf" type="hidden" name="_token" >
<input type="hidden" name="id" value="" >
<button class="btn btn-success" type="submit"> Remove</button>
</form>
</td>
</tr>
<tr>
<th colspan="2"></th>
<td>
<h5>Total</h5>
</td>
<td align="right">
<h5>{{ total }}</h5>
</td>
</tr>
</tbody>
script
<script >
import Axios from 'axios'
import EventBus from '../event-bus'
export default {
data(){
return{
csrf: document.head.querySelector('meta[name="csrf-token"]').content,
carrito: [],
}
},
created: function(data){
EventBus.$on('agregado', (data) => {
this.carrito.push(data);
})
},
mounted(){
Axios.get('carrito')
.then(Response => {this.carrito = Response.data})
},
computed: {
//fincion total
total: function () {
let total = 0;
Object.values(this.carrito).forEach(
(item) => (total += item.precio * item.cantidad)
);
return total.toFixed(2);
},
cantidad: function(){
}
},
}
</script>
component content where is the compass cart
form button which executes the method
<button v-on:click="addproduct" class="btn btn-info btn-block" type="submit"> Add</button>
this is the content of the data
data(){
return {
csrf: document.head.querySelector('meta[name="csrf-token"]').content,
Productos:{
id: 1,
name: 'producto 3',
precio: 1,
cantidad: 1,
}
}
},
method to add product
addproduct: async function () {
axios.post('sales/item', {
id: this.Productos.id,
name: this.Productos.name,
precio: this.Productos.precio,
cantidad: this.Productos.cantidad,
})
.then(function(response){
EventBus.$emit('agregado', response.data)
})
.catch(error => {
console.log(error.response);
});
},

Data are not loaded in Edit Form in Vue app

I'm experimenting with Vue.js and Axios with Laravel. I'm using this tutorial where a simple Posts app is build: https://pusher.com/tutorials/laravel-vue-axios. I'm trying to extend this with an Update function. When I'm clicking on the edit button near a Post, the right Id is fetched. But in my Edit form the data of the post aren't loading. What could be the issue?
This is my code in EditPost.vue:
<template>
<form action="" #submit="editPost(post)">
<h4 class="text-center font-weight-bold">Post edit form</h4>
<div class="form-group">
<input type="text" placeholder="title" class="form-control"> {{ post.title }}
</div>
<div class="form-group">
<textarea placeholder="content" class="form-control" v-model="post.content">
</textarea>
</div>
<div class="form-group">
<button :disabled="!isValid" class="btn btn-block btn-primary" #click.prevent="updatePost(post)">Update
</button>
</div>
</form>
</template>
<script>
import {mapGetters, mapActions} from 'vuex'
export default {
name: "EditPost",
data() {
return {
post:{}
}
},
created () {
this.fetchData();
},
mounted() {
this.$store.dispatch('fetchPost')
},
methods: {
...mapActions('post', [
'fetchPost',
'updatePost'
]),
updatePost(post) {
this.$store.dispatch('updatePost', post)
},
fetchData: function () {
var _this = this;
// ajax call - then
_this.$store.commit('setData', {
name: 'post',
data: res.data.post
});
}
},
computed: mapGetters([
'posts'
])
}
</script>
This is the code in recources/js/store/actions.js:
fetchPost({commit}, post) {
axios.get(`/api/posts/${post.id}`)
.then(res => {
commit('FETCH_POST', res.data)
}).catch(err => {
console.log(err)
})
},
UPDATE: I've put in extra code.
file Posts.vue:
<template>
<div>
<h4 class="text-center font-weight-bold">Posts</h4>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Content</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="post in posts">
<td>{{post.title}}</td>
<td>{{post.content}}</td>
<td>
<button class="btn btn-info" #click="editPost(post)"><i style="color:white" class="fa fa-edit"></i></button>
<button class="btn btn-danger" #click="deletePost(post)"><i style="color:white" class="fa fa-trash"></i></button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: "Posts",
mounted() {
this.$store.dispatch('fetchPosts')
},
methods: {
editPost(post) {
this.$store.dispatch('fetchPost',post)
},
deletePost(post) {
this.$store.dispatch('deletePost',post)
}
},
computed: {
...mapGetters([
'posts'
])
}
}
</script>
file recources/js/store/getters.js:
let getters = {
posts: state => {
return state.posts
}
}
export default getters
file recources/js/store/state.js:
let state = {
posts: []
}
export default state
file recources/js/store/mutations.js:
let mutations = {
CREATE_POST(state, post) {
state.posts.unshift(post)
},
FETCH_POSTS(state, posts) {
return state.posts = posts
},
UPDATE_POST(state, post) {
let index = state.posts.findIndex(item => item.id === post.id)
},
DELETE_POST(state, post) {
let index = state.posts.findIndex(item => item.id === post.id)
state.posts.splice(index, 1)
}
}
export default mutations
You are using post.content, which is coming from your data prop post. I don't see you adding content to post anywhere in your code.
I'm assuming your getter posts is getting the post data from the store.
So maybe you just need to use that instead?
v-model="posts.content">
Without seeing more of your code I cannot tell you exactly what to do. But your main problem is after you update the store value you need to get that value somehow.

How to reload the data of a table with vue and axios?

Well, i have a table populated with v-for: "usuario in usuarios". The initial charge does it correctly. But when i push the button "Buscar" only my <p>{{nombre}}</p> shows data. Look at these pictures:
Table populated with data
In the above picture, the table was populated with data, through getUsuarios() method. But in the next picture the table only shows blank data.
Table with blank data and <p>{{nombre}}</p>
Here are my codes:
Template:
<div>
<div class="panel panel-default">
<div class="panel-heading"><h1><strong>Lista de nombres</strong></h1></div>
<div class="panel-body">
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
<th>Nombre</th>
<th>Apellido Paterno</th>
<th>Apellido Materno</th>
</tr>
</thead>
<tbody>
<tr v-for="usuario in usuarios">
<td>{{usuario.Nombre}}</td>
<td>{{usuario.Apellido_P}}</td>
<td>{{usuario.Apellido_M}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<br />
<p>Buscar usuario</p>
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" v-model="busqueda" placeholder="Buscar usuario" />
<button class="btn btn-default" v-on:click="buscarUsuario">Buscar</button>
</div>
<p>{{nombre}}</p>
</div>
</div>
</template>
Script
<script>
import axios from 'axios'
export default {
data() {
return {
usuarios:[],
busqueda: '',
nombre: '',
}
},
methods: {
buscarUsuario() {
axios.get('http://localhost:50995/api/GetUsuario?id=' + this.busqueda)
.then(response => {
this.usuarios = response.data,
this.nombre = response.data.Nombre
}).catch(e => {
console.log(e)
})
},
getUsuarios() {
axios.get("http://localhost:50995/api/GetUsuarios")
.then(response => {
this.usuarios = response.data
})
.catch(e => {
console.log(e)
})
}
},
created() {
this.getUsuarios(),
this.buscarUsuario()
}
}
</script>
As you can see, the <p>{{nombre}}</p> is populated with the data of the ID that i put in the input. But the table only shows blank data.
The <p>{{nombre}}</p> is only for test if the buscarUsuario() method works, and it's works but not with the table.
And, how can i reload the data of the table with the properties of the ID when i push the "Buscar" button?
Thank you
Something is wrong in your buscarUsuario() logic: you are overwriting the initial correct array of usuario objects with a single object of one usuario
axios.get('http://localhost:50995/api/GetUsuario?id=' + this.busqueda)
.then(response => {
/* REMOVE THIS LINE */ this.usuarios = response.data,
this.nombre = response.data.Nombre
}).catch(e => {
console.log(e)
})

Resources