I am starting with the Inertia Laravel example https://github.com/drehimself/inertia-example
which is nothing but Laravel with Vue in one monolithic codebase, using Inertia.js:
https://github.com/inertiajs/inertia-laravel
https://github.com/inertiajs/inertia-vue
I am trying to access Laravel's .env variables inside my .vue component files
.env file:
APP_NAME=ABC
In app\Providers\AppServiceProvider.php:
public function register()
{
Inertia::share('appName', env('APP_NAME'));
}
In resources\js\Home.vue component:
<template>
<div>
<span class="tw-text-left">{{ appName }}</span>
</div>
</template>
<script>
export default {
props: [
"appName",
]
}
</script>
In my vue console, appName shows up blank. It should show "ABC" but doesn't.
What's going on here, and how I can access all my env variables, ideally without passing everything through the controller, which doesn't seem very efficient?
I finally got it working. Here's how, for those interested:
In AppServiceProvider:
Inertia::share(function () {
return [
'app' => [
'name' => config('app.name'),
],
];
});
In your vue file:
<template>
<div>
App name: {{ $page.app.name }}
</div>
</template>
The 2nd part is what I was missing..I was trying to accept the app.name prop, and was missing $page.
Hope this helps somebody!
I know this is kind of old, but I ran into this same issue and the methods above and around the net did not work for me. Something might have changed with Inertia? Anyway, I did get it working though.
Just like above add the following to the register method within your AppServiceProvider:
Inertia::share('appName', config('app.name'));
// I'm using config, but your could use env
Then in your Vue component access the $inertia variable like so:
{{ $inertia.page.props.appName }}
From the documentation on the author's website, you need to instruct vue to inject the page into your component, and then you can accessed the shared variables.
For example:
<template>
<div>
<span class="tw-text-left">{{ page.props.appName }}</span>
</div>
</template>
<script>
export default {
inject: ['page'],
// ...
}
</script>
if you want to share multiple variables with view use the following:
Inertia::share('app', [
'name' => config('app.name'),
'url' => config('app.url'),
]);
Related
Getting to know Laravel a bit more and I was wondering what's the best way to pass my data from my controller into my Vue component?
I have understood how to actually pass it as a prop, however, I can't seem to get it to render the way I want. my props in my Vue component are. My controller here:
{
public function fetch() {
$data = Http::get('https://jsonplaceholder.typicode.com/albums')->json();
return view('welcome', ['data' => $data]);
}
}
My view then passes on the data to my vue component like this.
<example-component :albums="#json($data)" />
My Vue props structure is below.
props: {
albums: {
type: Array,
default: []
},
}
Heres how im trying to render the data in my vue component:
<div>
<h1 v-for="album in albums" :key="album.id">
{{ album.title }}
</h1>
</div>
</template>
Results here enter link description here
I have verified the output from my controller is an array containing arrays. Am I handling the data wrong from the perspective of my Vue component?
you dont need to convert it to json :albums="#json($data)" it's already json ->json();
try replace
:albums="#json($data)"
with this
:albums="{{ $data }}"
i'm trying to write my own blog software based on vue.js/laravel for learning purposes.
Background
I'm asking myself how i write vue.js components in which the paths/urls are not hard coded. In the following example i have a post-listing component which lists all posts from the database. The json data is returned by a laravel api route (e.g. /api/posts)
In the listing i use a link to a laravel view (e.g. /posts/{id}) which shows the actual body of a specific post with {id}.
Example
In laravel's api.php route file i can give a name to a specific route and use it with route('api.posts.index'). That's dynamic enough i guess?
api.php
Route::get('', 'Api\ApiPostsController#index')->name('api.posts.index');
index.blade.php
<post-listing postsview="{{ route('web.posts.show') }}" postsapi="{{ route('api.posts.index') }}"></post-listing>
PostListing.vue
In my vue component i refer to these properties postsview and postsapi
<template>
<div>
<h2 class="title is-2">Recent posts</h2>
<ul>
<li v-for="post in posts['data']" v-bind:key="post.id">
<a :href="postsview + '/' + post.slug" v-text="post.title"></a>
</li>
</ul>
</div>
</template>
<script>
export default {
props: ["postsapi", "postsview"],
data() {
return {
posts: []
};
},
methods: {
getPosts() {
axios.get(this.postsapi).then(response => (this.posts = response.data));
}
},
mounted() {
this.getPosts();
}
};
</script>
The question
Is there a "best-practice" way or at least a better approach? Somehow i'm not happy with this solution, but lacking experience, i don't know where to begin.
Thanks.
There are many ways to achive this, this are a few options that I know of.
1: Use blade to pass the route to the component
<component route="{{ route('route_name') }}"></component>
2: You can save a global variable with all the routes you have defined.
You can use Route::getRoutes() to get all the routes
and add it to your window on your front end
3: Use a library,
This library does exactly what you are looking for I think.
https://github.com/tightenco/ziggy
If find other options please let me know, this is a common issue for most laravel developers.
I'm setting up some Vue Components in my Laravel 5.8 application, that require user information available through Auth::user(), most importantly, the api_token that I must use in my axios requests. I want to pass the Auth::user() object from Laravel to Vue in a secure and private method.
I initially passed the object as props, but I don't want private information on the object to be easily exposed using browser extensions such as Vue DevTools. Now, I've been searching for a way to define global variables inside the Blade Template and access them in Vue:
Pass data from blade to vue component
https://forum.vuejs.org/t/accessing-global-variables-from-single-file-vue-component/638
https://zaengle.com/blog/layers-of-a-laravel-vue-application
Based on those links above, it seems like what I need to do is set the variables to the window object, but I'm unsure on what I'm doing something wrong to achieve this. When I define the variable in the Blade Template, I can see the variable is assigning properly by doing console.log() but the problem comes when I try to use it in Vue.
app.blade.php
#if(Auth::user())
<script>
window.User = {!! json_encode(Auth::user()) !!}
console.log(window.User)
</script>
#endif
component.vue
<script>
export default {
data: function() {
return {
user: window.User
}
}
}
</script>
I've tried setting the data as window.User, this.User, and simply just User but it always comes up as undefined. What am I missing? Or is there any other/better way to do this?
Try the following Vue Component:
<template></template>
<script>
export default {
data: function() {
return {
user: window.User
}
},
created(){
console.log(this.user)
},
}
</script>
I could see the user data from the console.log in Vue component.
How can I have .env data such as APP_NAME in my components?
Let say I want to show to users Welcome to {{APP_NAME}}
UPDATE
Base on this document I've made changes in my env file and like:
MIX_APP_NAME=Laravel
and added this to my component script:
data() {
return {
app_name: process.env.MIX_APP_NAME,
}
},
Now I can have my app name in my component but the issue is I want to use it in bootstrap tooltip and there gives me this error:
- title=".... by {{app_name}}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of <div id="{{ val }}">, use <div :id="val">.
My code:
<span data-toggle="tooltip" data-placement="top" title="... {{app_name}}"></span>
Any idea?
First add to env file:
MIX_APP_NAME=Laravel
and add this to your component script:
data() {
return {
app_name: process.env.MIX_APP_NAME,
}
},
Now you can use it like this:
<div :title="`text ${app_name}`"></div>
Or:
{{ app_name }}
Source
thats worked for me without adding any require in webpack.mix
... just add a new variable in env file with this prefix : MIX_
BUT need to restart with php artisan serve and also restart with npm run watch ....
you can directly use it as process.env.APP_NAME
mounted(){
this.appName=process.env.APP_NAME
}
I'm trying to learn vue and with that I want to integrate it with laravel too..
I simply want to send the user id from blade to vue component so I can perform a put request there.
Let's say I have this in blade:
<example></example>
How can I send Auth::user()->id into this component and use it.
I kept searching for this but couldn't find an answer that will make this clear.
Thanks!
To pass down data to your components you can use props. Find more info about props over here. This is also a good source for defining those props.
You can do something like:
<example :userId="{{ Auth::user()->id }}"></example>
OR
<example v-bind:userId="{{ Auth::user()->id }}"></example>
And then in your Example.vue file you have to define your prop. Then you can access it by this.userId.
Like :
<script>
export default {
props: ['userId'],
mounted () {
// Do something useful with the data in the template
console.dir(this.userId)
}
}
</script>
If you are serving files through Laravel
Then here is the trick that you can apply.
In Your app.blade.php
#if(auth()->check())
<script>
window.User = {!! auth()->user() !!}
</script>
#endif
Now you can access User Object which available globally
Hope this helps.
Calling component,
<example :user-id="{{ Auth::user()->id }}"></example>
In component,
<script>
export default {
props: ['userId'],
mounted () {
console.log(userId)
}
}
</script>
Note - When adding value to prop userId you need to use user-id instead of using camel case.
https://laravel.com/docs/8.x/blade#blade-and-javascript-frameworks
Rendering JSON
Sometimes you may pass an array to your view with the intention of rendering it as JSON in order to initialize a JavaScript variable. For example:
<script>
var app = <?php echo json_encode($array); ?>;
</script>
However, instead of manually calling json_encode, you may use the #json Blade directive. The #json directive accepts the same arguments as PHP's json_encode function. By default, the #json directive calls the json_encode function with the JSON_HEX_TAG, JSON_HEX_APOS, JSON_HEX_AMP, and JSON_HEX_QUOT flags:
<script>
var app = #json($array);
var app = #json($array, JSON_PRETTY_PRINT);
</script>
Just to add for those who still get error.
For me this <askquestionmodal :product="{{ $item->title }}"></askquestionmodal> still gives error in console and instead showing html page I saw white screen.
[Vue warn]: Error compiling template:
invalid expression: Unexpected identifier in
Coupling to connect 2 rods М14 CF-10
Raw expression: :product="Coupling to connect 2 rods М14 CF-10"
Though in error I can see that $item->title is replaced with its value.
So then I tried to do like that <askquestionmodal :product="'{{ $item->title }}'"></askquestionmodal>
And I have fully working code.
/components/askquestionmodal.vue
<template>
<div class="modal-body">
<p>{{ product }}</p>
</div>
</template>
<script>
export default {
name: "AskQuestionModal",
props: ['product'],
mounted() {
console.log('AskQuestionModal component mounted.')
}
}
</script>