Laravel vue-router getting single data - laravel

I'm trying to return my data such as posts by their slug but so far I couldn't make it by Vue-router
Code
controller
public function single($slug)
{
$post = Post::where('slug', $slug)->first();
return response()->json([
"post" => $post
], 200);
}
blog.vue
<li v-for="post in posts" :key="post.slug">
<router-link to="/blog/${post.slug}">{{ post.title }}</router-link>
</li>
<script>
export default {
name: 'list',
mounted() {
if (this.posts.length) {
return;
}
this.$store.dispatch('getPosts');
},
computed: {
posts() {
return this.$store.getters.posts;
}
}
}
</script>
vuex store.js
state: {
posts: []
},
getters: {
posts(state) {
return state.posts;
}
},
mutations: {
updatePosts(state, payload) {
state.posts = payload;
}
},
actions: {
getPosts(context) {
axios.get('/api/posts')
.then((response) => {
context.commit('updatePosts', response.data.posts);
})
}
}
Problem
The problem is that i get this kind of url in my loop
site.pp/blog/${post.slug}
I should get something like:
site.pp/blog/hello-world
Question
Where did I make mistake? and how to fix it?

Related

Laravel Vue.js after patch request get doesn't load all the data

I want to dynamically hide the "Sign up" button when all the places for the event have been taken. I also update the list of signed-up users.
After clicking on the Signup button the data is saved correctly on the backend but the frontend displays only the pictures of players and there are the usernames. After refreshing the page I can see the usernames and photos. How can I fix my code so all the data will be displayed after the patch?
I'm using 2 Vue components:
AddPlayesComponent
<template>
<div>
<form v-if="freePlaces == true || freePlaces == 1" #submit.prevent="submit()">
<button type="submit" name="participant">Sign up</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
freePlaces: "",
url: "",
}
},
created() {
this.getUrl();
this.fetchStatus();
this.showForm();
},
methods: {
getUrl() {
let id = window.location.href.split('/').pop();
this.url = "/events/" + id + "/team" ;
},
fetchStatus() {
let id = window.location.href.split('/').pop();
axios.get('/events/'+ id + '/availabilty').then((response) => {
this.freePlaces = response.data;
})
},
showForm() {
Echo.channel('team-list-count')
.listen('.players-allowed', (data) => {
this.freePlaces = data.playersAllowed;
})
},
submit() {
axios.post(this.url, {
_method: 'patch'
})
.then(response => {
console.log(response.data);
})
.catch(e => {
console.log("Error is");
console.log(e.data);
});
}
},
computed: {
availabilePlaces() {
return this.freePlaces;
return this.url;
}
}
}
</script>
and TeamListComponent
<template>
<div>
<div v-for="(player, key) in team">
<img :src="'/storage/' + player.profil_photo" alt="profile picture " >
{{ player.username }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
team: [],
}
},
created() {
this.fetchTeam();
this.AddNewPlayerListener();
this.DeleteNewPlayerListener();
},
methods: {
fetchTeam() {
let id = window.location.href.split('/').pop();
axios.get('/events/'+ id + '/team').then((response) => {
this.team = response.data;
})
},
AddNewPlayerListener() {
Echo.channel('team-list')
.listen('.updated-team', (data) => {
this.team = data.team;
})
},
DeleteNewPlayerListener(){
Echo.channel('team-list-delete')
.listen('.updated-team', (data) => {
this.team = data.team;
})
}
},
computed: {
teamList() {
return this.team;
}
}
}
</script>
Controller contains this funcion:
protected function addPlayer($event) {
$registered = $event->registered_participants;
$registered++;
$allowed = $event->allowed_participants;
if($allowed <= $registered) {
$playersAllowed = false;
event(new ParticipantsCounter($playersAllowed));
if($allowed < $registered) {
return redirect()->route('event.show', [ 'event' => $event ]);
}
}
$event->registered_participants = $registered;
$event->save();
$profile = auth()->user()->profile;
$profile->participate()->syncWithoutDetaching([$event->id], false);
$team = $event->participants()->get();
foreach ($team as $player) {
$user = User::where('id', $player->user_id)->first();
$player->username = $user->username;
}
event(new NewParticipant($team));
return redirect()->route('event.show', [ 'event' => $event ]);
}
Data after patch request:
{ "id": 5,
"created_at": "2022-04-12T20:35:03.000000Z",
"updated_at": "2022-04-12T20:35:40.000000Z",
"user_id": 5,
"name": "Marlena",
"familyname": "Test",
"location": "Amblève",
"gender": "x",
"birthdate": "2000-12-12",
"favorite_sport": "hockey",
"biography": "Here comes biography",
"profil_photo": "profiles/kbERb4XrXnu379rtCcyWwb46pOq9UQAtkTKgr42W.jpg" }
Data after refreshing page:
{ "id": 5,
"created_at": "2022-04-12T20:35:03.000000Z",
"updated_at": "2022-04-12T20:35:40.000000Z",
"user_id": 5,
"name": "Marlena",
"familyname": "Test",
"location": "Amblève",
"gender": "x",
"birthdate": "2000-12-12",
"favorite_sport": "hockey",
"biography": "Here comes biography",
"profil_photo": "profiles/kbERb4XrXnu379rtCcyWwb46pOq9UQAtkTKgr42W.jpg",
"username": "testUser",
"pivot": {
"event_id": 1,
"profile_id": 5,
"created_at": "2022-04-25T15:27:37.000000Z",
"updated_at": "2022-04-25T15:27:37.000000Z" }
}
Update:
I solved it by creating an empty array where I push each player after adding a username.
$oldTeam = $event->participants()->get();
$team = [];
foreach ($oldTeam as $player) {
$user = User::where('id', $player->user_id)->first();
$player->username = $user->username;
array_push($team, $player);
}

