Why is TinyMCE throwing "b is not a constructor", and "({default{}) is not a constructor" when attempting to upload images on Laravel Forge, not dev? - laravel

I have my image upload functionality working in development, for which my environment is Laravel Sail. It is working in development, but not in production Laravel forge where it is throwing 'b is not a constructor," and "({default{}}) is not a constructor", depending on whether you're using chrome or firefox respectively, which should have similar-identical environments. Only thing I can think I did differently between them is that in production I used npm run dev in development and npm run build for production. For the application, I'm using Laravel, InertiaJS, and Vue3 and It looks like this:
Vue Form and Script:
<form enctype="multipart/form-data" class="mb-4 md:flex md:flex-wrap md:justify-between" action="/dashboard/pages/store"
method="post">>
<input type="hidden" name="_token" :value="csrfToken">
<div class="flex flex-col mb-4 md:w-1/2">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest" for="title">Title </label>
<input class="border py-2 px-3 text-grey-darkest md:mr-2" type="text" name="title" id="title">
</div>
<div class="flex flex-col mb-4 md:w-1/2">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest"
for="slug">Slug </label>
<input class="border py-2 px-3 text-grey-darkest md:mr-2" type="text" name="slug" id="slug">
</div>
<div class="flex flex-col mb-4 md:w-1/2">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest"
for="slug">Status </label>
<select class="border py-2 px-3 text-grey-darkest md:mr-2" name="status" id="status">
<option value="published">Published</option>
<option value="draft">Draft</option>
</select>
</div>
<!-- Page Header Image -->
<div class="flex flex-col mb-4 md:w-1/2">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest"
for="slug">Page Header Image </label>
<input class="border py-2 px-3 text-grey-darkest md:mr-2" type="file" name="header_image" id="header_image">
</div>
<div class="flex flex-col mb-4 md:w-full">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest" for="content">Content </label>
<editor name="content" id="content" api-key='xxxxxxxxxxxxxxxx'
:init="{
plugins: [
'advlist autolink lists link image charmap print preview anchor',
'searchreplace visualblocks code fullscreen',
'insertdatetime media table contextmenu paste imagetools'
],
toolbar: 'insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image ',
image_title: true,
automatic_uploads: true,
file_picker_types: 'image',
images_upload_handler: function (blobInfo, success, failure) {
let data = new FormData();
data.append('file', blobInfo.blob(), blobInfo.filename());
axios.post('/dashboard/pages/upload-images', data)
.then(function (res) {
success(res.data.location);
})
.catch(function (err) {
failure('HTTP Error: ' + err.message);
});
}
}"/>
</div>
<div class="grid mb-4 md:w-full place-items-center">
<button class="bg-red-500 md:w-36 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
type="submit">
Create
</button>
</div>
</form>
Here's the error I'm getting. I don't even know how to get it into the console so I can debug it further:
This is definitely related to the build script, as I ran npm run build on my local machine and it's doing the same thing locally/in development.

This seems to have been an issue with #rollup/plugin-commonjs.
The vite documentation for migration notes that this is the biggest difference between dev and build, so I tried their alternative strategy for removing commonjs because esbuild converts CJS-only dependencies to ESM.
https://vitejs.dev/guide/migration.html#using-esbuild-deps-optimization-at-build-time
To do this, from my Laravel build, in app.js I had to declare my config as a const, then you can use optimizeDeps.disabled: false (the default in v3 is disabled: 'build'). #rollup/plugin-commonjs can be removed by passing build.commonjsOptions: { include: [] }
For me, that left my app.js looking like this:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '#vitejs/plugin-vue';
const config = defineConfig({
plugins: [
laravel({
input: 'resources/js/app.js',
ssr: 'resources/js/ssr.js',
refresh: true,
}),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
],
ssr: {
noExternal: ['#inertiajs/server'],
},
alias: {
src: '/src',
},
});
config.build = { ...config.build, include: [] };
config.optimizeDeps = { disabled: false };
export default config;

Related

Laravel redirect with data in vue

