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

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

Related

vue.js alert pops instead of console.log or anything else

I was working on a Follow button and while trying to get things clear I used alert when I clicked my button, then I changed it to console.log instead of alert but still alert kept popping up. Then I did a text change instead of this but the alert keeps on popping. I already tried clearing cache or fresh migrate but still not working.
File: Follow.vue
<template>
<div class="container">
<button class="btn btn-primary ml-4" #click="followUser" v-text="buttonText"></button>
</div>
</template>
<script>
export default {
props: ['userId','follows'],
mounted() {
console.log('Component mounted.')
},
data: function () {
return {
status: this.follows
}
},
methods: {
followUser(){
axios.post('/follow/' + this.userId)
.then(response =>{
this.status = ! this.status;
});
;
},
computed: {
buttonText(){
return (this.status) ? 'Unfollow' : 'Follow';
}
}
}
}
</script>
File: index.blade.php
...ect...
<follow-me user-id="{{ $user->id }}" follows="{{ $follows }}"> </follow-me>
...ect...
File: ProfilesController.php
public function index(User $user)
{
$follows = (auth()->user()) ? auth()->user()->following->contains($user->id) : false;
return view('profiles.index', compact('user', 'follows'));
}
File: FollowsController.php
public function store(User $user){
return auth()->user()->following()->toggle($user->profile);
}
Run npm run watch , it will recompile your whole asset( any js or css file).
Don't forget to run npm run watch (or dev) to update your built assets.
About your button, replace
<button class="btn btn-primary ml-4" #click="followUser" v-text="buttonText"></button>
By
<button class="btn btn-primary ml-4" #click="followUser">{{ buttonText }}</button>

Using Laravel defined routes within a VUE component

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';
},

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
});
}

Update and access alert message variable between Vue components

I am using VueJS with Laravel 6.0. What I'm trying to achieve is that to create global variables alertStatus and alertMsg, so that every time when an AJAX call is made, the global variables can be updated to display an alert message to user.
So I decided to use prototype variable for this case. The idea is that when AJAX call is success/fail in User.vue, the prototype variable should be updated, and Alerts.vue should display it accordingly.
However, it seems that the prototype variable display does not update when the data is changed in User.vue component.
I'm not sure if my methods are correct, would like to get some ideas from stackoverflow.
Thanks
main.js
Vue.prototype.$alertStatus = '';
Vue.prototype.$alertMsg = [];
Alerts.vue
<template>
<div class="alert alert-light alert-elevate" role="alert">
<div class="alert-icon">
<i class="flaticon-warning kt-font-brand"></i>
</div>
<div class="alert-text">
{{alertMsg}}
</div>
</div>
</template>
User.vue
<script>
export default {
mounted() {
var datatable = this.init();
datatable.on('kt-datatable--on-ajax-fail', function(event, data){
this.$alertStatus = data.responseJSON.status;
this.$alertMsg = data.responseJSON.msg;
});
},
}
</script>
I would consider using an event handler instead of the global prototype.
Event.js — credit to Jeffrey Way of https://laracasts.com/
class Event {
constructor() {
this.vue = new Vue();
}
fire(event, data = null) {
this.vue.$emit(event, data);
}
listen(event, callback) {
this.vue.$on(event, callback);
}
}
export default Event;
I have outlined the basic usage below, plus I added a v-if to your alert to hide it when not in use.
app.js
import Event from './Event';
window.Event = new Event;
Alerts.vue
<template>
<div v-if="show" class="alert alert-light alert-elevate" role="alert">
<div class="alert-icon"><i class="flaticon-warning kt-font-brand"></i></div>
<div class="alert-text">
{{ alert.msg }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
alert: {},
show: false,
}
},
mounted() {
// listen for a global event
Event.listen('show-alert',alert => {
this.alert = alert;
this.show = true;
});
},
}
</script>
User.vue
<script>
export default {
mounted() {
var datatable = this.init();
datatable.on('kt-datatable--on-ajax-fail', function(event, data){
// fire a global event
Event.fire('show-alert',{
status: data.responseJSON.status,
msg: data.responseJSON.msg,
});
});
},
}
</script>

Vue/Laravel How to pass form from blade to vue to use checkValidity

Made following button made by vue(single component).
<template>
<div>
<input type="submit" class="button_orange button_big" value="Register" v-show="!isSubmitting" #click="startSubmit">
<div class="button_disable button_big" v-show="isSubmitting">Register</div>
</div>
</template>
<script>
export default {
data() {
return {
isSubmitting: false,
};
},
methods: {
startSubmit() {
if (form.checkValidity()) {
this.isSubmitting = true;
}
},
reset() {
this.isSubmitting = false;
},
},
};
</script>
Current problem is how to pass the form to vue to use checkValidity() method. laravel blade is the following type source code.
if there is idea how to pass form from blade to vue, please help.
<form>
<input type="text" name="test">
<submit-button></submit-button>
</form>
What's the problem with this?
document.querySelector("form").checkValidity()
(Of course this would require to have this for as the only form on the page, so if you can, you should have an ID on the form and go for something like document.querySelector("#myForm01").checkValidity() instead.)

Resources