how to pass laravel trans strings to vue component - laravel

In the event that you are developing your software using the Laravel framework and need to use the Vue library, you will face some obstacles, including how to access the files translation system provided by Laravel .
like how to access trans('home.var')

Add Language file like this
<messagings v-bind:language="{{ json_encode(trans('messages')) }}"></messagings>
then in vue component print like this
<h4>{{ this.language.messaging }}</h4>

1: pass trans as prop in blade normally just you need to encoding with json used json_encode() method :
<component :trans="{{json_encode(trans('home'))}}"></component>
2: in vue component page you need to decode json data first and set the translation data in some var :
export default {
props:['trans'],
data () {
return {
translation:[],
};
},
created(){
this.setTranslation()
},
methods:{
setTranslation(){
let decoded_trans = JSON.parse(this.trans);
this.transaction = decoded_trans;
}
}
3: Now you can access laravel trans normaly just be careful because vue will not detect if you call last node or first.
<template>
<div>
<h2>{{translation.header.login}}</h2> // this line in laravel mean : trans('home.header.login')
</div>
<template>
Finally I recently started learning vue , so this method may have some flaws, but We all strive to benefit :)

Related

Vue2 + laravel6 - Component implementation

I just started using Vue2 with Laravel6 and got stuck when trying to understand how to use component method.
As I am totally new for Vue, I am using the official tutorial of Vue as a reference. What I learned from here(https://v2.vuejs.org/v2/guide/components.html) about Vue component instantiation is we give options to a component.(e.g. we give 'template:' options for HTML part.)
When I look at laravel6 codes of resouces/js/app.js, it looks something like this:
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
I looked at js/components/ExampleComponent.vue expecting to see some options declared there. However, there's no option in the ExampleComponent.vue file. Instead, I see <template></template> tag. Apparently, the <template></template> tag seems to work as 'template:' option.
I have two questions regarding above:
Does <template></template> tag have the same meaning as 'template:' option?
If question 1 is yes, are other options also replacable with corresponding tags? (e.g. Can I use <props></props> tag for 'props:' option? or <data></data> tag for 'data:' option?
Thanks in advance!
In Vue world, there are two popular types of defining a component
First Type
in this type, you add all of your HTML inside the template property
and the props add as attribute inside the component object to
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
Second Type
in this type you add your component logic in a separate file ends with .vue
for example in laravel there is an ExampleComponent.vue file you will find on
it just template tag just as a wrapper for your component content and your logic you can write it as it mentions below.
<template>
// some content here
</template>
<script>
export default {
props: [],
methods: {
},
data(){
return {
}
}
}
</script>
Finally
there is no tag called props or data
for more info read this article

How to use paths/urls/routes dynamically in vue.js/laravel components

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.

How to pass an object from Laravel to Vue without using props

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.

Best practice to pass data from Laravel to Vue component

This is my blade code
<div id="app">
<Testcomponent bam-wam="ham" />
</div>
This is my VueJS Component code
<script>
export default {
name: "ExampleComponent",
props: [
'bamWam'
],
data () {
return {
};
},
created() {
console.log(this.bamWam);
}
}
</script>
Question is
This code runs good but I am asking what is better using Axios and Vuex to fetch data from my Laravel app or simply Pass data throw props like I did in this code?
Pass data through props is the best way.
<my-component my-data="yourData"></my-component>
If you want to use laravel variable for data from blade then,
<my-component my-data="'{{ $data->id }}'"></my-component>
<my-component :my-data="'{!! json_encode($data) !!}'"></my-component>
Avoid api call as much as possible. It will reduce the total number of request to server and expose fewer number of api endpoint.
If the data is available to the view where the component is added. Then the best way to pass php arrays from laravel to a vue component is to utilize json encoding like so:
<my-component :needed-data='#json($laravelCollection)'></my-component>
This will make you will be easily to perform actions to the php array in the Vue controller as if it was a JS object. Keep in mind that you have to use single quotes for #json.
For simple strings you can just directly pass it as props without the encoding.
This approach is better than creating a new API specifically for this component.
This was the only way that works for me:
<my-component :data="{{ $collection }}"></my-component>
JSON parsed solutions prints data in HTML.

call to ReactJS component in Laravel blade templates

I use Laravel 5.4 and React 15.5.4, code is writing in ES6.
I'd like replace Vue and use React and I did it. But I often will use small components for example 2 in different places of blade template. I don't want use one app component.
I'd like use something like:
<span class="react">
<TestComponent property={true} />
</span>
I can't do it automatically. Now I use
<span data-component="TestComponent" data-props="{property:true}" />
and in app.js
_.each(document.querySelectorAll('[data-react]'), element => {
let props ={};
Array.prototype.slice.call(element.attributes)
.forEach(item => {
props[item.name] = item.value;
if(item.name !== 'data-react'){
element.removeAttribute(item.name);
}
});
ReactDOM.render(React.createElement(reactComponents[element.getAttribute('data-react')],props),element);
});
It works but I need to use add all properties to one react component property and then use for example this.props.out.propery
I also would like set normal component tag in my blade component
I've try to use in app.js
_.each(document.querySelectorAll('.react'), item => {
ReactDOM.render(item.children,item);
});
Someone have any idea to solve this problem?
EDIT
I changed my solution to:
<span data-react="LoginForm" input="{{json(request()->old())}}" error="{{session('error')}}" errors="{{json($errors->getMessages())}}" />
or
<LoginForm data-react="LoginForm" input="{{json(request()->old())}}" error="{{session('error')}}" errors="{{json($errors->getMessages())}}" />
in blade and in resources/assets/js/app.js
var reactComponents = {
LoginForm: require('./components/login').default,
};
_.each(document.querySelectorAll('[data-react]'), element => {
let props ={};
Array.prototype.slice.call(element.attributes)
.forEach(item => {
props[item.name] = item.value;
});
ReactDOM.render(React.createElement(reactComponents[element.getAttribute('data-react')],props),element);
});
It works fine. This is not super clear solution but I have impression that the reasonable.
I can set components name in html code and add props almost same like in JSX.
As far as I know, you can not mix JSX components directly with Blade templates. The only server side rendering available today for React is NodeJS.
What you could do to improve your architecture is add specific HTML tags with certain ids and render the react components in them. So inside Blade you could do something like:
<div id="componentA"></div>
This will act as a place holder in your Blade template for that react component. Then you render your componentA from your app.js like this:
React.render(<ComponentA prop1='valueX'/>, document.getElementById("componentA"))
Remember that in this case the world of react and world of Blade run at different times.
You could use document.getElementsByTagName('LoginForm') getting all the instances and later iterate its attributes. It's clear code but not generic, because it will work just for LoginForm components.
If you want to render any tag name, then maybe it's better to use some attribute as you used with data-react.
getElementsByTagName isn't super supported by old browsers so maybe could a good idea to use jQuery as fallback $('LoginForm')

Resources