How to use vue router inside axios request - javascript

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.

Related

I cant get individual documents from a database using id?

I've been using Vue with a firebase database for my data I think where I'm going wrong is with the routing but I'm not 100% sure. what I've done so far is I've got a database with peoples profiles in it and I've use v-for to display all of these profiles out on the home page and now I'm trying to get it so that when you click on their individual profile you got to another page which will then fill the profile out according to a template using the id of the profile you've just clicked to fill in the page with that documents data.
What I know isn't happening is it isn't getting an id of a document because it should console log but it doesn't and it just displays the error message I made that it can't find the profile, as I said I'm pretty sure it is something that has to be done to the router, but I am not sure what to do and how to do it?
Here is the code below of the home page where you first see the profiles and select them.
<script>
import getPremium from "../Composables/getPremium.js";
import getStandard from "../Composables/getStandard.js";
import getBasic from "../Composables/getBasic.js";
const counter = useCounterStore();
const profile = useProfileStore();
const profileA = profilesbasic();
const {Premium, error, load} = getPremium();
load();
const {Standard, error2, load2} = getStandard();
load2();
const {Basic, error3, load3} = getBasic();
load3();
</script>
<template>
<div v-for =" Basics in Basic" :key="Basics.id" >
<router-link to="/Samplebasic">
<div class= "hover:scale-105 transition ease-in-out duration-300 bg-neutral-800 hover:bg-neutral-900 active:bg-neutral-900 text-neutral-400 font-bold rounded-xl">
<br>
<p>{{ Basics.name }}</p>
<img src="../assets/Sample pic.png" class="object-contain ml-6 w-60 h-80 transition ease-in-out duration-300">
<div class="grid grid-cols-2 grid-rows-fit text-left ml-6">
<p>Age:</p>
<p>{{ Basics.Age }}</p>
<p>Location:</p>
<p>{{ Basics.Location }}</p>
<p>Phone:</p>
<p>{{ Basics.Phone }}</p>
</div><br>
</div>
</router-link>
</div>
</template>
This is the JavaScript file that gets the documents from the database and is then imported to the home page.
import { projectFirestore } from "../Firebase/Config";
import { ref } from "vue"
const getBasic = () => {
const Basic = ref([])
const error3 = ref(null)
const load3 = async () => {
try{
const res = await projectFirestore.collection('Basic').get()
Basic.value = res.docs.map(doc => {
console.log(doc.data())
return {...doc.data(), id: doc.id}
})
}
catch (err){
error3.value = err.message
console.log(error3.value)
}
}
return { Basic, error3, load3}
}
export default getBasic
This is the profile page which I'm trying to get filled with the individuals' details depending on the profile you clicked on.
import getPBasic from "../Composables/getPBasic";
const {PBasic, error, load} = getPBasic();
load();
export default {
name: "Slider",
mounted(){
this.PBasic = PBasic;
this.error = error;
this.load = load;
},
data() {
return {
error: {},
PBasic: {},
load: {},
images: [
"/src/assets/sample-1.jpg",
"/src/assets/sample-2.jpg",
"/src/assets/sample-3.jpg",
"/src/assets/sample-4.jpg"
],
currentIndex: 0
};
},
methods: {
next: function() {
this.currentIndex += 1;
},
prev: function() {
this.currentIndex -= 1;
}
},
computed: {
currentImg: function() {
return this.images[Math.abs(this.currentIndex) % this.images.length];
}
}
};
</script>
<template>
<div v-if="error">{{ error }}</div>
<div v-if="PBasic" class="PBasic">
<br><br>
<p class="text-5xl text-red-700 font-serif">{{ PBasic.name }}</p><br><br>
<p>{{ Pbasic.age }}</p>
</template>
This is the javascript file that should get me that individual document based on the id of profile user clicked on.
import { projectFirestore } from "../Firebase/Config";
import { ref } from "vue"
const getPBasic = (id) => {
const PBasic = ref(null)
const error = ref(null)
const load = async () => {
try{
let res = await projectFirestore.collection('Basic').doc(id).get()
if(!res.exists) {
throw Error('That Profile no longer exists')
}
PBasic.value = {...res.data(), id: res.id}
console.log(PBasic.value)
}
catch (err){
error.value = err.message
console.log(error.value)
}
}
return { PBasic, error, load}
}
export default getPBasic
And this is the router of the sample basic as I have it now, I'm pretty sure it's the problem I just don't know how to fix it or what to do to the other files once I've done it?
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../components/Home.vue'
import Login from '../components/Login.vue'
import Advertise from '../components/Advertise.vue'
import Samplebasic from '../components/Samplebasic.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/Login',
name: 'Login',
component: Login,
},
{
path: '/Advertise',
name: 'Advertise',
component: Advertise,
}
{
path: '/Samplebasic',
name: 'Samplebasic',
component: Samplebasic,
}
]
const router = createRouter({
history: createWebHistory(),
routes,
})
export default router;
```
I hope I didn't go on for too long but that's the problem I'm having, and I don't know how to go about any help would be greatly appreciated, Thanks.

Vue use route params for axios get request

So I'm building my first vue project and I've been trying to pass route parameters to an axios get request and it's not working.
this is the code for the page, it gets rendered after the user clicks on a dynamic link in a table of tests
<template>
<v-app>
<app-navbar />
<v-main>
<h3>test {{$route.params.name}}, {{$route.query.status}},{{$route.query.tag}}</h3>
<h3>{{items}}</h3>
</v-main>
</v-app>
</template>
<script>
import appNavbar from '../../../components/appNavbar.vue';
import axios from "axios";
export default {
components : {appNavbar},
name: "App",
data() {
return {
items: [],
};
},
async created() {
try {
const res = await axios.get(`http://localhost:3004/tests`,{ params: $route.params.name });
this.items = res.data;
} catch (error) {
console.log(error);
}
},
};
</script>
<style lang="scss" scoped>
</style>
how can i pass the route params to the axios get function ?
This should be this.$route.params.name inside the script.
const res = await axios.get(`http://localhost:3004/tests`,{ params: this.$route.params.name });
Router.js const routes = [ { path: 'path/:name', name: 'Name', component: ComponentName, } ]
I used #Nitheesh solution I just had to specify the parameter name and it worked perfectly
Solution:
const res = await axios.get(`http://localhost:3004/tests`,{ params: {name:this.$route.params.name} });

