How to pass logged user from control to vuejs component? - laravel

in laravel 8/2.6/bootstrap 4.6/Axios app I want to pass logged user from control to vuejs component:
public function index()
{
$loggedUser = auth()->user();
return view('chat', [
'loggedUser' => $loggedUser,
]);
}
in blade file :
#extends('layouts.app')
#section('content')
<div class="container chats">
loggedUser::{{ $loggedUser}}!!!!!!!!!
<!-- I SEE USER data above : -->
<user-rooms :loggedUser="{{ $loggedUser }}"> </user-rooms>
</div>
#endsection
and vue component :
<template>
<div class="container">
loggedUser::{{ loggedUser}}
<!-- I see empty value above outputed -->
</div>
</template>
<script>
export default {
name: "Chat",
components: {},
props: {
loggedUser : {
type: Object,
required: true,
},
},
mounted() {
console.log('UserRooms.vue Component mounted loggedUser')
console.log(this.loggedUser) // I see undefined outputed
}, // mounted() {
};
</script>
I tried several direrent cases like :
<user-rooms :loggedUser="{{ json_encode($loggedUser) }}"> </user-rooms>
but failed anyway...
Which way is correct?
Thanks!

You should follow these steps to pass auth user in vue component.
You should add a <meta name="user" content="{{ Auth::user() }}"> in
// app.blade.php or whatever you have maybe master.blade.php like below
<head>
<meta charset="UTF-8">
#if (Auth::check())
<meta name="user" content="{{ Auth::user() }}">
#endif
<meta http-equiv="X-UA-Compatible" content="IE=edge"
...
...
and then in your component inside data object do this action:
data() {
return {
loggedUser : document.querySelector("meta[name='user']").getAttribute('content')
}
},
and you should see the logged in user in component mounted method:
mounted() {
console.log(this.loggedUser);
},
and now you can use the user object in every where of your component.

You can also get logged in information with this example:
lets say app.blade.php its your file that loads your page.
You can set a script that stores your authentication.
<script>
window.user = {{!! Auth::user() !!}}
</script>
Then in your vue component or even better if you are using vuex store you can get the object.
data(){
loggedUser: window.user
}

Related

How to use laravel-vue-i18n to change translations in laravel blades also?

Can anyone help me make translations working in laravel blades too?
I need to change/translate the contents of the title and description meta depending on the language being switched.
This is how the language changes in Vue:
<template>
<ul class='language-switcher'>
<li :class="{'active': language === 'de'}">
De
</li>
<li :class="{'active': language === 'en'}">
En
</li>
</ul>
</template>
<script>
import {loadLanguageAsync} from "laravel-vue-i18n";
export default {
name: "LanguageSwitcherComponent",
data() {
return {
language: 'en',
};
},
methods: {
switchLanguageTo(lang) {
// ...
loadLanguageAsync(lang);
// ...
},
},
}
</script>
In Vue, the translations work fine, but I need to translate title and description meta in index.balde.php as well.
<!DOCTYPE html>
<html lang="{{str_replace('_', '-', app()->getLocale())}}">
<head>
<title>{{ __("Site Title") }}</title>
<meta name="description" content="{{ __("Site Info") }}">
<meta charset="utf-8">
<meta name="csrf-token" content="{{ csrf_token() }}"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{mix('css/app.css')}}">
</head>
<body>
<div id="app">
<index-component/>
</div>
<script src="{{mix('js/app.js')}}"></script>
</body>
</html>
Also, this is how configured i18n in app.js:
import {i18nVue} from 'laravel-vue-i18n';
// ...
app.use(i18nVue, {
lang: 'en',
resolve: lang => import(`../../lang/${lang}.json`),
});
Thanks!
Save site language in cookies and in web.php set locale from cookies.
Route::get('/{any}', function (Request $request) {
// Set locale
App::setLocale($request->cookie('site_language') ?: 'en');
return view('index');
})->where('any', '.*');
Note: Maybe will need to add cookie name in app/Http/Middleware/EncryptCookies.php in $except list to get cookie from the $request successfully.

How to keep the component alive when refreshing page VUEJS [duplicate]

