Using Laravel defined routes within a VUE component - laravel

I am using Laravel 6 and VUE. I am converting a blade file into a VUE component. The blade file contains a table with rows of data being pulled in from a mysql DB. I have created a draggable component that is displaying users and will allow me to drag and drop rows in order to rearrange them, and the table is using VUE slots to pass html to my component. On my index view the table has a button on it. When the button is clicked it goes to a /create endpoint/route that I defined in Laravel using a routes.php file. I don't want to use vue routing, I prefer to maintain my laravel routes as they are. The issue I am having is, I do not know how to implement this exactly as I am new to VUE. Can someone shed some light on this? I tried using axios but maybe I am mis-using? Is there a better way to use a vue component but continue to use my routes I have defined in routes.php? Thank you.
main.blade.php
<!-- Draggable Component -->
<div id="app">
<draggable table=#yield('content.main')></draggable>
</div>
routes.php (partial to show which endpoint I am wanting to hit)
$route->any('users/create', 'UsersController#create');
Draggable.vue
<template>
<section v-bind:table="table">
<button class="btn btn-default" #click="create()">
<i class="fa fa-plus"></i>
</button>
<slot></slot>
</section>
</template>
<script>
export default {
props: ['table'],
data() {
return {
draggable: '',
};
},
created() {
this.draggable = this.table;
},
methods: {
create() {
axios.get(this.endpoint, {
UserName: this.UserName
}).then(res => {
this.creating = true;
this.UserName = res.data.UserName
}).catch(err => {
console.log("Error: " + err);
})
},
},
computed: {
endpoint() {
return `users/create`;
},
}
};
</script>
The error I get when the button is clicked:
Error: Request failed with status code 404

in your endpoint() you can add window.location.protocol + "//" + window.location.host so the method would be
endpoint() {
return window.location.protocol + "//" + window.location.host + 'users/create';
},

Related

Laravel Nova | Arrow functions | computed property not working in Tool.vue

I have a computed property that is not working correctly. When reading the docs this is how it should be done for Vue 2.x. The code i have:
<template>
<div>
<button :disabled="isDisabled">Import configurator data</button>
<input class="input" type="file" id="file" v-on:change="setFile">
</div>
</template>
<script lang="js">
export default {
data: () => {
return {
importDisabled: true,
}
},
computed: {
isDisabled() {
return this.importDisabled;
},
},
methods: {
setFile: (e) => {
this.importDisabled = false;
},
}
}
</script>
Expected behaviour: Button enables when a file is selected.
Actual behaviour: Button stays disabled.
What am i missing here? A console.log within the isDisabled() methods shows it is only called once. It is not called after importDisabled changes.
Other info:
vue 2.6.12
laravel nova
Also note: Vue tools does not detect a Vue component in the inspector. But the Vue behaviour is working when loading the tool.
It seems arrow functions are bound to the parent context. That was the reason my code did not work. this is then not bound to the Vue instance but the parent (Window) which causes it not to work.
Wrong:
setFile: (e) => {
this.importDisabled = false;
},
Right:
setFile: function() {
this.importDisabled = false;
},
More information:
https://codingexplained.com/coding/front-end/vue-js/using-es6-arrow-functions-vue-js

Updates the data in vue with laravel without refreshing the page or overlapping the div

