This is the problem : some vue routes don't work with Laravel router whereas others are working.
This one works :
Route::get('/dishesV2/edit/{id}', function () {
return view('back.nutritionV2.index');
});
Whereas this one does not :
Route::get('/mealPlansV2/edit/{id}', function () {
return view('back.nutritionV2.index');
});
The error thrown when I try to access to the second route is thrown by a route called after the creation of the vue component.. After the component is created, it's calling for the following route :
Route::get('/mealPlansV2/{id}/{day}','MealPlansV2Controller#fetchMealPlanDay');
And when I dd the parameters called by this route, I have the parameters of the route '/mealPlansV2/edit/{id}'...
Second problem is when I call the route columns in Laravel :
Route::get('/mealPlansV2/columns',function () {
return view('back.nutritionV2.index');
});
What's returned is the axios request "fetchMealPlans" that is called inside the components "columns" instead of the vue route columns...
This is how my vue routes look like :
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/mealPlansV2/columns',
name: 'MealPlansColumns',
component: MealPlansColumns,
},
{
path: '/mealPlansV2/edit/:id',
name: 'MealPlansEdit',
component: MealPlansEdit,
},
{
path: '/dishesV2/columns',
name: 'DishesColumns',
component: DishesColumns,
},
{
path: '/dishesV2/edit/:id',
name: 'DishesEdit',
component: DishesEdit,
},
],
});
Only the route DishesEdit works in my app.
Thanks for the help and do not hesitate if I haven't been clear on some points.
Related
I need to make a category filter for my blog posts. I was toying around with Vue a bit. But since I have not learned Vue, I was recommended to just use Axios. I am completely lost. How does it work? I cannot even log a result from here? I did get it to work with an example in the App.JS from a SO question, trying to find that again. But thats Vue? I am not sure what to do anymore ? This is my example the /axios refers to a controller I show the controller first then the blade :
class AxiosController extends Controller
{
public function index()
{
$articles = Article::all();
//$categories = Category::all();
return response()->json($articles);
}
}
The blade ( I had it without the axios.create and all kinds of try outs I did) I also did it without the #once and the #push I just read this in the Laravel documentation.
#once
#push('scripts')
<script src="https://unpkg.com/axios/dist/axios.min.js">
const instance = axios.create({
baseURL: 'http://localhost:8000/axios',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
const axios = require('axios');
axios.get('http://localhost:8000/axios')
.then(function (response) {
// handle success
console.log(response);
})
</script>
#endpush
#endonce
I'm setting up a laravel, vue project and i am using JWT auth for the user authentication. I am trying to protect the Routes with Vue Router and it is getting token from the local storage and giving access to the authentic user to specific route, but once on another route if i click on any other route or refresh the page it redirects me on the "/login" page again. The token remains same all the time but it is considering the token as the user is not authentic. Please help as i am new to laravel and vue
I have tried using meta info but that didn't work as well. Moreover, i have tried deleting the token from local storage and created it again but nothing works for me.
routes.js file
export const routes = [
{
path: '/', component: Home, name: 'home'
},
{
path: '/dashboard', component: Dashboard, name: 'dashboard', meta:{requiresAuth: true}
},
{
path: '/login', component: Login, name: 'login'
}
];
App.js file
import VueRouter from 'vue-router';
import { routes } from './routes.js';
window.Vue = require('vue');
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
routes
});
router.beforeEach((to, from, next) => {
console.log(to)
if (to.meta.requiresAuth) {
const authUser = JSON.stringify(window.localStorage.getItem('usertoken'))
if(authUser && authUser.accessToken){
console.log("here")
next();
}else{
next({name: 'login'});
}
}
next();
});
const app = new Vue({
el: '#app',
router
});
I expect the output to be like when the user is authentic and the router.beforeEach method finds a token, the user can get to any route until the token gets deleted or changed. Moreover, the user should not be taken to '/login' everytime a <router-link> is clicked or page is refreshed.
I was just trying to solve it and it is solved...the problem was with the line if(authUser && authUser.accessToken) . I added authUser.accessToken as a condition which was not fulfilled, so it was redirecting on every click. I removed that condition and just left with if(authUser) and now it is working perfectly. Also I have added JSON.stringify to change my object to text and then authenticate with JSON.parse by passing a variable.
My final code looks like:-
router.beforeEach((to, from, next) => {
console.log(to)
if (to.meta.requiresAuth) {
var usertoken = JSON.stringify(window.localStorage.getItem('usertoken'))
const authUser = JSON.parse(usertoken)
if(authUser){
console.log("here")
next();
}else{
next({name: 'login'});
}
}
next();
});
So I am using Laravel 5.5. I have a data coming from my Controller and I want to pass it to my root vue instance not the component.
So for example I have the Dashboard Controller which has a data of "users"
class DashboardController extends Controller {
public function index(){
$user = User::find(1);
return view('index', compact('user'));
}
}
I am using Larave mix on my project setup. So my main js file is the app.js. That "$user" data I need to pass on the root Vue instance. Which is located in app.js
const app = new Vue({
el: '#dashboard',
data: {
// I want all the data from my controller in here.
},
});
If you don't want to use an API call to get data (using axios or else), you could simply try this :
JavaScript::put(['user' => $user ]);
This will, by default, bind your JavaScript variables to a "footer" view. You should load your app.js after this footer view (or modify param bind_js_vars_to_this_view).
In app.js :
data: {
user: user
}
Read more : https://github.com/laracasts/PHP-Vars-To-Js-Transformer
I would make a request to fetch the user's data as has been suggested.
Alternatively, you can add a prop to the dashboard component in index.blade.php and set the user like <dashboard :user="{{ $user }}"></dashboard>. You'll probably want to json_encode or ->toArray() the $user variable.
Then within the dashboard component you can set data values based on the prop.
props: ['user'],
data () {
return {
user: this.user
}
}
I just solved this by placing a reference on the window Object in the <head> of my layout file, and then picking that reference up with a mixin that can be injected into any component.
TLDR SOLUTION
.env
GEODATA_URL="https://geo.some-domain.com"
config/geodata.php
<?php
return [
'url' => env('GEODATA_URL')
];
resources/views/layouts/root.blade.php
<head>
<script>
window.geodataUrl = "{{ config('geodata.url') }}";
</script>
</head>
resources/js/components/mixins/geodataUrl.js
const geodataUrl = {
data() {
return {
geodataUrl: window.geodataUrl,
};
},
};
export default geodataUrl;
usage
<template>
<div>
<a :href="geodataUrl">YOLO</a>
</div>
</template>
<script>
import geodataUrl from '../mixins/geodataUrl';
export default {
name: 'v-foo',
mixins: [geodataUrl],
data() {
return {};
},
computed: {},
methods: {},
};
</script>
END TLDR SOLUTION
If you want, you can use a global mixin instead by adding this to your app.js entrypoint:
Vue.mixin({
data() {
return {
geodataUrl: window.geodataUrl,
};
},
});
I would not recommend using this pattern, however, for any sensitive data because it is sitting on the window Object.
I like this solution because it doesn't use any extra libraries, and the chain of code is very clear. It passes the grep test, in that you can search your code for "window.geodataUrl" and see everything you need to understand how and why the code is working.
That consideration is important if the code may live for a long time and another developer may come across it.
However, JavaScript::put([]) is in my opinion, a decent utility that can be worth having, but in the past I have disliked how it can be extremely difficult to debug if a problem happens, because you cannot see where in the codebase the data comes from.
Imagine you have some Vue code that is consuming window.chartData that came from JavaScript::put([ 'chartData' => $user->chartStuff ]). Depending on the number of references to chartData in your code base, it could take you a very long time to discover which PHP file was responsible for making window.chartData work, especially if you didn't write that code and the next person has no idea JavaScript::put() is being used.
In that case, I recommend putting a comment in the code like:
/* data comes from poop.php via JavaScript::put */
Then the person can search the code for "JavaScript::put" and quickly find it. Keep in mind "the person" could be yourself in 6 months after you forget the implementation details.
It is always a good idea to use Vue component prop declarations like this:
props: {
chartData: {
type: Array,
required: true,
},
},
My point is, if you use JavaScript::put(), then Vue cannot detect as easily if the component fails to receive the data. Vue must assume the data is there on the window Object at the moment in time it refers to it. Your best bet may be to instead create a GET endpoint and make a fetch call in your created/mounted lifecycle method.
I think it is important to have an explicit contract between Laravel and Vue when it comes to getting/setting data.
In the interest of helping you as much as possible by giving you options, here is an example of making a fetch call using ES6 syntax sugar:
routes/web.php
Route::get('/charts/{user}/coolchart', 'UserController#getChart')->name('user.chart');
app/Http/Controllers/UserController.php
public function getChart(Request $request, User $user)
{
// do stuff
$data = $user->chart;
return response()->json([
'chartData' => $data,
]);
}
Anywhere in Vue, especially a created lifecycle method:
created() {
this.handleGetChart();
},
methods: {
async handleGetChart() {
try {
this.state = LOADING;
const { data } = await axios.get(`/charts/${this.user.id}/coolchart`);
if (typeof data !== 'object') {
throw new Error(`Unexpected server response. Expected object, got: ${data}`);
}
this.chartData = data.chartData;
this.state = DATA_LOADED;
} catch (err) {
this.state = DATA_FAILED;
throw new Error(`Problem getting chart data: ${err}`);
}
},
},
That example assumes your Vue component is a Mealy finite state machine, whereby the component can only be in one state at any given time, but it can freely switch between states.
I'd recommend using such states as computed props:
computed: {
isLoading() { return (this.state === LOADING); },
isDataLoaded() { return (this.state === DATA_LOADED); },
isDataFailed() { return (this.state === DATA_FAILED); },
},
With markup such as:
<div v-show="isLoading">Loading...</div>
<v-baller-chart v-if="isDataLoaded" :data="chartData"></v-baller-chart>
<button v-show="isDataFailed" type="button" #click="handleGetChart">TRY AGAIN</button>
I'm using Lumen + Vue js to build an app.
I have this code in routes.php
$app->get('{any}', function () {
return view('vue', []);
});
$app->get('/', function () {
return view('vue', []);
});
This works great for /login, /users, /anything . But when I add a subroute like /users/agents or /a/b, /a/b/c -> anything with more than one slash it gives me the 404 from lumen
You have the 404 error because {any} will not catch the parameters that contain slash. I order to make it do so, you need to add a pattern:
$app->get('{any:.+}', function () {
return view('vue', []);
});
I have a route defined in routes.php file but when i make an ajax request from my angular app, i get this error
{"error":{"type":"Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException","message":"Controller method not found.","file":"C:\\xampp\\htdocs\\tedxph\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Controllers\\Controller.php","line":290}}
this is my routes file
/*
|--------------------------------------------------------------------------
| Api Routes
|--------------------------------------------------------------------------
*/
Route::group(array('prefix' => 'api'), function() {
//Auth Routes
Route::post('auth/login', 'ApiUserController#authUser');
Route::post('auth/signup', 'ApiUserController#registerUser');
/* Persons */
Route::group(array('prefix' => 'people'), function() {
Route::get('{id}', 'ApiPeopleController#read');
Route::get('/', 'ApiPeopleController#read');
});
/* Events */
Route::group(array('prefix' => 'events'), function() {
Route::get('{id}', 'ApiEventsController#read');
Route::get('/','ApiEventsController#read');
});
});
Accessing the same url (http://localhost/site/public/api/auth/signup) from a rest client app on chrome does not give any errors, what could be wrong?
this is the angular code from my controller
$rootScope.show('Please wait..registering');
API.register({email: email, password: password})
.success(function (data) {
if(data.status == "success") {
console.log(data);
$rootScope.hide();
}
})
.error(function (error) {
console.log(error)
$rootScope.hide();
})
more angular code
angular.module('tedxph.API', [])
.factory('API', function ($rootScope, $http, $ionicLoading, $window) {
//base url
var base = "http://localhost/tedxph/public/api";
return {
auth: function (form) {
return $http.post(base+"/auth/login", form);
},
register: function (form) {
return $http.post(base+"/auth/signup", form);
},
fetchPeople: function () {
return $http.get(base+"/people");
},
fetchEvents: function() {
return $http.get(base+"/events");
},
}
});
It'd help to see the code you're using to make the angular request, as well as the header information from Chrome's Network -> XHR logger, but my first guess would be Angular is sending the AJAX request with the GET method instead of the POST method. Try changing Angular to send an explicit POST or change routes.php so auth/signup responds to both GET and POST requests.
Update looking at your screen shots, the AJAX request is returning an error 500. There should be information logged to either your laravel.log file or your PHP/webserver error log as to why the error is happening. My guess if your Angular request sends different information that your Chrome/REST-app does, and that triggers a code path where there's an error.
Fixed the problem, turns my controller was calling an undefined method in the controller class.
Renamed the method correctly and the request now works, thanks guys for the input.