I am currently working on developing a simple blog application using Laravel with Vue.js. I have successfully created custom components, registered them in my app.js file, and referenced them in the views by their component names. However, upon loading the app, I encountered the following error:
[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
(found in )
Could someone help me identify what might be causing this issue? Here is the code snippet in question:
CreatePost.vue:
<template>
<div class="card mt-4" :key="componentKey">
<div class="card-header">New Post</div>
<div class="card-body">
<div v-if="status_msg" :class="{ 'alert-success': status, 'alert-danger': !status }" class="alert" role="alert">
{{ status_msg }}
</div>
<form>
<div class="form-group">
<label for="exampleFormControlInput1">Title</label>
<input v-model="title" type="text" class="form-control" id="title" placeholder="Post Title" required />
</div>
<div class="form-group">
<label for="exampleFormControlTextarea1">Post Content</label>
<textarea v-model="post_body" class="form-control" id="post-content" rows="3" required></textarea>
</div>
<div class>
<el-upload action="https://jsonplaceholder.typicode.com/posts/" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-change="updateImageList" :auto-upload="false">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt />
</el-dialog>
</div>
</form>
</div>
<div class="card-footer">
<button type="button" @click="createPost" class="btn btn-success">{{ isCreatingPost ? "Posting..." : "Create Post" }}</button>
</div>
</div>
</template>
<style>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
<script>
import { setTimeout } from "timers";
import { mapState, mapActions } from "vuex";
export default {
name: "create-post",
props: ["posts"],
data() {
return {
dialogImageUrl: "",
dialogVisible: false,
imageList: [],
status_msg: "",
status: "",
isCreatingPost: false,
title: "",
post_body: "",
componentKey: 0
};
},
computed: {},
mounted() {},
methods: {
...mapActions(["getAllPosts"]),
updateImageList(file) {
this.imageList.push(file.raw);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.imageList.push(file);
this.dialogVisible = true;
},
createPost(e) {
e.preventDefault();
if (!this.validateForm()) {
return false;
}
const that = this;
this.isCreatingPost = true;
let formData = new FormData();
formData.append("title", this.title);
formData.append("post_body", this.post_body);
$.each(this.imageList, function(key, image) {
formData.append(`images[${key}]`, image);
});
api.post("/post/create_post", formData, { headers: { "Content-Type": "multipart/form-data" }})
.then(res => {
this.title = this.post_body = "";
this.status = true;
this.showNotification("Post Successfully Created");
this.isCreatingPost = false;
this.imageList = [];
/* "that", defined above, used here instead of "this" to avoid conflict issues */
that.getAllPosts();
that.componentKey += 1;
});
},
validateForm() {
if (!this.title) {
this.status = false;
this.showNotification("Post title cannot be empty");
return false;
}
if (!this.post_body) {
this.status = false;
this.showNotification("Post body cannot be empty");
return false;
}
return true;
},
showNotification(message) {
this.status_msg = message;
setTimeout(() => {
this.status_msg = "";
}, 3000);
}
}
};
</script>
app.js:
/**
* Initially, we will include all JavaScript dependencies for this project such as Vue and other libraries. This serves as a solid foundation when
* creating sophisticated, high-performance web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
import store from './store/index';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
/**
* The code below can automatically register your Vue components. It scans this directory recursively for Vue
* components and registers them based on their "basename".
*
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
// const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
Vue.component('all-posts', require('./components/AllPosts.vue').default);
Vue.component('create-post', require('./components/CreatePost.vue').default);
/**
* Next, we establish a new Vue application instance and attach it to the page. From there, additional components can be added
* or the JavaScript scaffolding can be customized to match your specific requirements.
*/
const app = new Vue({
store,
el: '#app',
});
posts.blade.php:
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-6">
<create-post />
</div>
<div class="col-md-6">
<all-post />
</div>
</div>
</div>
@endsection