I am creating a simple laravel and vuejs CRUD Application. Vue Routes are not working, I am pretty new to vuejs; please see the code
Below is the code for web.php
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::get('/vue','Api\PostController#home');
Route::resource('/api','Api\PostController');
Following is the code for app.js
require('./bootstrap');
window.Vue = require('vue');
window.VueRouter=require('vue-router').default;
window.VueAxios=require('vue-axios').default;
window.Axios=require('axios').default;
let AppLayout = require('./components/App.vue');
const Posts = Vue.component('Posts',require('./components/Posts.vue'));
const EditPost =
Vue.component('EditPost',require('./components/EditPost.vue'));
const AddPost =
Vue.component('AddPost',require('./components/AddPost.vue'));
const DeletePost =
Vue.component('DeletePost',require('./components/AddPost.vue'));
const ViewPosts =
Vue.component('ViewPosts',require('./components/ViewPosts.vue'));
const ExampleComponent =
Vue.component('ViewPosts',require('./components/ExampleComponent.vue'));
// Registering routes
Vue.use(VueRouter,VueAxios,axios);
const routes = [
{
name: 'Posts',
path: '/posts',
component: Posts
},
{
name: 'AddPost',
path: '/add-posts',
component: AddPost
},
{
name: 'EditPost',
path: '/edit-post/:id',
component: EditPost
},
{
name: 'DeletePost',
path: '/delete-post',
component: DeletePost
},
{
name: 'ViewPosts',
path: '/view-post',
component: ViewPosts
},
{
name: 'ExampleComponent',
path: '/example-component',
component: ExampleComponent
},
];
const router = new VueRouter({mode: 'history', routes: routes});
new Vue(
Vue.util.extend(
{ router },
AppLayout
)).$mount('#app');
This is the code of my blade tamplate, when I browse http://localhost:8000/vue this view is being rendered. As you can see in the web.php code above.
I can also see the notification in console You are running Vue in development mode. Make sure to turn on production mode when deploying for production.
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div class="container">
<header class="page-header">
<div class="branding">
<img src="https://vuejs.org/images/logo.png" alt="Logo" title="Home page" class="logo"/>
<h1>Vue.js CRUD With Laravel 5 application</h1>
</div>
</header>
</div>
<section id="app">
</section>
<script>
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
]); ?>
</script>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
But when I run my application using
php artisan serve
and browse to
http://localhost:8000/posts
Application show a 404 error. Please help me with this problem.
You need to add a laravel route for the view where you are using the app.js (vuejs) in routes/web.php file.
Route::get('/route-name/?{name}', function(){
return redirect('vue_app');
})->where('name', '[A-Za-z]+');
and then you have to use the laravel route as a parent route for the vuejs's routes and use the url like below,
http://localhost:8000/laravel-route/view-route
in your case,
http://localhost:8000/route-name/posts
Or you can also use,
Route::get('{any}', function () {
return view('vue_app');
})->where('any', '.*');
and instead of previous use localhost:8000/posts
Try this to your web.php route
Route::get('/', function () {
return view('index');
});
Route::get('/{catchall?}', function () {
return response()->view('index');
})->where('catchall', '(.*)');
if with {any} did not work, you may also try adding ?
Route::get('/any-your-route/{any?}', function() {
return view('your-view');
})->where('any', '.*');
hope this help you. i just try this code and work on laravel blade template with vue router.
Tested on Laravel 8
For your second part of question,
You should use <div> instead of <section> and you have to bring the main/registered component inside of the html element selected by id="app" in blade file. in your case,
<div id="app">
<app-layout></app-layout>
</div>
Hope this help you. you can check this basic vuejs with laravel
PS: You should ask two different problem in two seperate posts.
you can do simply like this.
Route::get('/{vue_capture?}', function(){
return view('welcome');
})->where('vue_capture', '[\/\w\.-]*');

Vue component not being rendered in blade file

So I am trying to build a new Laravel app with Vue. For some reason, the example component that the app comes with works fine, but my own doesn't. Here's my file structure and code:
views/layout/vue.blade.php
<html>
<head>
<title>Skat</title>
</head>
<meta name="csrf-token" content="{{ csrf_token() }}">
<body>
<div id="app">
#yield("content")
</div>
<script src="/js/app.js"></script>
</body>
</html>
resources/views/vue.blade.php this is working fine!
#extends('layouts.vue')
#section('content')
<example-component></example-component>
#endsection
resources/js/components/ExampleComponent.vue
<template>
<div class="container">
some stuff ..
</div>
</template>
<script>
export default {
name: 'example-component',
mounted() {
console.log('Component mounted.')
}
}
</script>
resources/views/home.blade.php this is NOT working :(
#extends('layouts.vue')
#section('content')
<home></home>
#endsection
resources/js/components/Home.vue
<template>
<div class="container-fluid d-flex h-100 flex-column">
test test
</div>
</template>
<script>
export default {
name: 'home',
components: {
}
}
</script>
<style scoped>
...
</style>
routes/web.php
Route::get('/', function () {
return view('vue');
});
Route::get('/home', function () {
return view('home');
});
resources/js/app.js
...
import ExampleComponent from './components/ExampleComponent.vue';
import Home from './components/Home.vue';
const app = new Vue({
el: '#app',
components: {
ExampleComponent,
Home
}
});
I am not getting any errors or anything. I guess somewhere I didn't set it up right, but I'm confused!
Thanks! :)
Don't use components: {} on the root instance. Explicitly declare it with:
Vue.component('example-component', ExampleComponent).
Even better.
const files = require.context('./', true, /\.vue$/i);
files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default));

