Laravel compact in vue - laravel

I want to know how can I pass variables to vue component in laravel?
When we work with blade we can pass variables like:
$now = Carbon::now();
return view('xxxxxxxx', compact('now');
That way I can use $now in xxxxxxxx blade file. But what about vue components? we usually return data by json for components and with axios route we get that info no way to specify such data for exact component of us?
What if I want to use $now = Carbon::now(); in single.vue component?
How can I make that happen?
Update
Here is what I want to do with timing as carbon cannot be used (based on comments) I want to use moment.js
Logic
Let users bid if project deadline hasn't arrived
Don't let users bid if project deadline has arrived
template
<template v-if="`${project.deadline | timeAgo}`">
pssed (will be replaced by button is just for test)
</template>
<template v-else>
still have time (will be replaced by button is just for test)
</template>
script
var moment = require('moment');
export default {
data(){
return {
project : '',
}
},
mounted: function() {
// I found this code by google not sure if is currect!
Vue.filter('timeAgo', function(value){
return moment(value) >= fromNow()
});
},
}
Based on my code above here is the results

Try this:
This is my routes, simply I just render a view with some pre-defined variables
Route::get('/', function () {
return view('welcome', [
'now' => Carbon::now(),
'deadline' => Carbon::now()->addHours(2)
]);
});
And this is my view file. Here I have custom element named: example-component. And this is how I passed PHP variables to Vue component using props.
And pass your data to window like so:
<script>window.data = #json(compact('now', 'deadline'))</script>
And this is my Vue component file:
<template>
<h1>
<span v-if="isPassed">This job is passed</span>
<span v-else>You have to finish this job</span>
{{ parsedDeadline | timeFromX(parsedNow) }}
</h1>
</template>
<script>
const moment = require('moment');
export default {
props: {
now: {
type: String,
default: () => window.data.now.date // since `now` is an object, you need to access the `date` property to get plain string date that moment can parse
},
deadline: {
type: String,
default: () => window.data.deadline.date // same as above
}
},
computed: {
parsedNow () {
return moment(this.now)
},
parsedDeadline () {
return moment(this.deadline)
},
isPassed () {
return this.parsedNow.isAfter(this.parsedDeadline)
}
}
}
</script>
Here's the documentation about computed and filters. You may NEVER add a filter in a mounted function since it may leads to memory leak. Here's how I add my filter. In your app.js (assumed you're using default Laravel Vue preset)
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('example-component', require('./components/ExampleComponent.vue'));
Vue.filter('timeFromX', (a, b) => a.from(b)); // TADAAA...!!!
const app = new Vue({
el: '#app'
});
UPDATE
If you want to try this, you may edit the routes/web.php and change the deadline value:
Route::get('/', function () {
return view('welcome', [
'now' => Carbon::now(),
'deadline' => Carbon::now()->subHours(2), // Passed 2 hours ago
// 'deadline' => Carbon::now()->addHours(2), // In 2 hours
]);
});
Checkout the Carbon docs here about addition and subtraction.
UPDATE II
If you got error in app.js from the code above, maybe your transpiler doesn't know about arrow-parens.
// Looks like arrow-parens not working, see code below
// Vue.filter('timeFromX', (a, b) => a.from(b)); // TADAAA...!!!
// Change it to this ???
Vue.filter('timeFromX', function (a, b) {
return a.from(b);
});

Related

Laravel vue.js 2 response view won't output parameters

I am new to vue.js and recently been assigned a project to learn it and refactor old code to vue.js like some of the existing pages already have been and I am having some issues. vue2
My question:
I have a get request with a controller that has a response something like this:
return Response::view('somebladefile', ['title' => 'some_title']);
Within the blade file I include a js file which will be responsible for vue
<script src="{{ cdnMix('somefile.js') }}"></script>
somefile.js contents:
const IndexPage = Vue.component('indexpage',require('./somepath/IndexPage.vue').default);
window.indexPageInstance = new IndexPage().$mount('#vuecontainerid');
So now within IndexPage.vue i would like to access variable 'title' that I passed with the response to my blade file originally. What would be the best way one would go about it? Tried few ways I found on YT/Google but without success, this is my code currently, any pointers would be appreciated, thanks!
<template>
<HeaderComponent></HeaderComponent>
</template>
<script>
const HeaderComponent = require('./somepath/HeaderComponent.vue').default;
export default {
name: 'indexpage',
props: ['data'],
components: {
'HeaderComponent': HeaderComponent,
},
data: function() {
return {
// why doesn't it work!!: '',
}
},
mounted: function() {
console.log(this.data);
}
}
</script>
Vue works, but I can't seem to be able to access 'title' variable.
Also I would like to be able to access 'title' within other components like the HeaderComponent I have within indexpage

How to pass simple user input from Vue to Laravel Controller?

I'm trying to create something simple with Laravel + Vue.js without having to use the database.
I have two inputs from a Vue Component, and I was wondering how I pass those two values back into a Controller.
Usually, you use Axios to complete CRUD functions, but I honestly just want to pass simple values to the backend, and then have the backend transfer an array into back to the Vue Component.
Any advice? All the decent tutorials online usually use a database to transfer data back and forth.
Have you heard of inertiajs?
inertiajs allows you to create fully client-side rendered, single-page apps, without much of the complexity that comes with modern SPAs. It does this by leveraging existing server-side frameworks.
I was able to send data back and forth using axios
Here is what I had for my Vue Component:
<template> ... </template>
<script>
export default {
data() {
return {
name: '',
days: ''
}
},
methods: {
getData() {
axios.get('/api/urihere', {
params: {
name: this.name,
days: this.days
}
}).then((response) => {
console.log(response.data)
}).catch((error) => {
console.log(error)
})
}
},
mounted() {
//
}
}
</script>
While I had you had a simple get for Routes
Route::get('/urihere', [UrihereController::class, 'someMethod']);
and inside the said-controller
public function someMethod(Request $request)
{
return [$request->name, $request->days];
}

Create global method vue on app.js laravel

I want create global method to translate message using Laravel-JS-Localization
But when i call the method using vue mustache got an error like this:
Property or method "trans" is not defined on the instance but referenced during render.
Make sure that this property is reactive.
Here my laravel app.js code:
require('./bootstrap');
window.Vue = require('vue');
Vue.component('dashboard', require('./components/Dashboard').default);
const app = new Vue({
el: '#vue',
methods: {
trans: function (key) {
return Lang.get(key);
},
},
});
Dashboard.vue code :
<template>
<p>{{ trans('common.welcome') }}</p>
</template>
<script>
data () {
return {
name: '',
}
},
</script>
dashboard.blade.php code :
..........
<div class="col-9" id="vue">
<dashboard></dashboard>
</div> <!--c end col-8 -->
..........
I would probably go with creating a Plugin. For example
Vue.use({
install (Vue) {
Vue.prototype.$trans = Lang.get
}
})
Adding this to your app.js code before creating any components or new Vue({...}) will mean all your components will have access to the $trans method.
Alternatively, you can create a Global Mixin but these aren't strongly recommended.
Use global mixins sparsely and carefully, because it affects every single Vue instance created, including third party components
Vue.mixin({
methods: {
trans (key) {
return Lang.get(key)
}
}
})

How to add loader in vue js

How to add Loading effect in VUE js plus Laravel.
This is a single page website in vuejs, i want to add loader when i change the route.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Help please in VUE js + Laravel
add this line of code in your app.js file
router.beforeEach((to, from, next) => {
// add loader
next()
})
router.afterEach(() => {
// terminate you loader
})
so Full file is
window.Vue = require('vue');
import VueRouter from 'vue-router';
import VueProgressBar from 'vue-progressbar'
window.Fire = new Vue();
Vue.use(VueProgressBar, {
color: 'rgb(143, 255, 199)', //normal color for progress bar
failedColor: 'red', //color for failed progress bar
height: '2px'//height of progress bar can be changed here
})
Vue.component(HasError.name, HasError)
Vue.component(AlertError.name, AlertError)
Vue.use(VueRouter);
window.Fire = new Vue();
let routes = [
{
path: '/',
name: 'posts',
component: post,
},
{
path: '/general',
name: 'dashboard',
component: Dashboard,
},
];
let router = new VueRouter({
routes // short for `routes: routes`
});
router.beforeEach((to, from, next) => {
// add loader
VueProgressBar .start();
next()
})
router.afterEach(() => {
// terminate you loader
VueProgressBar.finish();
})
const app = new Vue({
el: '#app',
router,
data: {},
methods: {}
});
window.Fire = new Vue();
If you are requesting while browsing through the pages, the loader can work accordingly.
<script>
export default {
data: () => ({
loaderIsActive: false,
items: null,
}),
mounted() {
this.fetch();
},
methods: {
async fetch() {
this.loaderIsActive = true;
this.items = await axios.post('YOUR API');
this.loaderIsActive = false;
}
}
}
In this way you can use it.

How can I preload data for vue.js in Laravel Spark?

According to the docs and examples, I have perfectly working code that functions great:
Vue.component('admin-competitions-index', {
data: function() {
return {
competitions: []
}
},
mounted() {
this.$http.get('/api/admin/competitions')
.then(response => {
this.competitions = response.data;
});
},
methods: {
/**
* Toggle whether a competition is published or not.
*/
togglePublished(competition) {
Spark.patch(`/api/admin/competitions/togglePublished/${competition.id}`, this.togglePublishedForm)
.then(response => {
competition.is_published = response;
});
}
}
});
However, I'd like to change this code to save the extra request that is made on page load. I don't see a convention anywhere in Laravel or Spark where this is done. I'm guessing that all I need to do is set a JS variable but I'm not sure where it would be proper to do so.
I also understand that this kind of defeats the point of using vue for asynchronous loading, but nevertheless I would like to learn this. I think it will become more useful if I were to use vue for my #show restful requests where even if I wanted everything to load asynchronously I would at the very least have to supply vue with the competition ID that I want loaded.
This works out of the box:
#section('scripts')
<script>
var competition = {!! $competition !!};
</script>
#endsection

Resources