I have a problem in sight.
I just started to learn, but I'm confused about something, why when I update the data I send with axios.post and update them, the devil disappears for 2 seconds and refreshes the page.
Look how I thought
<li v-for="question in questions" :key="question.id" class="list-group-item">
{{ question.questiontype }}
<br>
<button v-on:click="addVote(question.id)">Add 1</button>
<br>
<span class="badge badge-primary"><strong>{{ question.votes }}</strong></span>
</li>
data() {
return {
success: false,
questions:[],
percentages:[],
}
},
created() {
this.getQuestions(),
this.getPercentages()
},
methods: {
getQuestions(){
axios.get('/api/questionlist')
.then((response)=>{
this.questions = response.data.question
})
},
getPercentages(){
axios.get('/api/getpercentage')
.then((response)=>{
this.percentages = response.data.percentage
})
},
addVote(id) {
axios.post('api/vote/' + id)
.then((response) => {
this.questions = response.data.question
console.log(response.data)
this.getQuestions()
})
}
So I'm interested in the data I sent with the post.
I would like the page to update without refresh or to overlap the div for 2 seconds.
What exactly am I doing wrong?
I tried a few ways on stackoverflow but they didn't help
If your button is inside a form, you probably want to add type="button" attribute to it or prevent the form submission action.
<button type="button" v-on:click="addVote(question.id)">Add 1</button>
OR:
<button v-on:click.prevent="addVote(question.id)">Add 1</button>
I'm guessing that's probably why you're seeing the page refresh. If you want to display the updated data, you either need to make another axios call to fetch or you need to return the new entry from your API endpoint and push/add it to your list.
So modify your code as follows:
addVote(id) {
axios.post('api/vote/' + id)
.then((response) => this.getQuestions());
}

VueJS dynamically add textareas based on user click (tinymce issue)

I built a dynamic form where the user has the option to add as many HTML textareas as possible. The problem I'm running into is when the user loads the next textarea, I lose tinymce. Same thing happening for any external script (example: datepicker and Select2.js). Any ideas?
Here is my code
<div v-for="index in counter" :key="index">
<email_template_row></email_template_row>
<hr>
</div>
<button class="btn btn-sm btn-success" #click="addRow" type="button">Add Row</button>
// Tinymce code here...
// load vuejs from cdn...
Vue.component('email_template_row', {
template: '<div><textarea name="col_2_content[]" class="form-control tinymce" placeholder="Body"></textarea></div>',
});
var vue = new Vue({
el: '#app',
data:{
counter: 1
},
methods: {
addRow: function () {
this.counter += 1;
}
},
});
Thank you.
You need to re-initialize those components after one is appended to the HTML.
So basically your addRow method should look like this:
addRow: function () {
this.counter += 1;
tinymce.init({
selector: 'textarea', // change this value according to your HTML, you can be more specific
auto_focus: 'element',
// add your configuration
});
}

Call a Vue.js function inside app.blade.php on button click

Hy Guys,
I need to call a Vue.js function inside app.blade.php file. It should be triggered on a button click.
Here is the code sample I've used.
<button onclick="changeItem()">Saved Items</button>
changeItem() is a Vue.js function.
Kindly help :)
In your app.blade define the component
<div id="app">
<example-component></example-component>
</div>
By defualt laravel will include Vue JS packages in resources\js\app.js
In your resources\js\components\ExampleComponent.vue (Below Code)
<template>
<button v-on:click="say">Say what</button>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
// define methods under the `methods` object
methods: {
say: function (event) {
// `this` inside methods points to the Vue instance
alert('Hello ')
// `event` is the native DOM event
if (event) {
alert(event.target.tagName + " Clicked ")
}
}
}
}
</script>
Run : npm run watch // To compile app.js
Please mark/upvote if this finds helpful :)
<div id="app">
<button #click="changeItem">
{{message}}
</button>
</div>
new Vue({
data: {
message: "Save Items"
},
methods: {
changeItem() {
alert("Clicked!")
}
}
})
#click="changeItem" it is short form v-on:click="changeItem"
Please read this

How to paginate with Vuetify and Laravel?

Goodnight
I'm trying to do server side paging with Vuetify and Laravel.
But the methods provided by Vuetify have not worked for me to do it correctly. I have a completed page that I want to implement with the Vuetify components.
I attach my code made with simple bootstrap.
<ul class="pagination">
<li class="page-item" v-if="pagination.current_page > 1">
<v-btn flat icon color="red lighten-2">
<v-icon #click.prevent="changePage(pagination.current_page - 1, search)">thumb_down</v-icon>
</v-btn>
</li>
<li class="page-item" v-for="page in pagesNumber" :key="page" :class="[page == isActived ? 'active' : '']">
<v-btn fab dark color="indigo" #click.prevent="changePage(page, search)" v-text="page">
</v-btn>
</li>
<li class="page-item" v-if="pagination.current_page < pagination.last_page">
<v-btn flat icon color="red lighten-2">
<v-icon #click.prevent="changePage(pagination.current_page + 1, search)">thumb_down</v-icon>
</v-btn>
</li>
</ul>
Method of page to server:
methods:{
get(page, search){
let url = `http://127.0.0.1:8000/api/articles?page=${page}&search=${search}`;
axios.get(url)
.then( response => {
let res = response.data
this.products = res.articles.data;
this.pagination = res.pagination;
})
.catch(function (error) {
console.log(error);
})
},
changePage(page, search){
this.pagination.current_page = page;
this.get(page, search);
},
},
The previous code works correctly but without actually using the paging of the Vuetify component.
Using the Vuetify component for paging I only show the lentgh of the pagination but in no way I manage to pass between the pages provided by the server.
<v-pagination
v-model="pagination.current_page"
:length="pagination.total"
prev-icon="mdi-menu-left"
next-icon="mdi-menu-right"
#input="next"
></v-pagination>
Looking for information indicate that using #input="next" I can call a method to go to the next page but what can I use to return?
How can I click on any page number and ask for the page to the server as in my code made with bootstrap?
I wish I could help and I thank you.
Here is what works for me with Laravel 5.5 and Vuetify 1.3:
HTML
<v-pagination
v-model="pagination.current"
:length="pagination.total"
#input="onPageChange"
></v-pagination>
JS
export default {
data() {
return {
users: null,
pagination: {
current: 1,
total: 0
}
}
},
methods: {
getUsers() {
window.axios.get('/api/users?page=' + this.pagination.current)
.then(response => {
this.users = response.data.data;
this.pagination.current = response.data.current_page;
this.pagination.total = response.data.last_page;
});
},
onPageChange() {
this.getUsers();
}
},
mounted() {
this.getUsers();
}
}
Laravel
public function users()
{
$users = User::paginate(10);
return response($users, 200);
}
When your component is mounted, getUsers() will get called. pagination.current defaults to 1 so the first page will load. The response will set pagination.total. Vuetify handles binding the page buttons to pagination.current so that when you click one, pagination.current gets set to the page number and then #input triggers getUsers() which uses pagination.current to get the page you selected.
Note: in laravel 5.8, the pagination response object may have changed from response.data.current_page to response.data.meta.current_page and response.data.last_page to response.data.meta.last_page
.

Resources