Vue2-medium editor styles not pulling in - vue.js

I'm trying to work with this vue2-medium-editor based on this: https://github.com/FranzSkuffka/vue-medium-editor
I'm following the instructions but Im not getting the styles to load for some reason..
So, my first step I installed
yarn add vue2-medium-editor
Then I imported my component in:
<template>
<div class="flex flex-col h-screen">
<div class="grid place-items-center">
<!-- Auth Card -->
<div
class="w-full p-12 px-6 sm:px-10 bg-white rounded-lg shadow-md lg:shadow-lg"
>
<!-- <h2
class="text-center font-semibold text-3xl lg:text-4xl text-gray-800"
>
</h2> -->
<form method="POST">
<!-- Email Input -->
<input
id="title"
type="text"
name="title"
placeholder="Title of your story"
class="text-xl block w-full py-5 px-2 mt-2 text-gray-800 appearance-none border-b-2 border-gray-100 focus:text-gray-500 focus:outline-none focus:border-gray-200"
required
/>
<editor :content='content' :options='options'></editor>
</form>
<div class="mt-5 flex justify-between">
<router-link :to="{ name: 'write-story' }">
<button class="bg-transparent hover:bg-blue-500 text-blue-700 font-bold py-2 px-4 rounded inline-flex items-center border-2 border-blue-500 hover:text-white hover:border-transparent">
<svg class="ml-2 fill-current w-4 h-4 mr-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z"/></svg>
<span>Back</span>
</button>
</router-link>
<router-link :to="{ name: 'home' }">
<button class="bg-transparent hover:bg-blue-500 text-blue-700 font-bold py-2 px-4 rounded inline-flex items-center border-2 border-blue-500 hover:text-white hover:border-transparent">
<span>Submit</span>
</button>
</router-link>
</div>
</div>
</div>
</div>
</template>
<script>
import editor from 'vue2-medium-editor'
export default {
name: "new-question",
components: { editor },
data() {
return {
content: "test",
options: {
}
}
}
}
</script>
Theres a step in the documentation to include the required css and it points to the css on the base medium editor.
So, I installed medium editor with yarn add medium-editor
Then I included the styles like this based on this github repo: https://github.com/tui2tone/vue2-medium-editor =>
<style>
#import "~/medium-editor/dist/css/medium-editor.css";
#import "~/vue2-medium-editor/src/themes/default.css";
</style>
This is within the same file. It bult successfully but it doesnt seem to work.
This is what Im getting now:
What am I missing?
Edit 1
if I do this:
<style>
#import "medium-editor/dist/css/medium-editor.css";
#import "vue2-medium-editor/src/themes/default.css";
</style>
I get this error:
Uncaught Error: Cannot find module '-!../../../../node_modules/css-loader/index.js??ref--6-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!./medium-editor/dist/css/medium-editor.css'
at webpackMissingModule (app.js:3172)
at Object../node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/containers/Story/Create.vue?vue&type=style&index=0&lang=css& (app.js:3172)
at __webpack_require__ (app.js:20)
at Object../node_modules/style-loader/index.js!./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/containers/Story/Create.vue?vue&type=style&index=0&lang=css& (app.js:21655)
at __webpack_require__ (app.js:20)
at Module../resources/js/containers/Story/Create.vue?vue&type=style&index=0&lang=css& (app.js:61170)
at __webpack_require__ (app.js:20)
at Module../resources/js/containers/Story/Create.vue (app.js:61119)
at __webpack_require__ (app.js:20)
at Module../resources/js/router.js (app.js:61283)
```

Related

I'm trying to use Dialog headless ui as a way to open a modal out of my dropdown, but everything I've tried so far hasn't worked

Apologies as I'm new to headless ui and vue in general. I have a dropdown in my parent component that works. What I'm trying to do is use dialog to open a modal upon clicking the button in the dropdown. The issue is everyway I have thought to try either causes the dropdown to flash open and close, or the dropdown to open, allow me to click the modal button, but nothing happens, no modal appears. Below is my code for the dialog modal:
<template>
<div class="flex items-center justify-center">
<button type="button" #click="openModal" class="rounded-md bg-black bg-opacity-20 px-4 py-2 text-sm font-medium text-white hover:bg-opacity-30 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
Open dialog
</button>
</div>
<TransitionRoot appear :show="isOpen" as="template">
<Dialog as="div" #close="closeModal" class="relative">
<TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0" enter-to="opacity-100" leave="duration-200 ease-in" leave-from="opacity-100" leave to="opacity-0">
<div class="fixed inset-0 bg-black bg-opacity-25" />
</TransitionChild>
<div class="fixed inset-0 overflow-y-auto">
<div
class="flex min-h-full items-center justify-center p-4 text-center"
>
<TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0 scale-95" enter-to="opacity-100 scale-100" leave="duration-200 ease-in" leave-from="opacity-100 scale-100" leave-to="opacity-0 scale-95">
<DialogPanel
class="w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all"
>
<DialogTitle
as="h3"
class="text-lg font-medium leading-6 text-gray-900"
>
Payment successful
</DialogTitle>
<div class="mt-2">
<p class="text-sm text-gray-500">
Your payment has been successfully submitted. We’ve sent you
an email with all of the details of your order.
</p>
</div>
<div class="mt-4">
<button
type="button"
class="inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
#click="closeModal"
>
Got it, thanks!
</button>
</div>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>
</TransitionRoot>
</template>
<script setup>
import { ref } from 'vue'
import {
TransitionRoot,
TransitionChild,
Dialog,
DialogPanel,
DialogTitle,
} from '#headlessui/vue'
const isOpen = ref(true)
function closeModal() {
isOpen.value = false
}
function openModal() {
isOpen.value = true
}
</script>

Flowbite modal not showing

I am trying to use flowbite components in my project but they are not working , (e.g dropdown, modal,...).
I followed the documentation but nothing works.
I'm using vuejs 3, Vite v2.9.9.
This is my main.js file:
import { createApp } from 'vue'
import App from "#/App.vue";
import router from './router/index'
import store from './state/store'
// Imported css file [TailwindCSS]
import './index.css'
// Imported flowbite
import 'flowbite';
createApp(App)
.use(router)
.use(store)
.mount('#app')
modal.vue
<template>
<!-- Modal toggle -->
<button class="block text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" type="button" data-modal-toggle="default-modal">
Toggle modal
</button>
<!-- Main modal -->
<div id="default-modal" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed right-0 left-0 top-4 z-50 justify-center items-center h-modal md:h-full md:inset-0">
<div class="relative px-4 w-full max-w-2xl h-full md:h-auto">
<!-- Modal content -->
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<!-- Modal header -->
<div class="flex justify-between items-start p-5 rounded-t border-b dark:border-gray-600">
<h3 class="text-xl font-semibold text-gray-900 lg:text-2xl dark:text-white">
Terms of Service
</h3>
<button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-toggle="default-modal">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</button>
</div>
<!-- Modal body -->
test
<!-- Modal footer -->
<div class="flex items-center p-6 space-x-2 rounded-b border-t border-gray-200 dark:border-gray-600">
<button data-modal-toggle="default-modal" type="button" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">I accept</button>
<button data-modal-toggle="default-modal" type="button" class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:ring-gray-300 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:text-white dark:hover:bg-gray-600">Decline</button>
</div>
</div>
</div>
</div>
</template>
I had the same problem at svelte.
I finally solved it:
import 'flowbite/dist/flowbite.js'
...
let modal = new Modal(document.getElementById('modalId'),{placement:'center'})
...
<button on:cllick={()=>modal.show()} >Open</button>
Okay, so what I did to make it work is to create the Modal with Javascript (check here the flowbite documentation) instead of using this data-modal-toggle="defaultModal" property defined in the html component.
Find below an example with Vue3 Single File Component. For other frameworks the solution should be similar.
<template>
<!-- Modal toggle -->
<button class="block text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" type="button" #click="toggleModal">
Toggle modal
</button>
<!-- Main modal -->
<div id="defaultModal" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 w-full md:inset-0 h-modal md:h-full justify-center items-center">
<div class="relative p-4 w-full max-w-2xl h-full md:h-auto">
<!-- Modal content -->
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<!-- Modal header -->
<div class="flex justify-between items-start p-4 rounded-t border-b dark:border-gray-600">
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">
Terms of Service
</h3>
<button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" #click="toggleModal">
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
<span class="sr-only">Close modal</span>
</button>
</div>
<!-- Modal body -->
<div class="p-6 space-y-6">
<p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.
</p>
<p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.
</p>
</div>
<!-- Modal footer -->
<div class="flex items-center p-6 space-x-2 rounded-b border-t border-gray-200 dark:border-gray-600">
<button #click="toggleModal" type="button" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">I accept</button>
<button #click="toggleModal" type="button" class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-gray-600">Decline</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return{
modal: ''
}
},
methods: {
toggleModal() {
this.modal.toggle();
}
},
mounted() {
// set the modal menu element
const targetEl = document.getElementById('defaultModal');
// options with default values
const options = {
placement: 'center',
backdropClasses: 'bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40',
onHide: () => {
console.log('modal is hidden');
},
onShow: () => {
console.log('modal is shown');
},
onToggle: () => {
console.log('modal has been toggled');
}
};
this.modal = new Modal(targetEl, options);
}
}
</script>
This took me 2 weeks to figure out, I am using Vite with Vue.
I followed the instructions here https://flowbite.com/docs/getting-started/vue/
Where it didn't state to add the script tag
<script src="./node_modules/flowbite/dist/flowbite.js"></script>
in my index.html
Which is, stated in #3 https://flowbite.com/docs/getting-started/quickstart/

Why I cant parse the {{task}} variable inside the v-for in the task-panel child?

The for loop is working properly. When I add a new task panel shows but the {{task}} variable inside the component is not showing. It must be something with the component template.
<span class="col-span-3 bg-blue-200 p-2">{{task}}</span>
I have left all the code down here maybe is something that I don't see.
Any idea? Thanks
<body>
<div id="app">
<task-input></task-input>
</div>
<script>
let app = Vue.createApp({ });
app.component(
'task-input',
{
template:
`<div class=" container grid grid-cols-4 mb-5 border-2 border-gray-600 center mt-5 mx-auto bg-gray-400 ">
<input id="taskInput" v-model="task" class="bg-white col-span-3 p-3 text-black font-bold" type="text" placeholder="What you will do next" />
<button #click="addTask()" class="text-white font-extrabold uppercase">Add new task</button>
</div>
<div class="container container mx-auto rounded-top-lg">
<div class=" bg-gray-200 border-2 border-gray-600 center column-1 container mx-auto mt-5 mx-auto rounded-top-lg">
<h1 class="font-sans text-2xl text-center text-white bg-gray-500 uppercase font-extrabold px-4 py-4">
{{title}}
</h1>
<ul class="bg-white">
<task-panel v-for="task in tasks"/>
</ul>
</div>
</div>`,
data() {
return {
title:"Here is a nice title",
task: '',
tasks: [],
}
},
components:['task-panel'],
methods:{
addTask(){
this.tasks.push(this.task);
this.task='';
console.log(this.tasks);
}
}
},
);
app.component('task-panel',{
template:
`<li class="grid bg-gray-200 mt-1">
<div class="grid grid-cols-4">
<span class="col-span-3 bg-blue-200 p-2">{{task}}</span>
<span class="col-span-1 text-center self-center uppercase font-bold">test</span>
</div>
<div class="flex justify-end bg-gray-300 p-1">
<button class="bg-blue-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">To Do</button>
<button class="bg-green-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Done</button>
<button class="bg-red-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Blocked</button>
</div>
</li>
`,
data() {
return { }
},
props: ['tasks', 'modelValue'],
computed:{
tasks:{
get(){
return this.tasks;
}
}
}
});
app.mount('#app');
</script>
</body>
The v-for is only in the scope of the parent component. The v-for's iterator prop does not get automatically passed into the task-panel.
You need to explicitly bind the iterator prop to task-panel's prop:
👇
<task-panel v-for="task in tasks" :task="task" />
Also, the prop in task-panel should have the same name. It's currently spelled tasks (with an s at the end). The last s should be removed so that it matches what the template is rendering:
// props: ['tasks', ⋯],
props: ['task', ⋯],
<script src="https://unpkg.com/vue#3.2.31/dist/vue.global.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<div id="app">
<task-input></task-input>
</div>
<script>
let app = Vue.createApp({ });
app.component(
'task-input',
{
template:
`<div class=" container grid grid-cols-4 mb-5 border-2 border-gray-600 center mt-5 mx-auto bg-gray-400 ">
<input id="taskInput" v-model="task" class="bg-white col-span-3 p-3 text-black font-bold" type="text" placeholder="What you will do next" />
<button #click="addTask()" class="text-white font-extrabold uppercase">Add new task</button>
</div>
<div class="container container mx-auto rounded-top-lg">
<div class=" bg-gray-200 border-2 border-gray-600 center column-1 container mx-auto mt-5 mx-auto rounded-top-lg">
<h1 class="font-sans text-2xl text-center text-white bg-gray-500 uppercase font-extrabold px-4 py-4">
{{title}}
</h1>
<ul class="bg-white">
<task-panel v-for="task in tasks" :task="task" />
</ul>
</div>
</div>`,
data() {
return {
title:"Here is a nice title",
task: '',
tasks: [],
}
},
components:['task-panel'],
methods:{
addTask(){
this.tasks.push(this.task);
this.task='';
console.log(this.tasks);
}
}
},
);
app.component('task-panel',{
template:
`<li class="grid bg-gray-200 mt-1">
<div class="grid grid-cols-4">
<span class="col-span-3 bg-blue-200 p-2">{{task}}</span>
<span class="col-span-1 text-center self-center uppercase font-bold">test</span>
</div>
<div class="flex justify-end bg-gray-300 p-1">
<button class="bg-blue-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">To Do</button>
<button class="bg-green-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Done</button>
<button class="bg-red-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Blocked</button>
</div>
</li>
`,
data() {
return { }
},
props: ['task', 'modelValue'],
});
app.mount('#app');
</script>

Error in mounted hook: "TypeError: Cannot read properties of undefined (reading 'required')" in vuejs

in my laravel vue application I have following vue modal to upload a document
<template>
<div>
<modal-md :identifier="identifier" :has-multiple-actions="false">
<template slot="modal_title">
<div class="flex justify-between items-center border-b border-certstyle-border px-10 py-3">
<h3 class="text-2xl leading-10 text-certstyle-titles font-bold my-2 flex items-center">
<span class="border-l-2 border-certstyle-orange inline-block h-6 mr-2"></span>
<span>Add document</span>
</h3>
<div class="h-full flex items-center cs--reveal transition-all duration-500"></div>
</div>
</template>
<template slot="modal_content">
<!--Modal content-->
<div class="bg-certstyle-background-light w-full h-full px-10 pt-8 pb-10">
<!--Name-->
<div class="mb-5 relative z-30">
<p class="text-certstyle-titles font-bold text-sm mb-1">Name</p>
<div class="h-12 relative z-10">
<input value="" name="name" id="add_name_input" type="text" class=" form-input w-full relative z-10" >
</div>
<validator identifier="addDocument" name="add_name_input" selector="id" ></validator>
</div>
<div class="flex justify-between">
<!--Completed at-->
<div class="w-1/2 mr-2">
<p class="text-certstyle-titles font-bold text-sm mb-1">Date of issue</p>
<validator-v2 identifier="addDocument" name="issued_at" :rules="{ required: { message: 'Date of issue is required.'}}">
<div class="h-12">
<cs-date-picker
id="minimumDate"
v-model="dateOfIssue"
:default-selection="true"
name="issued_at">
</cs-date-picker>
</div>
</validator-v2>
</div>
<!--Expiration date-->
<div class="w-1/2 ml-2">
<p class="text-certstyle-titles font-bold text-sm mb-1">Expiry date</p>
<validator-v2 identifier="addDocument" name="expires_at" depends-on-name="does_not_expire" :rules="{ required: { message: 'Expiry date is required.'}}">
<div class="h-12">
<cs-date-picker
id="maximumDate"
v-model="expiryDate"
:default-selection="true"
:disable="doesNotExpire"
name="expires_at">
</cs-date-picker>
</div>
</validator-v2>
</div>
</div>
<div class="flex justify-between">
<!--Completed at-->
<div class="w-1/2 mr-2">
<div class="mb-4">
<label class="inline-flex items-center focus:outline-none checkbox--container mt-2">
<input type="checkbox" name="does_not_expire" v-model="doesNotExpire">
<span class="checkbox--checkmark flex items-center justify-center ">
<svg class="icon text-certstyle-orange feather feather-check" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</span>
<span style="bottom: 4px;" class="text-certstyle-text font-normal text-sm relative">This document does not expire</span>
</label>
</div>
</div>
</div>
<!--Upload document-->
<div class="mb-1">
<dashboard-input-label identifier="document" :settings="{help: true, helpDirection: 'left'}">
Upload document
<template slot="helpText">
Maximum filesize is 5 MB.
The default allowed file extensions are: pdf, jpeg and png.
</template>
</dashboard-input-label>
<validator-v2 :identifier="identifier" name="document_file" :rules="{ required: { message: 'Document is required.'}}">
<custom-file-upload :max-upload-file-size="5" name="document_file" v-model="documentFile" ref="documentDocument"></custom-file-upload>
</validator-v2>
</div>
<!--Document number-->
<div class="mb-1">
<p class="inline-block text-certstyle-titles font-bold text-sm mb-1">Document Number</p>
<div class="relative">
<input v-model="documentNumber" name="document_number" id="add_document_number_input" :disabled="doesNotHaveDocumentNumber" type="text" class=" form-input w-full relative z-10" >
<input-annotation identifier="document_number">
Fill in your document number here.
<span class="font-bold"> Note!</span>
Use the document number mentioned on the qualification you upload. Don\'t use your WINDA-ID.
</input-annotation>
<label class="inline-flex items-center focus:outline-none checkbox--container mt-2">
<input type="checkbox" name="no_document_number" v-model="doesNotHaveDocumentNumber">
<span class="checkbox--checkmark flex items-center justify-center">
<svg class="icon text-certstyle-orange feather feather-check" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</span>
<span style="bottom: 4px;" class="text-certstyle-text font-normal text-sm relative">
This document has no document number.
</span>
</label>
</div>
</div>
</div>
</template>
<template slot="modal_actions">
<div class="flex items-center justify-between space-x-4">
<disables-submit-on-errors
:identifier="identifier"
#proceed="addNewDocument"
>
<loading-button ref="submitBtnSave" size="normal">
Save & Close
</loading-button>
</disables-submit-on-errors>
<disables-submit-on-errors
:identifier="identifier"
#proceed="storeDocumentAndAddNew"
>
<loading-button ref="submitBtn" size="normal">
Save & Add new
</loading-button>
</disables-submit-on-errors>
</div>
</template>
</modal-md>
<div class="flex flex-col fixed top-0 right-0 z-50">
<toastr-alert
v-if="message !== ''"
:message="message"
:type="type"
#hidden="resetToastrMessage">
</toastr-alert>
</div>
</div>
</template>
<script>
import ModalMd from "#/components/dashboard/sharedComponents/modals/modal-md";
import CheckboxWarning from "#/components/inputs/checkbox-warning/checkbox-warning";
import CsDataPicker from "#/components/inputs/cs-data-picker/cs-data-picker";
import HasToastrMessage from "#/Mixins/HasToastrMessage";
import Helper from "#/Support/Helper";
var url = window.location.href;
var url_split = url.split("/");
var emp_id_location = url_split.length - 2;
var emp_id = url_split[emp_id_location];
export default {
name: "add-document",
props: ['identifier', 'selectedDocumentId'],
mixins: [HasToastrMessage],
components: {CsDataPicker, CheckboxWarning, ModalMd},
data() {
return {
certificadocumentId: null,
dateOfIssue: null,
expiryDate: null,
documentNumber: null,
doesNotHaveDocumentNumber: false,
doesNotExpire: false,
documentFile: null,
doesOptIn: false,
isAddNew: false,
}
},
watch: {
doesNotHaveDocumentNumber() {
if(this.doesNotHaveDocumentNumber) {
this.documentNumber = null
}
}
},
mounted() {
if(this.selectedDocumentId) {
this.documentId = this.selectedDocumentId
}
},
methods: {
addDocument(documentId) {
this.documentId = documentId
},
storeDocumentAndAddNew() {
this.isAddNew = true
const loader = this.$refs.submitBtn;
this.storeDocument(loader)
},
addNewDocument() {
const loader = this.$refs.submitBtnSave;
this.storeDocument(loader)
},
storeDocument(loader) {
loader.startLoading();
if(!this.documentNumber && !this.doesNotHaveDocumentNumber) {
this.showToastrErrorMessage("Document number is required unless you confirm it does not apply")
loader.stopLoading();
return
}
if(!this.expiryDate && !this.doesNotExpire) {
this.showToastrErrorMessage("Expiry date is required unless you confirm it does not apply")
loader.stopLoading();
return
}
const formData = new FormData()
formData.append('emp_id', emp_id)
formData.append('issued_at', moment(this.dateOfIssue).format('DD-MM-YYYY'))
formData.append('expires_at', moment(this.expiryDate).format('DD-MM-YYYY'))
formData.append('document_number', !this.doesNotHaveDocumentNumber
? this.documentNumber
: null)
if(this.doesNotExpire) {
formData.append('does_not_expire', this.doesNotExpire)
}
formData.append('opt_in', this.doesOptIn)
formData.append('document_file',this.$refs.documentDocument.file)
this.$store.dispatch('addDocument', formData).then((data) => {
this.showToastrSuccessMessage("Document added successfully")
if(!this.isAddNew) {
eventsHub.$emit(`overlay:close:${this.identifier}`)
}
this.reset()
this.$emit('created')
}).catch((error) => {
if(Helper.isset(error.response.data) &&Helper.isset(error.response.data.errors)) {
collect(error.response.data.errors).each((error) => {
this.showToastrErrorMessage(error[0])
});
}
}).finally(() => { loader.stopLoading()})
},
reset() {
this.documentNumber = null
this.doesNotHaveDocumentNumber = false
this.doesNotExpire = false
this.documentFile = null
this.doesOptIn = false
this.isAddNew = false
},
}
}
</script>
<style scoped>
</style>
but when I run this, it gives me an console error saying, Error in mounted hook: "TypeError: Cannot read properties of undefined (reading 'required')"
I'm using the same code for another model and it works fine, and apart from the console error once when I hit the submit, it's just showing me the loading spinner, without saving the data to db
What's I'm doing wrong and how to fix it?

How to bind a image with Vue JS

I'm using Vue 3 and when I use :src in nothing appears on my site, I'm using one array with v-for. That's my code:
<BreezeDropdownLink2 v-for="(item, i) in itemsCart" :key="i" class=" hover:bg-gray-100 inline-flex w-full py-3 dark:hover:bg-gray-800">
<div class="justify-between inline-flex w-full">
<div class="rounded-md bg-gray-100 block h-12 dark:bg-vd2">
<img :src="item.image" class="w-16 h-12">
</div>
<div>
<p class="font-semibold text-gray-500 dark:text-gray-300" v-html="item.title"></p>
<span class="text-xs mb-10 text-gray-400" v-html="item.subtitle"></span>
</div>
<div class="inline-flex">
<NumberInput/>
<span class="font-semibold text-gray-500 ml-3 mt-5 dark:text-gray-300" v-html="'$'+item.price"></span>
<a #click="removeItem(item.id)" class="dark:text-gray-300"><svg data-v-c52069be="" xmlns="http://www.w3.org/2000/svg" width="14px" height="14px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="cart-item-remove cursor-pointer feather feather-x"><line data-v-c52069be="" x1="18" y1="6" x2="6" y2="18"></line><line data-v-c52069be="" x1="6" y1="6" x2="18" y2="18"></line></svg></a>
</div>
</div>
</BreezeDropdownLink2>
The itemsCart is:
itemsCart:[{id: 1, title: 'Apple Watch <br> Series 5', price: 339.99, subtitle:'By Apple', image:'../Assets/Img/product1.png'}]
Wrap the images' path in a require call. The below code works fine for me.
<template>
<div>
<div v-for="item in itemsCart" :key="item.id">
<div>
<img :src="item.image" style="width:50px;height:50px" />
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
itemsCart: [{
id: 0,
image: require('./assets/logo1.png')
},
{
id: 1,
image: require('./assets/logo2.png')
}
]
}
}
}
</script>