I'm trying to redirect my controller with data in laravel to a vue file which then displays the data. It's a SPA and I'm using vue router.
Here is my controller redirection:
return redirect('/bedankt-voor-je-bericht')->with('mailstatus', 'Bedankt voor uw bericht!');
And here is my vue file:
<script>
export default {
mounted() {
axios.get('/bedankt-voor-je-bericht')
.then((response) => {
console.log(response);
});
}
}
</script>
The response data does not include the mailstatus variable at the moment. But how will i accomplish this? Any help would be appreciated.
Update:
What is I want to send a form how would we accomplish that? Here is my code for the form:
<form method="post" action="/api/contact/send">
<div class="flex flex-col mb-[15px]">
<label class="font-bold text-[20px] mb-[5px]" for="">Naam</label>
<input class="border border-[#888888] rounded-[10px] min-h-[35px] px-2" type="text" name="name">
</div>
<div class="flex flex-col mb-[15px]">
<label class="font-bold text-[20px] mb-[5px]" for="">Emailadres</label>
<input class="border border-[#888888] rounded-[10px] min-h-[35px] px-2" type="text" name="email">
</div>
<div class="flex flex-col mb-[15px]">
<label class="font-bold text-[20px] mb-[5px]" for="">Bericht</label>
<textarea name="body" class="border border-[#888888] rounded-[10px] p-2 min-h-[215px] resize-none"></textarea>
</div>
<div class="flex justify-end">
<button type="submit" class="border border-[#25d097] bg-white text-[#25d097] w-full box-border p-2 rounded-[8px] hover:bg-[#25d097] hover:text-[#ffffff]">Verstuur</button>
</div>
</form>
Then i have my routes/api like this Route::post('/contact/send', ContactController::class); And in my controller I have this:
public function __invoke(Request $request)
{
if ($request->email && $request->name && $request->body) {
$mail = (new Mailsettings)->setup();
$mail->setFrom($request->email, $request->name);
$mail->addAddress(env('MAIL_USERNAME'), 'Plugzy');
$mail->addReplyTo($request->email, $request->name);
$mail->isHTML(true);
$mail->Subject = 'Nieuwe e-mail Plugzy';
$mail->Body = $request->body;
// $mail->send();
return response()->json(['mailstatus', 'Bedankt voor uw bericht!'], 200);
}
return response()->json(['mailstatus', 'Er ontbreekt iets!'], 200);
}
If the action is pointed to the api then there is no redirection to the next page.
For anyone that might run into this problem I've found an answer for returning a response without any page reloads. There's a npm package called v-form
thanks to this package I've managed to make it work as following:
This is my vue file for submitting the form:
<form #submit.prevent="sendemail()" #keydown="form.onKeydown($event)">
<div class="flex flex-col mb-[15px]">
<label class="font-bold text-[20px] mb-[5px]" for="">Naam</label>
<input
v-model="form.name"
class="border border-[#888888] rounded-[10px] min-h-[35px] px-2"
type="text"
name="name">
</div>
<div class="flex flex-col mb-[15px]">
<label class="font-bold text-[20px] mb-[5px]" for="">Emailadres</label>
<input v-model="form.email"
class="border border-[#888888] rounded-[10px] min-h-[35px] px-2"
type="text"
name="email">
</div>
<div class="flex flex-col mb-[15px]">
<label class="font-bold text-[20px] mb-[5px]" for="">Bericht</label>
<textarea v-model="form.body"
name="body"
class="border border-[#888888] rounded-[10px] p-2 min-h-[215px] resize-none">
</textarea>
</div>
<div class="flex justify-end">
<button type="submit" class="border border-[#25d097] bg-white text-[#25d097] w-full box-border p-2 rounded-[8px] hover:bg-[#25d097] hover:text-[#ffffff]">Verstuur</button>
</div>
</form>
<script>
import Form from 'vform'
export default {
data() {
return {
form: new Form({
name: '',
email: '',
body: ''
})
}
},
methods: {
sendemail: async function () {
const response = await this.form.post('/api/contact/send')
console.log(response);
}
}
}
</script>
And then in my api.php I've got this api route defined: Route::post('/contact/send', ContactController::class);. Which will activate my controller which has the following inside:
return response()->json(['mailstatus', 'Bedankt voor uw bericht!'], 200);. So now in the vue file I'll get the correct response without a page reload.