Laravel vue js Opening video in modal onClick not working

So what i'm trying to do is pretty simple but for some reason is not working please let me show you.
This is my navigation bar written in vue js and here i'm holding almost all my vue components.
Navigation.vue
<template>
<single-video :user_id="user_id" :video="this.video" :videoUser="this.videoUser"
:videoOptions="videoOptions"></single-video>
</template>
<script>
export default {
name: "Navigation",
data: function () {
return {
user_id: user_id,
// isLogin: isLogin,
video: {},
videoUser: {},
videoOptions: {
autoplay: true,
controls: true,
sources: [
{
src: "",
type: "application/x-mpegURL"
}
]
}
}
},
methods: {
openVideoModal(video){
this.videoOptions.sources[0].src = 'storage/videos/' + video.id + '/' + video.id + '.m3u8';
axios.get('video/' + video.channel_id).then(response => {
this.videoUser = response.data;
}).catch(error => {
if (error.response.status == 422) {
this.errors = error.response.data.errors;
}
console.log('Error');
});
this.video = video;
$('#singleVideo').modal('show');
},
},
}
</script>
In one of my child component i have this method which calling openVideoModal() function in navigation. With the video id. So far it's working.
<a #click="$parent.openVideoModal(video)">
This one is my single video component which display the video itself.And is in modal ("singleVideo" modal)
single-video.vue
<video v-if="this.video"
ref="videoPlayer"
id="my-video"
class="video-js vjs-default-skin vjs-big-play-centered"
controls
preload="auto"
width="749"
height="421"
:poster="this.video.thumbnail"
data-setup="{}">
</video>
<script>
import videojs from 'video.js';
export default {
props: ['user_id', 'video', 'videoUser', 'videoOptions'],
data: function () {
return {
errors: {},
singleVideo: {},
player: null
}
},
mounted() {
if(this.videoOptions.sources[0].src) {
this.player = videojs(this.$refs.videoPlayer, this.videoOptions, function onPlayerReady() {
})
}
},
methods: {
beforeDestroy() {
if (this.player) {
this.player.dispose()
}
}
}
</script>
Please don't delete my question it is very important to me to solve this. I'm going nuts over it. :(

How to pass data from a child component to the parent component using Laravel and Vue

I am using Vue.js 2 and Laravel 7.
I want to pass some errors from the child component to the parent controller. But for some reasons emit did not work.
This is the method of the child component AllocateTask:
methods: {
assignTask: function() {
this.form.task_id = this.user.tasks;
this.form.user_id = this.dev.id;
alert(this.form.task_id);
alert(this.form.user_id);
axios.post('/ticketsapp/public/api/store_task_user', this.form)
.then((response) => {
console.log(response.data);
alert('ok');
this.errors = response.data;
alert(Object.keys(this.errors).length);
if (Object.keys(this.errors).length === 0) {
alert('viva');
} else {
alert('noviva');
this.$emit('failure');
this.$emit('pass-errors', this.errors);
}
})
.catch(error => {
alert('no ok');
console.log(error);
});
}
}
This is the parent component TheReporterTickets:
<template>
<div>
<allocate-task :dev="dev" :tasks="tasks" #pass-errors="onPassErrors" #failure="displayErrors=true" #success="displaySuccess=true"></allocate-task>
<hr>
<validated-errors :errorsForm="errorsTicket" v-if="displayErrors===true"></validated-errors>
</div> </template>
<script>
import AllocateTask from "./AllocateTask.vue"
import ValidatedErrors from "./ValidatedErrors.vue"
export default {
components: {
'allocate-task': AllocateTask,
'validated-errors': ValidatedErrors
},
props: {
dev: {
type: Array,
required: true,
default: () => [],
},
tasks: {
type: Array,
required: true,
default: () => [],
}
},
mounted() {
console.log('Component mounted.');
},
data: function() {
return {
displayErrors: false,
errorsTicket: []
}
},
methods: {
onPassErrors(value) {
alert('error');
console.log('errors passed');
const values = Object.values(value);
this.errorsTicket = values;
console.log(this.errorsTicket);
}
}
} </script>
As you can imagine, I am unable to call the method onPassErrors located in the parent component. I visualize correctly the alert in the else statement of the child component, so I suppose that I am unable to pass the data from the child to the parent component.
Can help?

Query relationship with v-autocomplete in Vuetify [ Laravel ]

I use dropdown v-autocomplete in Vuetify and i want to query relationship from laravel. When select in input field in v-autocomplete, its work well, its show name that i want to query, but when i selected on it, it show to default value.
Here my Vuetify
<template>
<v-autocomplete
:items="purchases"
dense
solo
v-model="model"
item-text="name"
item-value="name"
return-object
clearable
#input="addTocart"
>
<template v-slot:item="{ item }">
{{ item.product.name }}
</template>
</v-autocomplete>
</template>
In my script
<script>
export default {
name: 'Add Purchase',
created() {
this.fetchPurchase()
},
data() {
return {
products: [],
purchases: [],
model: [],
items: [],
purchase_status: ['Received', 'Partial', 'Pending', 'Ordered'],
discount: 0.00,
tax: 0.00,
shipping_cost: 0.00,
}
},
computed: {
total() {
return this.products.reduce((total, item) => {
return total + item.unit;
}, 0);
}
},
methods: {
fetchPurchase() {
this.$axios.$get(`api/purchase`)
.then(res => {
this.purchases = res.data;
console.log(res);
})
.catch(err => {
console.log(err)
})
},
addTocart (item) {
if(this.items.includes(item)) {
alert("already there");
}else {
this.items.push(item);
}
item.unit = 1;
},
removeItem(index) {
this.items.splice(index, 1)
},
}
}
</script>
Is there a way that i can archieve this? Thanks in advance..

Prop mutating warning in VUE

I got an vue-warning (which results to as an error on my end coz my code is not working) that says:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "editmode"
With it, tried the suggestion here but can't make it work. Below is my work:
props:{
editmode:{
type: Boolean,
default: false,
}
},
methods:{
toggleM(){
var editmode = this.editmode;
editmode = !editmode;
this.editmode = editmode;
if(editmode == false){
//dothis
}else{
//dothat
}
},
}
TEMPLATE
<template>
<div class="ui-table-container-body">
<div class="ui-table" v-if="Boolean(items.length) || Boolean(Object.keys(items).length)" v-cloak>
<ui-table-body ref="body" v-model="items"
:editmode="editmode"
>
</ui-table-body>
</div>
</div>
</template>
The line this.editmode = editmode; is the one pointed in my console, is there any way I can surpass this?
You must use a data variable as a gateway to your prop.
In your component, the code code should look like this:
props:{
editmode:{
type: Boolean,
default: false,
}
},
data: {
dataEditMode = false
},
watch: {
'editmode': {
handler: 'onEditmodeChanged',
immediate: true,
},
'dataEditMode': {
handler: 'onDataEditModeChanged'
}
},
methods:{
toggleM(){
var editmode = this.dataEditMode;
editmode = !editmode;
this.dataEditMode = editmode;
if(editmode == false){
//dothis
}else{
//dothat
}
},
onEditmodeChanged (newVal) {
this.dataEditMode = newVal
},
onDataEditModeChanged (newVal) {
this.$emit('editmodeChanged', newVal)
}
}
and the the inclusion of this component in your parent-component should look like this:
<my-component-name :editmode="editmode" #editmodeChanged="(e) => { editmode = e }"></my-component-name>
You shouldn't mutate props from the component itself. See the One Way Data Flow section of the guide. You can use a prop as the initial value, and then keep a value in the data section and mutate that:
props: {
editmode: {
type: Boolean,
default: false,
}
},
data () {
return {
emode: this.editmode,
}
},
methods: {
toggleM () {
let editmode = this.emode;
editmode = !editmode;
this.emode = editmode;
if (editmode == false) {
// dothis
} else {
// dothat
}
},
}
Demo
Vue.component('editbox', {
template: '<div>' +
'<button #click="toggleM">{{ btext }}</button>' +
'<input v-if="emode" />' +
'</div>',
props: ['editmode'],
data () {
return {
emode: this.editmode,
}
},
computed: {
btext () {
return this.emode ? "Text" : "Edit";
}
},
methods:{
toggleM() {
this.emode = !this.emode;
},
}
})
var app = new Vue({
el: '#app',
data: {
mode: true,
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<editbox :editmode="mode" />
</div>
I would send back an event to the parent so it could modify its value:
For example (not tested):
Child Component
props:{
editmode:{
type: Boolean,
default: false,
}
},
methods:{
toggleM(){
var editmode = !this.editmode;
this.$emit('changeEditMode', editmode);
if (editmode == false){
//dothis
} else {
//dothat
}
},
}
Parent
<child-component #changeEditMode="editModeChanged" :editmode="editmode"></child-component>
...
methods:{
editModeChanged(value){
this.editmode = value
},
}

Resources