I am currently refactoring some old code. I want to get the data of of a vue form in order to post into my database through laravel's api. Looking at the json output I get & the controllers method everythings looks fine to me. I also tried to move the Route::post code to the regular web.php without success.
I'll post a screenshot of my schema & exact errors message (xhr cancelled).
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::get('/session', 'SessionController#index');
Route::get('/session/{id}', 'SessionController#currentRoom');
Route::post('/create', 'SessionController#create');
Route::put('/session/{id}', 'SessionController#update');
Route::delete('/session/{id}', 'SessionController#destroy');
SessionController.php
<?php
namespace App\Http\Controllers;
use App\Services\LongPolling;
use Faker\Generator;
use App\Session;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Response;
class SessionController extends Controller
{
public function create(Request $request)
{
// $session = new Session();
// $session->playerName = $faker->name;
// $session->playerId = $faker->numberBetween($min = 0, $max = 127);
// $session->roomName = $faker->name;
// $session->roomDescription = $faker->text;
// $session->overallValue = $faker->numberBetween($min = 10, $max = 70);
// $session->playerValue = $faker->randomDigitNotNull;
// $session->isAdmin = $faker->boolean ? false : true;
// $session->save();
$validator = Validator::make($request->all(), [
'roomName' => 'required|string',
'roomDescription' => 'required|string'
]);
if ($validator->fails()){
return Response::json(['errors' =>$validator->errors()], 422);
}
$session = Session::create([
'roomName' => $request('roomName'),
'roomDescription' => $request('roomDescription')
]);
return Response::json(['session' => $session,
'message' => 'success'], 200);
}
Create.vue
<template>
<div>
<form>
<strong>roomname:</strong>
<br />
<input type="text" v-model="roomName" />
<br />
<strong>description:</strong>
<br />
<input type="text" v-model="roomDescription" />
<br />
<button v-on:click="formSubmit">Click me</button>
</form>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
roomName: "",
roomDescription: ""
};
},
methods: {
formSubmit() {
axios
.post("/api/create", {
roomName: this.roomName,
roomDescription: this.roomDescription
})
.then(function(response) {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
}
};
</script>
<style>
</style>
room.blade.php
<!-- Stored in resources/views/child.blade.php -->
#extends('layouts.app')
#section('title', 'Scrumpoker')
#section('content')
<br>
<br>
<create>
</create>
#endsection
app.js
require('./bootstrap');
import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
Vue.use(Vuetify)
const opts = {}
// Vue.component('App', require('./components/App.vue').default);
// Vue.component('Card', require('./components/card.vue').default);
// Vue.component('session', require('./components/Session.vue').default);
Vue.component('create', require('./components/Create.vue').default);
const app = new Vue({
el: '#app',
vuetify: new Vuetify(),
});
Check if it's related to CORS and not related to POST?
Related
I have that error: Unknown custom element: - did you register the component correctly?
I want do likes system with Vue.js .
How i can fix this? Please help.
It seems like I wrote everything correctly ...
I have practically no experience with a tool like Vue.js, so I don’t quite understand what’s wrong
web.php
Route::post('/blog/like','BlogController#getlike');
Route::post('/blog/like/{id}','BlogController#like');
BlogController
public function getlike(Request $request)
{
$article = Article::find($request->article);
return response()->json([
'article'=>$article,
]);
}
public function like(Request $request)
{
$article = Article::find($request->article);
$value = $article->like;
$article->like = $value+1;
$article->save();
return response()->json([
'message'=>'Thanks',
]);
}
LikeComponent.vue
<template>
<div class="container">
<p id="success"></p>
<i #click.prevent="likePost" class="fa fa-thumbs-up" aria-hidden="true"></i>({{ totallike }})
</div>
</template>
<script>
export default {
props:['article'],
data(){
return {
totallike:'',
}
},
methods:{
likePost(){
axios.post('/blog/like/'+this.article,{article:this.article})
.then(response =>{
this.getlike()
$('#success').html(response.data.message)
})
.catch()
},
getlike(){
axios.post('/blog/like',{article:this.article})
.then(response =>{
console.log(response.data.article.like)
this.totallike = response.data.article.like
})
}
},
mounted() {
this.getlike()
}
}
</script>
app.js
require('./bootstrap');
window.Vue = require('vue');
Vue.component('like-component', require('./components/LikeComponent.vue').default);
const app = new Vue({
el: '#app',
});
article.blade.php
<like-component :post="{{ $article->id }}"></like-component>
i think you have to define your sub components
inside a tag which has an id app in
article.blade.php
like this :
< div id=“app”>
< like-component : post="{{ $article->id }}">
< / div>
“
and you have to run
npm run watch in your console
I have a few forms. Every of them have the same logic (validation, sending...) so, I want to create one method to control actions on my forms. For now my code is redundancy, because I have the same methods onSubmit() on every .vue file.
my HTML:
<div id="app">
<myform-one></myform-one>
<myform-two></myform-two>
</div>
my JavaScript (main.js - entry file in webpack):
import Vue from 'vue';
import Myform1 from './myform1.vue';
import Myform2 from './myform2.vue';
new Vue({
el: '#app',
components: {
myformOne: Myform1,
myformTwo: Myform2
}
});
and VUE components files:
myform1.vue:
<template>
<div>
<form #submit.prevent="onSubmit">
<input type="text" v-model="fields.fname11" />
<input type="text" v-model="fields.fname12" />
<button type="submit">submit</button>
</form>
</div>
</template>
<script>
let formfields = {
fname11: '',
fname12: ''
};
export default {
data() {
return {
fields: formfields
}
},
methods: {
onSubmit() {
// code responsible for reading, validating and sending data here
// ...
console.log(this.fields);
}
},
}
</script>
and myform2.vue:
<template>
<div>
<form #submit.prevent="onSubmit">
<input type="text" v-model="fields.fname21" />
<input type="text" v-model="fields.fname22" />
<input type="text" v-model="fields.fname23" />
<button type="submit">submit</button>
</form>
</div>
</template>
<script>
let formfields = {
fname21: '',
fname22: '',
fname23: '',
};
export default {
data() {
return {
fields: formfields
}
},
methods: {
onSubmit() {
// code responsible for reading, validating and sending data here
// ...
console.log(this.fields);
}
},
}
</script>
How can I create and use one, common method submitForm()? And where its code should be (good practice)?
Create a separate file which contains the logic:
// submitForm.js
export default function (fields) {
// code responsible for reading, validating and sending data here
// ...
}
Then use that logic inside the components
import submitForm from "../services/submitForm.js"
...
methods: {
onSubmit() {
submitForm(this.fields)
}
}
Vue3 (with Quasar for me but I'm sure it would work for any framework):
Say you have a parent which contains a number of forms <Forms />:
First create a composable function like so useForms.js:
import { ref } from 'vue'
const forms = ref([])
export function useForms(){
const checkForms = () => {
forms.value.forEach((form) => form.validate()
}
const addFormToFormsArray = (form) => {
forms.value.push(form)
}
return { forms, addFormToFormsArray, checkForms }
}
Then import it into <Forms />:
<template>
<Form />
<Form />
<Form />
<button #click="checkForms">Check Form</button>
</template>
<script setup>
import { useForms } from '../useForms';
const { checkForms } = useForms()
</script>
Finally, inside the <Form />:
<template>
<form ref="form">
.../stuff
</form>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useForms } from '../useForms';
const form = ref(null)
onMounted(() => {
addFormToFormsArray(form.value)
})
const { checkForms, addFormToFormsArray } = useForms()
</script>
When performing the check function in the parent, it should go through each form and check for any issues.
There are some options. My favorite is creating a mixin vue docs mixins
export const form_functionality = {
methods: {
on_submit() {
//logic of submit
},
//here we can have other reusable methods
}
}
Then in your components use that mixin as follow:
import { form_functionality } from 'path_of_mixin'
export default {
mixins: [form_functionality]
}
In the end, what mixins has (created, methods, data etc) will be merged to the component
which uses that mixin.
So, practically you can access the mixin method like this.on_submit()
I'm trying to use the vue2-editor with my project but I can't get it to work. It says: "Failed to mount component: template or render function not defined." When I try to use import instead of require I get the error message: "Couldn't find a declaration file for module...". I've set up a types.d.ts to solve this but still doesn't work.
Any help is appreciated!
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import PopupImages from "./PopupImages.vue";
import VModal from 'vue-js-modal';
import UploadFile from "./UploadFile.vue";
import axios from 'axios';
import router from "../router";
import store from "../store";
const VueEditor = require('vue2-editor').default;
class Route {
name: string;
description: string;
constructor(){
this.name = "";
this.description = "";
console.log(VueEditor);
}
}
Vue.use(VModal, { dynamic: true });
#Component({
components: {
VModal,
UploadFile,
VueEditor
}
})
export default class NewRoute extends Vue {
route: Route;
content: any;
constructor(){
super();
this.route = new Route();
this.content = '<h1> Testing </h1>';
}
sendData(){
let newRoute = {
name : this.route.name,
description : this.route.description
}
console.log(newRoute);
axios.get('')
.then((response) => {
console.log(response);
})
.catch((error: any) => {
console.log(error);
})
}
}
</script>
<template>
<div id="newRoute">
<vue-editor v-model="content"></vue-editor>
<modal name="addRoute" :width="400" :height="450">
<form>
<h1>Insert new trail</h1>
<p>
<label for ="route">Route name</label>
<input type = "text" id="route" name ="route" v-model="route.name" size = "30" maxlength ="30" required/>
</p>
<p>
<label for = "description">Description</label>
<textarea id= "description" name = "description" v-model="route.description">
</textarea>
</p>
<p>Upload JSON or GPX file</p>
<UploadFile></UploadFile>
<br/>
<button type="submit" #click ="sendData">Submit</button>
</form>
</modal>
</div>
</template>
ArticleController
<?php
namespace App\Http\Controllers\Articles;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\ArticleCategory;
use App\Models\Article;
use App\Models\ArticleTranslation;
use Lang;
class ArticleController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$locale = Lang::locale();
// $locale = Lang::getLocale();
$articles = Article::withTranslations($locale)->get();
return $articles;
}
Article.vue component
<template>
<div>
<div v-for="article in articles" :key="article.articles">
<div v-for="translation in article.translations">
<h4>{{ translation.title }}</h4>
{{ translation.subtitle }}
{{ translation.content }}
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import { mapGetters } from 'vuex'
export default {
layout: 'basic',
computed: mapGetters({
locale: 'lang/locale'
}),
data: function () {
return {
articles: []
}
},
watch: {
locale: 'lang/locale'
},
mounted() {
console.log(this.locale)
this.getArticles ()
},
methods: {
getArticles() {
var app = this;
axios.get('/api/articles')
.then(response => {
// JSON responses are automatically parsed.
this.articles = response.data
})
.catch(e => {
this.errors.push(e)
})
}
}
}
</script>
api.php
Route::group(['middleware' => 'guest:api'], function () {
Route::post('login', 'Auth\LoginController#login');
Route::post('register', 'Auth\RegisterController#register');
Route::post('password/email', 'Auth\ForgotPasswordController#sendResetLinkEmail');
Route::post('password/reset', 'Auth\ResetPasswordController#reset');
Route::resource('articles', 'Articles\ArticleController');
});
I'm detecting the locale on the frontend and using it in the controller to fetch articles for that locale. This works only when i refresh the page everytime.
I'm using this template which has a navbar with language switcher
How to watch the locale and fetch the articles again in order to refresh the dom without refreshing the page.
<script>
import axios from 'axios'
import { mapGetters } from 'vuex'
export default {
layout: 'basic',
computed: mapGetters({
locale: 'lang/locale'
}),
data: function () {
return {
articles: []
}
},
watch: {
locale: function (newLocale, oldLocale) {
this.getArticles()
}
},
mounted() {
console.log(this.locale)
this.getArticles ()
},
methods: {
getArticles() {
var app = this;
axios.get('/api/articles')
.then(response => {
// JSON responses are automatically parsed.
this.articles = response.data
})
.catch(e => {
this.errors.push(e)
})
}
}
}
</script>
Tried this and it worked!
I have the following app.js file as main Vue component.
import './bootstrap';
import router from './routes';
new Vue({
el: '#app',
router: router
});
My bootstrap.js is the following
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
// Global variable for API access
window.hostname = 'https://city.molotex.ru/cgi-bin/citygate.py?';
// Global variable for VueJS
window.Vue = Vue;
// Vue router
Vue.use(VueRouter);
//Vue Resource
var VueResource = require('vue-resource');
Vue.use(VueResource);
// axios
window.axios = axios;
window._ = require('lodash');
try {
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
} catch (e) {}
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = window.Laravel.csrfToken;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
My Login Vue is the following:
<template>
<form class="form-horizontal" role="form" method="POST" action="login">
<div class="form-group">
<label for="email" class="col-md-4 control-label">Логин (email)</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control" name="email" v-model="email">
</div>
</div>
<div class="form-group">
<label for="password" class="col-md-4">Пароль</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control" name="password" v-model="password">
</div>
</div>
<div class="form-group">
<div class="col-md-8 col-md-offset-4">
<button type="button" v-on:click="login" class="btn btn-primary">
Login
</button>
</div>
</div>
</form>
</template>
<script>
export default {
mounted() {
console.log('Component is mounted.');
},
data() {
return {
email: '',
password: '',
response_key: ''
}
},
methods: {
login() {
let self = this;
axios.post('/login', {
email: this.email,
password: this.password
}).then(function (response) {
self.response_key = response.data.result;
this.$router.push('/user_main_page');
console.log(response);
}).catch(function (error) {
console.log(error);
});
}
}
}
</script>
And my routes file is the following:
import VueRouter from 'vue-router';
let routes = [
{
path: '/',
component: require('./components/Example.vue')
},
{
path: '/about',
component: require('./components/About.vue')
},
{
path: '/login',
component: require('./components/Login.vue')
},
{
path:'/user_main_page',
component: require('./components/UserMainPage.vue')
}
];
export default new VueRouter({
routes
});
But when I have the following error:
TypeError: Cannot read property '$router' of undefined
at app.js:4341
at
I tried different types of routing such as:
using global route variable as:
window.router = VueRouter;
or importing VueRouter inside the component, but neither of this approaches helped. What am I doing wrong, how to make Router work.
I'm assuming that the codes that you posted are all that there is and the error you are encountering can be traced down at this block at the Login Vue component, where you refer to the $router variable.
axios.post('/login', {
email: this.email,
password: this.password
}).then(function (response) {
self.response_key = response.data.result;
this.$router.push('/user_main_page');
console.log(response);
}).catch(function (error) {
console.log(error);
});
Although this.$router is the correct syntax for accessing the router dependency, calling it inside a callback function, using the regular function expression, creates a new binding to the "this" object instead of the Vue object itself.
You have two options to solve this:
Store the object reference into a variable vm outside the callback function.
const vm = this;
axios.post('/login', {
email: this.email,
password: this.password
}).then(function (response) {
self.response_key = response.data.result;
vm.$router.push('/user_main_page');
console.log(response);
}).catch(function (error) {
console.log(error);
});
Use the arrow syntax when creating the function such that your reference to "this" is not overwritten. (Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
axios.post('/login', {
email: this.email,
password: this.password
}).then(response => {
self.response_key = response.data.result;
this.$router.push('/user_main_page');
console.log(response);
}).catch(error => {
console.log(error);
});
1:
then(function (response) {
self.response_key = response.data.result;
this.$router.push('/user_main_page');
console.log(response);
}.bind(this))
2:
In ES6:
then((response) => {
self.response_key = response.data.result;
this.$router.push('/user_main_page');
console.log(response);
})
In Login Vue file, change code
this.$router.push('/user_main_page');
to
self.$router.push('/user_main_page');
you have already defined
let self = this;
so using:
self.$router.push('/user_main_page');
will work.