How can I show data names field in vue-multiselect plugin in edit page?

I have a vue laravel SPA, and was working on the edit page of employees page. I already have create employees page and can display data on the vue-multiselect plugin (https://vue-multiselect.js.org/). Right now, I can display the employee id's from an array in vue-multiselect in the edit page. How can I format it to show employee names?
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
<script>
import Multiselect from 'vue-multiselect'
export default {
components: { Multiselect },
data() {
return {
employee: {
designation_id: [],
position_id: [],
},
designation_names: {},
position_names: {}
}
},
methods: {
updateEmployee() {
this.axios
.patch(`/api/employees/${this.$route.params.id}`, this.employee)
.then((res) => {
this.$router.push({ name: 'employees' });
});
},
async getDesignations(id) {
const { data } = await this.axios.get(`/employees/${id}/designations`);
this.$set(this.designation_names, id, data.join(', '));
},
async getPositions(id) {
const { data } = await this.axios.get(`/employees/${id}/positions`);
this.$set(this.position_names, id, data.join(', '));
},
},
created() {
this.axios
.get(`/api/employees/${this.$route.params.id}`)
.then((res) => {
this.employee = res.data;
});
for(const row of this.rows) { this.getDesignations(row.id); }
for(const row of this.rows) { this.getPositions(row.id); }
},
}
</script>
<template>
<form #submit.prevent="updateEmployee">
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="name">First Name</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="name" id="name" type="text" placeholder="First Name" tabindex="1" v-model="employee.first_name" />
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="name">Last Name</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="name" id="name" type="text" placeholder="Last Name" tabindex="2" v-model="employee.last_name" />
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="designation_id">Designation</label>
<multiselect
v-model="employee.designation_id"
:options="designation_options"
:custom-label="opt => designation_options.find(designation => designation.id == opt).name"
:multiple="true"
:taggable="true"
></multiselect>
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="position_id">Position</label>
<multiselect
v-model="employee.position_id"
:options="position_options"
:multiple="true"
:taggable="true"
></multiselect>
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="basic_pay">Basic Pay</label>
<div class="relative rounded">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="text-gray-700">₱</span>
</div>
<input class="shadow appearance-none border rounded w-full py-2 pl-8 pr-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="basic_pay" id="basic_pay" type="number" step="any" placeholder="00.00" tabindex="5" v-model="employee.basic_pay" />
<div class="absolute inset-y-0 right-0 flex items-center"><label for="basic_pay" class="sr-only">Basic Pay</label>
</div>
</div>
</div>
<div class="md:w-3/6 mb-4 flex-1"> </div>
</div>
<button type="submit" class="sm:hidden md:flex bg-blue-500 hover:bg-blue-400 text-white font-bold py-2 px-4 border-b-4 border-blue-700 hover:border-blue-500 rounded outline-none focus:outline-none">Update</button>
</form>
</template>
I've managed to solve this by retrieving each field, instead of the previous code which I retrieved all in a single object.
this.axios
.get(`/api/designations/${this.$route.params.id}`)
.then((res) => {
this.form.name = res.data.name;
this.form.description = res.data.description;
});
Before:
this.axios
.get(`/api/designations/${this.$route.params.id}`)
.then((res) => {
this.form= res.data;
});

How can I create an array of id's from the selected option in vue-multiselect plugin?

I've created an Laravel Vue SPA app. Right now, I can successfully retrieved the data in object format and can display the names in vue-multiselect (https://vue-multiselect.js.org/) when selected. Also, I can already save the selected options to the database in an object format. My question is how can I save only the id's in an array?
This is the results from api:
[
{
"id": 1,
"name": "Shoe Machine Operators",
"description": "Iusto cupiditate quo veniam.",
"created_at": "2022-03-23T10:23:35.000000Z",
"updated_at": "2022-03-23T10:23:35.000000Z"
},
{
"id": 2,
"name": "Librarian",
"description": "Vero eius quidem quo fugiat.",
"created_at": "2022-03-23T10:23:35.000000Z",
"updated_at": "2022-03-23T10:23:35.000000Z"
}
]
Here's my markup code where my vue-multiselect element is:
<form #submit.prevent="addEmployee">
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="name">First Name</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="name" id="name" type="text" placeholder="First Name" tabindex="1" v-model="employee.first_name" />
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="name">Last Name</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="name" id="name" type="text" placeholder="Last Name" tabindex="2" v-model="employee.last_name" />
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="designation_id">Designation</label>
<multiselect v-model="employee.designation_id"
:options="designation_options"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
placeholder="Pick one or many"
label="name"
track-by="name"
:preselect-first="true"
>
<template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single" v-if="values.length && !isOpen">{{ values.length }} options selected</span></template>
</multiselect>
<pre class="language-json"><code>{{ employee.designation_id }}</code></pre>
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="position_id">Position</label>
<multiselect v-model="employee.position_id"
:options="position_options"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
placeholder="Pick one or many"
label="name"
track-by="name"
:preselect-first="true"
>
<template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single" v-if="values.length && !isOpen">{{ values.length }} options selected</span></template>
</multiselect>
<pre class="language-json"><code>{{ employee.position_id }}</code></pre>
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="basic_pay">Basic Pay</label>
<div class="relative rounded">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="text-gray-700">₱</span>
</div>
<input class="shadow appearance-none border rounded w-full py-2 pl-8 pr-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="basic_pay" id="basic_pay" type="number" step="any" placeholder="00.00" tabindex="5" v-model="employee.basic_pay" />
<div class="absolute inset-y-0 right-0 flex items-center"><label for="basic_pay" class="sr-only">Basic Pay</label>
</div>
</div>
</div>
<div class="md:w-3/6 mb-4 flex-1"> </div>
</div>
<button type="submit" class="sm:hidden md:flex bg-blue-500 hover:bg-blue-400 text-white font-bold py-2 px-4 border-b-4 border-blue-700 hover:border-blue-500 rounded outline-none focus:outline-none">Create</button>
</form>
Here's my script:
<script>
export default {
data() {
return {
employee: {},
designation_id: [],
designation_options: [],
}
},
methods: {
addEmployee() {
this.axios.post('/api/employees', this.employee).then(response => (this.$router.push({
name: 'employees'
}))).catch(err => console.log(err)).finally(() => this.loading = false)
},
getDesignationNames() {
this.axios.get('/api/designation').then((res) => {
this.designation_options = res.data;
}).catch(err => console.log(err))
},
},
created: function() {
this.getDesignationNames();
},
}
</script>
Any help is much appreciated.
I tried getting only the id using .map() function but it caused the vue-multiselect to not show the names and return only the first clicked result in an id format.
getDesignationNames() {
this.axios.get('/api/designation').then((res) => {
this.designation_options = res.data.map((a) => {
return a.id;
});
}).catch(err => console.log(err))
},
Use v-model.
Define v-model binding as an array.
Check this example
<script setup>
import { ref } from 'vue'
const data = ref([{id:1,name:"first"},{id:2,name:"second"},{id:3,name:"third"},{id:4,name:"forth"},{id:5,name:"fifth"}])
const selected = ref(["2","4"])
</script>
<template>
<select v-model="selected" multiple>
<option v-for="item in data" :value="item.id">{{item.name}}</option>
</select>
<div>Selected: {{selected}}</div>
</template>

Tailwindcss file input display issue

I'm running a fresh Laravel project with Jetstream installed.
I copied an example file input code snippet from tailwincss examples page and it is not displaying correctly.
This is what the example on tailwind page looks like:
And this is what it looks like on my page:
Both screenshots were taken in Brave browser.
I tried re-running npm run dev but that didn't change anything.
I'm not great with frontend so perhaps I'm missing something obvious here, but I spent some time looking for answers on similar issues and couldn't to find any.
Here's the html of the element:
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
<div class="block p-6 rounded-lg shadow-lg bg-white max-w-sm">
<form>
<div class="flex justify-center">
<div class="mb-3 w-96">
<label for="formFile" class="form-label inline-block mb-2 text-gray-700">Default file input example</label>
<input class="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none" type="file" id="formFile">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
This is what my app.css looks like:
#import 'tailwindcss/base';
#import 'tailwindcss/components';
#import 'tailwindcss/utilities';
And tailwind.config.js:
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./vendor/laravel/jetstream/**/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
],
theme: {
extend: {
fontFamily: {
sans: ['Nunito', ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [require('#tailwindcss/forms'), require('#tailwindcss/typography')],
};
My bad, I forgot to install and import tw-elements.

Can't access component method inside my blade file

I am trying to access a method inside my blade file, with #click but I am getting an error
signup-modal.vue
<template>
<div>
<div v-if="modal" class="animated fadeIn fixed z-50 pin overflow-auto bg-black flex">
<div class="animated fadeInUp fixed shadow-inner max-w-md md:relative pin-b pin-x align-top m-auto justify-end md:justify-center p-8 bg-white md:rounded w-full md:h-auto md:shadow flex flex-col">
<p class="text-xl leading-normal mb-8 text-center">
{{ __("Sign up to name to start socializing") }}
</p>
<div class="justify-center">
<form action="/auth/register" method="post">
<div class="mb-4">
<label class="block text-grey-darker text-sm font-bold mb-2" for="username">
{{ __("Name" )}}
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight" id="username" type="text" placeholder="Username">
</div>
<div class="mb-4">
<label class="block text-grey-darker text-sm font-bold mb-2" for="username">
{{ __("Email" )}}
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight" id="username" type="text" placeholder="Username">
</div>
<div class="mb-4">
<label class="block text-grey-darker text-sm font-bold mb-2" for="username">
{{ __("Password" )}}
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight" id="username" type="text" placeholder="Username">
</div>
<div class="flex items-center justify-end">
<button class="bg-teal hover:bg-teal-dark text-white font-bold py-2 px-4 rounded" type="button">
{{ __("Sign up") }}
</button>
</div>
</form>
</div>
<span #click="toggleModal" class="absolute pin-t pin-r pt-4 px-4">
<svg class="h-6 w-6 text-grey hover:text-grey-darkest" role="button" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><title>Close</title><path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"/></svg>
</span>
</div>
</div>
</div>
</template>
<script>
export default {
data: function()
{
return {
modal: false
}
},
methods: {
toggleModal: function() {
console.log("djdjd")
//this.modal = !this.modal
}
}
}
</script>
app.js
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
Vue.component('signup-modal', require('./components/signup-modal.vue'));
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app'
});
My blade file:
<div id="app">
<button class="bg-blue w-full rounded-full text-white py-2 mb-2" #click="toggleModal">
{{ __("Sign up") }}
</button>
</div>
<div>
<signup-modal></signup-modal>
</div>
</div>
As you can see in my blade file I am trying to access my components method toggleModal but I am getting an error:
app.js:36520 [Vue warn]: Property or method "toggleModal" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
(found in <Root>)
warn # app.js:36520
warnNonPresent # app.js:37826
has # app.js:37859
(anonymous) # VM374:3
Vue._render # app.js:40471
updateComponent # app.js:38715
get # app.js:39069
Watcher # app.js:39058
mountComponent # app.js:38722
Vue.$mount # app.js:44467
Vue.$mount # app.js:46866
Vue._init # app.js:40567
Vue # app.js:40656
(anonymous) # app.js:13896
__webpack_require__ # app.js:20
(anonymous) # app.js:13869
__webpack_require__ # app.js:20
(anonymous) # app.js:63
(anonymous) # app.js:66
app.js:36520 [Vue warn]: Invalid handler for event "click": got undefined
Why is this and how can I fix it?
To achieve what I wanted to do, I went the event-based way. For example, in my component, I added the method mounted, and added the following:
mounted()
{
eventHub.$on('signup-click', this.toggleModal)
}
And my main Vue method I added a simple event emitter method like so:
const app = new Vue({
el: '#app',
methods: {
generateEvent: (event) => {
eventHub.$emit(event);
}
}
});
And then in my blade file, I simple called that method like so:
<button class="bg-blue w-full rounded-full text-white py-2 mb-2" #click="generateEvent('signup-click')">
{{ __("Sign up") }}
</button>
Which simple emits the event, so my component listens to it, then calls that child method.

Resources