How to deal when llogged user refresh page of vuejs/vuex app?

in my laravel 5.8 / vuejs 2.5 / "vuex 3.1 user login into the system and some data are stored in user's store, like in auth/Login.vue:
<script>
export default {
...
mounted() {
this.setAppTitle("", 'Login', bus);
}, // mounted() {
computed: {
authError() {
return this.$store.getters.authError;
}
}, // computed: {
methods: {
authenticate() {
this.$store.dispatch('login'); // calling action
login(this.$data.form)
.then((res) => {
this.$store.commit("loginSuccess", res); // calling mutation
this.$store.dispatch('retrieveUserLists', res.user.id );
this.$router.push({path: '/websites-blogs'}); // For debugging!
})
.catch((error) => {
this.$store.commit("loginFailed", {error}); // calling mutation
});
}
}, // methods: {
and store where user's account and his data are kept resources/js/store.js :
export default {
state : {
currentLoggedUser: user,
// personal data only for logged user
userLists: [],
},
getters : {
...
userLists(state) {
return state.userLists;
},
It works ok, until logged user refresh page (F5 or CTRL+R) and user is still logged in my page, but some data, say (userLists)
are empty and some listing is empty.
I have MainApp.vue :
<template>
<body class="account-body">
<v-dialog/>
<MainHeader></MainHeader>
<div class="content p-0 m-0" style="width: 100% !important; margin: auto !important;">
<notifications group="wiznext_notification"/>
<router-view></router-view>
</div>
</body>
</template>
<script>
...
export default {
name: 'main-app',
components: {MainHeader},
mixins: [appMixin],
created() {
},
mounted() {
...
},
methods: {
...
}, // methods: {
}
</script>
and resources/views/index.blade.php :
<?php $current_dashboard_template = 'Horizontal' ?>
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title id="app_title">{{ config('app.name', 'Laravel') }}</title>
<link href="{{ asset(('css/Horizontal/bootstrap.min.css')) }}" rel="stylesheet" type="text/css">
<link href="{{ asset(('css/Horizontal/icons.css')) }}" rel="stylesheet" type="text/css">
<link href="{{ asset(('css/Horizontal/style.css')) }}" rel="stylesheet" type="text/css">
...
{{--<link href="css/Horizontal/ion.rangeSlider.css" rel="stylesheet" type="text/css"/>--}}
{{--<link href="css/Horizontal/ion.rangeSlider.skinModern.css" rel="stylesheet" type="text/css"/>--}}
{{--<link href="css/Horizontal/powerange.css" rel="stylesheet" type="text/css"/>--}}
<link href="{{ asset(('css/'.$current_dashboard_template.'/app.css')) }}" rel="stylesheet" type="text/css">
...
</head>
<body>
<div class="wrapper" id="app">
<main>
<div id="main_content">
<mainapp></mainapp>
</div>
</main>
</div>
</body>
#include('footer')
<script src="{{ asset('js/jquery.min.js') }}"></script>
<script src="{{ asset('js/bootstrap.bundle.min.js') }}"></script>
<script src="{{ asset('js/metisMenu.min.js') }}"></script>
<script src="{{ asset('js/waves.min.js') }}"></script>
<script src="{{ asset('js/jquery.slimscroll.min.js') }}"></script>
<script src="{{ asset('js/app.js') }}{{ "?dt=".time() }}"></script>
{{--<script type="text/javascript" src="{{ asset('js/vuecsv.min.js') }}"></script>--}}
</html>
Could you please to advice a proper way of such situations ? What could I do?
MODIFIED :
I tried to remake my storage and seems it works ok :
const user = getLocalUser();
export default {
state : {
currentLoggedUser: user,
isLoggedIn: !!user,
loading: false,
auth_error: null,
api_url: '/api',
// personal data only for logged user
userLists: [], // I need to save data on page refresh
},
getters : {
...
userLists(state) {
// that works ok after user logged into the system and userLists is read on all page without refresh
if ( state.userLists.length > 0 ) {
return state.userLists;
}
// if userLists is empty check data in localStorage which were saved in refreshUserLists mutation
let localStorageUserLists = JSON.parse(localStorage.getItem("userLists"));
if ( localStorageUserLists.length > 0 ) {
console.log("localStorageUserLists RETURNED::")
return localStorageUserLists;
}
return [];
},
},
mutations : {
// that works ok after user logged into the system and his personal data(in my case 5 rows) are read from db into the vuex store
refreshUserLists(state, payload) {
state.userLists = payload;
localStorage.setItem("userLists", JSON.stringify(payload) );
},
},
What else have I to pay attention at ?
So the thing is, Vuex control your data status across your entire application and components, but once your user press F5 or any other refresh option, the Vuex is reset, there is nothing you can do about it, it's just like it works.
One work around solution i can think right now is to save the data on Vuex and maybe on localstorage, then, on vuex create lifecycle you can just populate the data with the localstorage data if it's empty.
I disagree with the proposed solutions. A browser refresh usually indicates that the user wants to fetch the most fresh data from the server, and reset the app state with that fresh data. Therefore you shouldn't store Vuex state in localStorage or cookies to get around this. If you do that, you now have your app state in two places, and also the user thinks they have the most fresh data when they don't.
The best way to handle a browser refresh event in a SPA is to bootstrap your state from scratch. When your app loads after a refresh, it should notice that the user is not logged in (since that is the default state), and should log them in by negotiating with the server behind the scenes, such as by sending the session cookie and receiving confirmation (or redirecting to login page if the session has expired). It should also re-fetch all relevant data from the server and store that in Vuex again.
you can use both localStorage and cookies.due to problems that I had with LocalStorage i recommand cookies. Vue has a rich plugin called Vue-cookies.
you can set and get data by these commands:
var user = { id:1, name:'Journal',session:'25j_7Sl6xDq2Kc3ym0fmrSSk2xV2XkUkX' };
this.$cookies.set('user',user);
// print user name
console.log(this.$cookies.get('user').name)
more details:
Github

Laravel class access in Vue.js

I have the following class where I defined my Minimum/Maximum length values:
class MinMaxValuesUser {
const Min_UserName = 6;
const Max_UserName = 30;
}
Below is the rule in request class where the min max values are used instead of hardcoding it.
public function messages() {
return [
"Min_UserName.min" => trans("Profile.Min_UserName"),
"Max_UserName.max" => trans("Profile.Max_UserName")
];
}
public function rules() {
return [
"UserName" => "min:" . MinMaxValuesUser::Min_UserName
. "|max:" . MinMaxValuesUser::Max_UserName
];
}
and below is the JQuery Validate code where I used the same server-side class.
$('form#frmProfile').validate({
rules: {
UserName: {
minlength: {!! \App\MinMaxValues\MinMaxValuesUser::Min_UserName !!},
maxlength: {!! \App\MinMaxValues\MinMaxValuesUser::Max_UserName !!}
}
}
});
Issue
As I am writing a lot of code, so I have started to use Vue.js which is already embedded in Laravel. Everything works great here
but as we know vue.js is a front-end framework and loads in client side so will not be able to use the above server-side classes to keep the min max numbers centralized.
Kindly suggest how to get rid of this issue.
put your user configurations in a /config/user.php file like this
<?php
return [
'Min_UserName' => 4,
'Max_UserName' => 10
];
You can now access it anywhere in your php like this
config('user.Min_userName'); // specific value
config('user'); // array of both values
And you can place it into your view files like this:
#json(config('user'))
If your view component is defined in a blade file you can put this in your data definition:
'user_requirements': #json(config('user'))
If your vue component is buried down further in a js file then you'll want to define a js variable in your blade template (probably your layout) like this
let MyUserReqs = #json('user');
And then you can define it in your vue component using the js variable MyUserReqs.
You can set up your app.blade.php template something like this:
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<!-- Site Properties -->
<title>{{ config('app.name') }}</title>
<!-- Styles -->
<link href="{{ asset('inside/css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<!-- Scripts -->
<script src="{{ asset('inside/js/app.js') }}"></script>
<script type="text/javascript">
const globalProps = {
minlength: {!! \App\MinMaxValues\MinMaxValuesUser::Min_UserName !!},
maxlength: {!! \App\MinMaxValues\MinMaxValuesUser::Max_UserName !!}
}
globalProps.install = function(){
Object.defineProperty(Vue.prototype, '$globalProps', {
get () { return globalProps }
})
}
Vue.use(globalProps);
</script>
</body>
</html>
We define a constant, then "install/define" that constant as a vue.prototype object, then we tell vue to use it. You can also do that set up in any blade template... but if you need it everywhere on you app, you can set it up here.
Then you are ready to go, in your vue instances you can use it like this for the html/template
<div v-if="$globalProps.minlength == 6"></div>
And if you want to access it inside the script:
methods: {
someMethod() {
if(this.$globalProps.maxlength == 6){
}
},
}
Outside vue, on jquery, you could refer to it simply as globalProps.maxlength
I would take the validation logic away form the front end and instead handle this in the backend. This way, you only have to write the validation logic in one place and the front end will handle the response appropriately.
Jeffery Way did a really good tutorial on this. I would recommend following this - https://laracasts.com/series/learn-vue-2-step-by-step/episodes/19

Resources