I am new in Vue.js. I want to understand on using component. I tried to import my component to another component but it failed. I am using Laravel 5.8. Below are the error that I received.
Module not found: Error: Can't resolve
'./components/modalAlert.vue
Below are my codes.
app.js
Vue.component('form-to-do', require('./components/formToDo.vue').default);
Vue.component('modal-alert', require('./components/modalAlert.vue').default);
const app = new Vue({
el: '#app',
});
formToDo.Vue
<template>
// form
<modal-alert></modal-alert>
</template>
<script>
import modalAlert from './components/modalAlert.vue';
export default {
components: {
'modal-alert': modalAlert
},
data() {
return {
setErrors: [],
tasks: [],
task: {
id: '',
name: '',
completed: '',
date_completed: ''
},
result: '',
input: {
name: ''
}
};
},
}
</script>
modalAlert.vue
<template>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Test
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['id'],
data() {
return {
}
},
mounted() {
console.log('Component mounted.')
}
}
</script>
Your components are probably in the same folder. In your component formToDo.vue:
Change this:
import modalAlert from './components/modalAlert.vue';
To this:
import modalAlert from './modalAlert.vue';
To solve the other issue, as #ambianBeing suggested, your component formToDo.vue must have root element to be able to add child component inside it.
<template>
<div> <!-- this is the root -->
<modal-alert></modal-alert>
</div>
</template>
Related
I am trying to use Vue3 (Vite) and Bootstrap 5 to create a modal that is called by code. However, when opening the modal from its parent, an error is thrown.
I have bootstrap installed and included:
import bootstrap (main.js)
import bootstrap/dist/js/bootstrap does not change anything.
I have created a simple modal that listens for a prop and then opens the modal.
When I open it, the error appears:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'backdrop')
<template>
<div class="modal" tabindex="-1" id="errModal" aria-labelledby="ErrorModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Error {{ this.occurred }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="ErrorModalLabel"></button>
</div>
<div class="modal-body">
<p>{{ this.error_message }}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
</template>
<script>
import { Modal } from "bootstrap"
export default {
props: {
occurred: String,
error_message: String,
show: Boolean,
},
components: {
myModal: null
},
data() {
return {
}
},
methods: {
},
mounted() {
this.myModal = new Modal(document.getElementById('errModal'))
},
watch: {
show: function (newVal, oldVal) { // watch it
this.cam_prop = newVal.properties
},
}
};
</script>
Calling from Parent:
<RegIdentErrorModalVue id="#ErrModal" :show="this.error" :occurred="'Identification'" :error_message="this.error_text">
</RegIdentErrorModalVue>
Creating the Modal with new bootstrap.Modal does not work (bootstrap not defined)
I think the error is importing, but the styling works, could it be Vite?
my comments object's state is fine
but my saveComment() function can't find comments' post_id and makes error ->>
CommentList.vue?6c27:107 Uncaught TypeError: Cannot read properties of undefined (reading 'post_id')
at HTMLButtonElement.eval (CommentList.vue?6c27:107)
at HTMLButtonElement.dispatch (jquery.js?1157:5430)
at HTMLButtonElement.elemData.handle (jquery.js?1157:5234)
how can i use props in vue?? i want to use props like data..
<div>
{{ comments }}
<button #click="getComments()" class="btn btn-primary">
open comments
</button>
<!-- Button trigger modal -->
<button
#click="openWriteComment()"
type="button"
class="btn btn-primary"
id="openModalBtn"
data-bs-toggle="modal"
data-bs-target="#exampleModal"
>
Write Comment
</button>
<!-- Modal -->
<div
class="modal fade"
id="modalBox"
tabindex="-1"
aria-labelledby="exampleModalLabel"
aria-hidden="true"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
<input type="text" id="commentBody" value="type your comment" />
</div>
<div class="modal-footer">
<button #click="saveComment()" class="btn btn-primary" id="saveBtn">
Save changes
</button>
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
</div>
</div>
</div>
</div>
<comment-item
v-for="(comment, index) in commentlist"
:key="index"
:comment="comment"
></comment-item>
</div>
</template>
<script>
import CommentItem from "./CommentItem.vue";
export default {
components: { CommentItem },
data() {
return {
commentlist: [],
};
},
created() {
this.getComments();
},
props: ["post", "loginuser", "comments"],
methods: {
getComments() {
axios
.get("/commentlist")
.then((res) => {
console.log(res.data);
this.commentlist = this.comments;
console.log(this.commentlist);
})
.catch((err) => {
console.log(err);
});
},
openWriteComment() {
$("#openModalBtn").on("click", function () {
$("#modalBox").modal("show");
});
},
saveComment() {
$("#saveBtn").on("click", function () {
console.log(document.getElementById("commentBody").value);
axios
.post("/commentSave/" + this.comments.post_id, {
comment: document.getElementById("commentBody").value,
})
.then((res) => {
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
});
},
},
};
</script>```
I think I sopotted your error.
Your error:
saveComment() {
$("#saveBtn").on("click", function () { // This callback is a regular function
console.log(document.getElementById("commentBody").value);
axios
// when you get here 'this' context from Vue is lost
// "this.comments" doesn't exist in the context of this function.
.post("/commentSave/" + this.comments.post_id, {
comment: document.getElementById("commentBody").value,
})
Solution:
saveComment() {
$('#saveBtn').on('click', () => { // convert this to arrow function.
console.log(document.getElementById('commentBody').value)
axios
.post('/commentSave/' + this.comments.post_id, {
comment: document.getElementById('commentBody').value
})
In my Vue app I have a main component where I have the following router views:
<router-view></router-view>
<div class="modal">
<router-view name="modal"></router-view>
</div>
In multiple places I want to open specific router-links to open a modal. To reach this I made a route the following way:
{
path: '/visitors/login',
props: true,
components: {
modal: ModalLogin
},
meta: {
modal: true,
}
},
This way the specific modal gets loaded into the modal router-view. The only thing is that the default router-view gets cleared when I do this. Is there a way to prevent the default router-view from changing, so it will keep is active page, and only fill the modal router-view?
As a follow up to my comment, instead of trying to map a modal to a route, I built this sample implementation with Vue 2 and the CLI.
For the routes / or /visitors, the Visitors component/page will be rendered, and you can click the 'Login' button to open the modal.
If you enter the route /visitors/login in the browser address bar, the modal will open over the Visitors page.
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import Visitors from '../Visitors.vue'
const routes = [
{
path: '/',
redirect: 'visitors'
},
{
name: 'visitors',
path: '/visitors/:modal?',
component: Visitors,
props: true
}
]
export default new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
App.vue
<template>
<div id="app" class="container">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
data() {
return {
}
}
}
</script>
Visitors.vue
<template>
<div class="visitors">
<h4>Visitors</h4>
<div class="row">
<div class="col-md-4">
<button class="btn btn-secondary" #click="showModal">Login</button>
</div>
</div>
<login-modal v-if="displayLogin" #login-event="login" #close-modal-event="hideModal" />
</div>
</template>
<script>
import LoginModal from './LoginModal.vue';
export default {
components: {
LoginModal
},
props: {
modal: {
type: String,
required: false
}
},
data() {
return {
displayLogin: false
}
},
methods: {
showModal() {
this.displayLogin = true;
},
hideModal() {
this.displayLogin = false;
},
login(user) {
this.hideModal();
// Process login
console.log(user);
}
},
created() {
if (this.$route.params.modal) {
if (this.$route.params.modal === 'login') {
this.displayLogin = true;
}
}
}
}
</script>
LoginModal.vue
<template>
<div class="login-modal">
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Login</h5>
<button type="button" #click="closeModal">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form #submit.prevent="login">
<div class="form-group">
<label for="username">User Name</label>
<input type="email" class="form-control" id="username" v-model="user.name">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" v-model="user.password">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" #click="login">Login</button>
<button type="button" class="btn btn-secondary" #click="closeModal">Close</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
user: {
name: '',
password: ''
}
}
},
methods: {
closeModal() {
this.$emit('close-modal-event');
},
login() {
this.$emit('login-event', this.user)
}
}
}
</script>
<style scoped>
/* Override default value of 'none' */
.modal {
display: block;
}
</style>
I have a component where I'm handling all the errors / error message. I debug it and successfully passed the error string in variable, but I can't display in template
Here is my code
export class ErrorHandlerComponent {
get ComponentName() {
return "error-handler";
}
constructor() {
this.errorMessage = ko.observable();
if (!ko.components.isRegistered(this.ComponentName)) {
ko.components.register(this.ComponentName, {
viewModel: ErrorHandlerComponent,
template:
`
<div class="modal fade" id="modalError" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" data-backdrop='static' data-keyboard='false'>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel"><i class="fa fa-exclamation-circle"></i> Error occurred</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
</button>
</div>
<div class="modal-body" data-bind="text: errorMessage">
</div>
<div class="modal-footer modal-btn">
<button type="button" class="btn btn-warning btn-lg" data-bind="click: ClickRefreshPage">Refresh</button>
</div>
</div>
</div>
</div>
`
});
}
}
Show(msg) {
this.errorMessage(msg);
$('#modalError').modal('show');
}
Close() {
$('#modalError').modal('hide');
$(".modal-backdrop").remove();
$("body").css({ 'padding-right': '0px' });
}
ClickRefreshPage() {
alert('refreshing...');
}
}
when I call Show function, the parameter is passed and this.errorMessage() had a value, but in text: errorMessage I can't display it.
john is right though, this refers to the ErrorHandlerComponent at the time of components.register and that is obviously always empty.
What I'm missing is an observable parameter passed through from the parent via the components' param property. if you put that in your constructor, ko will link everything through and passing a validationmessage to the component will be displayed.
https://jsfiddle.net/ezw9q02x/1/
I am getting the error "Make sure that this property is reactive, either in the data option, or for class" in vuejs.
I created a laravel application and wanted to make the user management work in real-time so I deplyed vuejs with the root template being Users.vue. Additionally I created a separate component called AddUserModal for the modal popup and used it in the root template as The popup displays correctly and rendered well in the browser. The problem started when I tried to do model binding and for that, am using vform for the server side validation. After declaring the data in Users.vue(root) I proceeded to AddUserModal to set up my form with v-model but this throws back an error. The code is below
This is the script from Users.vue
<script>
export default {
data() {
return {
form : new Form({
name : '',
email : '',
role : '',
description : '',
password : ''
})
}
},
mounted() {
console.log('Component mounted.')
}
}
AddUserModal
<div class="container">
<div class="modal fade" id="addUserModal" tabindex="-1" role="dialog" aria-labelledby="addUserModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<form>
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addUserModalLabel">Add User</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<input v-model="form.name" type="text" name="name"
class="form-control" :class="{ 'is-invalid': form.errors.has('name') }">
<has-error :form="form" field="name"></has-error>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-danger" data-dismiss="modal"><i class="fas fa-times-circle"></i></button>
<button type="button" class="btn btn-sm btn-success"><i class="fas fa-save"></i></button>
</div>
</div>
</form>
</div>
</div>
</div>
app.js
require('./bootstrap');
//vue
vue
window.Vue = require('vue');
//imports
import VueRouter from 'vue-router'
import { Form, HasError, AlertError } from 'vform'
//vue Router
vue router
Vue.use(VueRouter)
//Vform
window.Form = Form
Vue.component(HasError.name, HasError)
Vue.component(AlertError.name, AlertError)
let routes = [
{ path: '/users', component: require('./components/Users.vue')}
]
const router = new VueRouter({
mode: 'history',
routes
})
Vue.component('example-component', require('./components/AddUserModal.vue'));
const app = new Vue({
el: '#app',
router
});
When I placed the scripts in AddUserModal, the model binding works fine but throws up an error when placed in the Users.vue
This is the browser console output
app.js:37116 [Vue warn]: Property or method "form" 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.