I am working with laravel and vuejs I show the data with dataTable, in the mobile version it does not show me the api data, the problem is in the mobile version that is not shown, in the desktop version if the data is shown, the edit buttons do not open in mobile version either. I have tried link an api from the internet and if it shows me the data.
Controller:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use App\Models\Admin\Dependence;
use App\Http\Controllers\Controller;
use App\Http\Controllers\ResponseApiController;
class DependenceController extends ResponseApiController
{
public function getDependencies()
{
$dependencies = Dependence::orderBy('created_at', 'desc')->get();
$message = $this->sendResponse($dependencies, 'Dependencias listadas correctamente');
return $message;
}
}
Route:
Route::get('dependencies', 'Admin\DependenceController#getDependencies');
Vue - Libraries in global file:
//DataTables
import 'datatables.net-bs4';
import 'datatables.net/js/jquery.dataTables.min.js';
import 'datatables.net-bs4/css/dataTables.bootstrap4.min.css';
import 'datatables.net-bs4/js/dataTables.bootstrap4.min.js';
import 'datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css';
import 'datatables.net-responsive-bs4/js/responsive.bootstrap4.min.js';
//DataTable Global
Vue.prototype.$tableGlobal = function(table) {
this.$nextTick(() => {
$(table).DataTable();
});
}
Template:
<template>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col-auto mr-auto">
<h2 class="text-secondary">Dependencies List</h2>
</div>
<div class="col-auto">
<button class="right btn btn-primary btn-sm" v-b-modal.modal-1 #click="showModal = true">Add</button>
</div>
</div>
</div>
<!-- /.card-header -->
<div class="card-body animated fadeIn">
<table id="tblDependencies" class="table table-bordered table-hover dt-responsive">
<thead>
<tr>
<th>Description</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr v-for="dependence in dependencies" :key="dependence.id">
<td>{{ dependence.description }}</td>
<td>
<!-- Change Status -->
<b-button size="sm" #click="statusUpdate(dependence)" class="mr-1" :class="[dependence.status == 1 ? 'btn-success' : 'btn-danger']">
<b-icon :icon="dependence.status == 1 ? 'check' : 'x' "></b-icon>
</b-button>
<!-- Edit -->
<b-button v-b-modal.editDependence size="sm" #click="editDependence(dependence)" class="btn btn-warning">
<b-icon icon="pencil-fill"></b-icon>
</b-button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
<!-- /.col -->
</div>
<AddDependence ref="dependenceModal" #reload="getDependencies"></AddDependence>
<EditDependence ref="editModal" :editDependence="this.dataEditDependence" #reload="getDependencies"></EditDependence>
</div>
</template>
<script>
// Services
import * as dependenceService from '../../services/dependence';
// Components
import AddDependence from '../../components/Admin/Dependence/AddDependence.vue';
import EditDependence from '../../components/Admin/Dependence/EditDependence.vue'
export default {
data() {
return {
dependencies: [],
dataEditDependence: {}
}
},
mounted() {
this.getDependencies();
},
components: {
AddDependence,
EditDependence
},
methods: {
getDependencies: async function() {
try {
const response = await dependenceService.getDependencies();
if(response.status == 200) {
this.dependencies = response.data.data;
this.reloadTable();
}
} catch (error) {
this.loading = false
console.log(error);
if (error.response.status == 422){
console.log(error);
}
}
},
statusUpdate: async function(dependence) {
try {
const response = await dependenceService.activateDesactivate(dependence.id);
if (response.status == 200) {
if(response.data.data.status == 1) {
dependence.status = 1;
}else {
dependence.status = 0;
}
this.$alerta('Actualizado', 'Estado actualizado correctamente', 'success');
this.reloadTable();
}
} catch (error) {
console.log(error);
}
},
editDependence(dependence) {
this.dataEditDependence = dependence;
},
reloadTable() {
$('#tblDependencies').DataTable().destroy();
this.$tableGlobal('#tblDependencies');
},
}
}
</script>
http_service:
import store from '../store';
import axios from 'axios';
export function http() {
return axios.create({
baseURL: store.state.apiURL,
});
}
Service:
import {http} from './http_service';
export function getDependencies() {
return http().get('/dependencies');
}
Related
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>
Nuxt.js I searched lots of tutorials for CSV uploading using laravel API but I did not get logic on how to code csv uploading things help me to solve this or give tutorial links.
Modules
import { AxiosResponse } from "axios";
import { axios } from "#/plugins/axios";
export default {
async importVsim(params: any): Promise<AxiosResponse<null>> {
return await <AxiosResponse>axios.post('v1/ucl/import',params);
}
}
Components
<template>
<div style="display:inline; text-align:left;">
<b-button icon-left="upload" #click="open">UCL CSV</b-button>
<b-modal
v-model="showModal"
trap-focus
aria-role="dialog"
aria-label="Example Modal"
:width="600"
aria-modal>
<div class="card mb-4">
<header class="card-header">
<p class="card-header-title">UCL CSV</p>
</header>
<div class="card-content">
<b-field label="mnk_*.csv">
<b-upload v-model="file1" class="file-label">
<span class="file-cta">
<b-icon class="file-icon" icon="upload"></b-icon>
<span class="file-label">Click to upload</span>
</span>
<span class="file-name" v-if="file1">
{{ file1.name }}
</span>
</b-upload>
</b-field>
<b-field label="htk_*.csv">
<b-upload v-model="file2" class="file-label">
<span class="file-cta">
<b-icon class="file-icon" icon="upload"></b-icon>
<span class="file-label">Click to upload</span>
</span>
<span class="file-name" v-if="file2">
{{ file2.name }}
</span>
</b-upload>
</b-field>
<div style="text-align:center;">
<b-button #click="close" :loading="loading">cancel</b-button>
<b-button class="is-primary" #click="upload" :loading="loading">Ok</b-button>
</div>
</div>
</div>
</b-modal>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "nuxt-property-decorator"
import importCsv from "#/modules/importCsv"
#Component({})
export default class extends Vue {
file1: any = null
file2: any = null
loading: boolean = false
showModal: boolean = false
errors: any = {}
async upload() {
const response = await importCsv.importVsim(this.file2)
console.log(response)
}
open() {
this.errors = {}
this.showModal = true
}
close() {
this.showModal = false
}
}
</script>
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");
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.
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.