Ember Octane Upgrade How to pass values from component to controller

Upgrade from Ember <3.15 to >=3.15. How do I pass form values from a controller into a component?
I cannot begin to explain the number of diagnostic combinations attempted and their corresponding errors received. So, I figure it best to ask how it should be done correctly? Is Glimmer involved?
A simple example: pass a change password from old password to both a new and confirm password via a component to a controller. In the Component, I keep getting onsubmit() is not a function error.
Code example:
User Input Form
ChangePasswordForm.hbs
<div class="middle-box text-center loginscreen animated fadeInDown">
<div>
<h3>Change Password</h3>
<form class="m-t" role="form" {{on "submit" this.changePassword}}>
{{#each errors as |error|}}
<div class="error-alert">{{error.detail}}</div>
{{/each}}
<div class="form-group">
{{input type="password" class="form-control" placeholder="Old Password" value=oldPassword required="true"}}
</div>
<div class="form-group">
{{input type="password" class="form-control" placeholder="New Password" value=newPassword required="true"}}
</div>
<div class="form-group">
{{input type="password" class="form-control" placeholder="Confirm Password" value=confirmPassword required="true"}}
</div>
<div>
<button type="submit" class="btn btn-primary block full-width m-b">Submit</button>
</div>
</form>
</div>
</div>
Template Component
ChangePassword.hbs
<Clients::ChangePasswordForm #chgpwd={{this.model}} {{on "submit" this.changePassword}} #errors={{this.errors}} />
Component
ChangePasswordForm.js
import Component from '#glimmer/component';
import { tracked } from '#glimmer/tracking';
import { action } from '#ember/object';
export default class ChangePasswordForm extends Component {
#tracked oldPassword;
#tracked newPassword;
#tracked confirmPassword;
#tracked errors = [];
#action
changePassword(ev) {
// Prevent the form's default action.
ev.preventDefault();
this.oldPassword = ev.oldPassword;
this.newPassword = ev.newPassword;
this.confirmPassword = ev.confirmPassword;
// Call the form's onsubmit method and pass in the component's values.
this.onsubmit({
oldPassword: this.oldPassword,
newPassword: this.newPassword,
confirmPassword: this.confirmPassword
});
}
}
Controller
ChangePassword.js
import Controller from '#ember/controller';
import { inject as service } from '#ember/service';
import { action } from '#ember/object';
export default class ChangePassword extends Controller {
#service ajax
#service session
#action
changePassword(attrs) {
if(attrs.newPassword == attrs.oldPassword)
{
this.set('errors', [{
detail: "The old password and new password are the same. The password was not changed.",
status: 1003,
title: 'Change Password Failed'
}]);
}
else if(attrs.newPassword != attrs.confirmPassword)
{
this.set('errors', [{
detail: "The new password and confirm password must be the same value. The password was not changed.",
status: 1003,
title: 'Change Password Failed'
}]);
}
else
{
let token = this.get('session.data.authenticated.token');
this.ajax.request(this.store.adapterFor('application').get('host') + "/clients/change-password", {
method: 'POST',
data: JSON.stringify({
data: {
attributes: {
"old-password" : attrs.oldPassword,
"new-password" : attrs.newPassword,
"confirm-password" : attrs.confirmPassword
},
type: 'change-passwords'
}
}),
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/vnd.api+json',
'Accept': 'application/vnd.api+json'
}
})
.then(() => {
// Transistion to the change-password-success route.
this.transitionToRoute('clients.change-password-success');
})
.catch((ex) => {
// Set the errors property to the errors held in the ex.payload.errors. This will allow the errors to be shown in the UI.
this.set('errors', ex.payload.errors);
});
}
}
}
Model
ChangePassword.js
import Route from '#ember/routing/route';
import AbcAuthenticatedRouteMixin from '../../mixins/abc-authenticated-route-mixin';
export default Route.extend(AbcAuthenticatedRouteMixin, {
//export default class ChangePasswordRoute extends Route(AbcAuthenticatedRouteMixin, {
model() {
return {
oldPassword: '',
newPassword: '',
confirmPassword: ''
};
},
})
There is no onsubmit method in #glimmer/component, so you cannot call this.onsubmit inside an action in the component.
First, you need to pass the action created in your controller to your component. This can be done like this:
<ChangePasswordForm #chgpwd={{this.model}} #changePassword={{action 'changePassword'}} />
Remember, you cannot pass data up any more in a glimmer component, you need to use an action since everything is one way binding.
Second, you need to call this action inside your glimmer component:
this.args.changePassword({
oldPassword: this.oldPassword,
newPassword: this.newPassword,
confirmPassword: this.confirmPassword
});
I've created an Ember Twiddle for you to show this example working.

Vue Axios Post Cancelled in Laravel (api)

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?

vue-async-data not working

I'm trying to use vue-async-data to fetch data asynchronously before rendering my Vue component, but I'm having no success. I'm not getting any erros, but it simply doesn't work.
Here's my main.js code:
import Vue from 'vue'
import VueAsyncData from 'vue-async-data'
import router from './router'
import App from './App.vue'
Vue.use(VueAsyncData)
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
And here's my App.vue code:
<template>
<div>
{{ msg }}
<navigation wait-for="async-data"></navigation>
</div>
</template>
<script>
import Navigation from './components/Navigation.vue'
export default {
name: 'app',
components: {
Navigation
},
data: function() {
return {
msg: 'not loaded yet...'
}
},
asyncData: function (resolve, reject) {
// load data and call resolve(data)
// or call reject(reason) if something goes wrong
setTimeout(function () {
// this will call `vm.$set('msg', 'hi')` for you
resolve({
msg: 'hi'
})
}, 1000)
}
}
</script>
The msg value doesn't change at any moment, but the component is still rendered.
Am I missing somenthing?
As Bert Evans stated, vue-async-data doesn't work with Vue 2.0.
I used vue-router and the created function to achieve what I needed (as suggested in: https://router.vuejs.org/en/advanced/data-fetching.html.
<template>
<div>
<div class="loading" v-if="loading">
Loading...
</div>
<div v-if="error" class="error">
{{ error }}
</div>
<navigation v-if="currentUser"></navigation>
</div>
</template>
<script>
import Navigation from './components/Navigation.vue'
export default {
name: 'app',
components: {
Navigation
},
data: function() {
return {
loading: true,
error: false,
currentUser: null
}
},
created: function() {
this.fetchUserData()
},
methods: {
fetchUserData: function() {
this.$http.get('/Account/CurrentUserInfo').then(data => {
this.currentUser = data
this.loading = false
}, response => {
this.loading = false
this.error = true
});
}
}
}
</script>

Categories