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

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);
}

Related

Apollo client's offsetLimitPagination requests for graphql server although the data is available in cache

Whenever I navigate to different pages, data will be added to Apollo's cache. but when I navigate to previous pages, although the data is available in cache. Apollo issues a network request to graphql server.
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
users: {
...offsetLimitPagination(),
read(existing, { args }) {
return (
existing &&
existing.slice(
args?.offset,
args?.offset + args?.limit
)
)
},
}
},
},
},
})
const client = new ApolloClient({
uri: "https://api.spacex.land/graphql/",
cache,
connectToDevTools: true,
})
And my component:
const Users: React.FC = () => {
const [offset, setOffset] = useState(0)
const { loading, data, error, fetchMore } = useUsersQuery({ \\ Generated via graphql-code-gen
variables: { offset, limit: 2 },
})
const fetchMoreHandler = (): void => {
const currentLength = data?.users.length || 0
fetchMore({
variables: { offset: offset + currentLength, limit: 2 },
}).then(() => {
setOffset((ofsset) => ofsset + currentLength)
})
}
const fetchPrevHandler = (): void => {
let currentLength = data?.users.length || 0
if (currentLength === 0) {
currentLength = 2
}
fetchMore({
variables: { offset: offset - currentLength, limit: 2 },
}).then(() => {
setOffset((ofsset) => ofsset - currentLength)
})
}
if (loading) {
return <div>Loading....</div>
}
if (error) {
return <div>Something went wrong!</div>
}
return (
<div className={classes.root}>
{offset > 0 && (
<button type="button" onClick={fetchPrevHandler}>
Prev
</button>
)}
<div>
{data?.users.map((user) => (
<div key={user.id}>
<h6>{user.name}</h6>
</div>
))}
</div>
{(data?.users.length || 0) > 0 && (
<button type="button" onClick={fetchMoreHandler}>
Next
</button>
)}
</div>
)
}
export default Users
And here's the query:
query Users($offset: Int, $limit: Int) {
users(offset:$offset, limit: $limit, order_by:[{timestamp:desc}]) {
id
name
rocket
timestamp
twitter
}
}
When I navigate my cache looks like this:
_APOLLO_CLIENT_.cache.data.data:
{
"users:a75bf714-30e4-4219-8335-e413f8f127ef": {
"id": "a75bf714-30e4-4219-8335-e413f8f127ef",
"__typename": "users",
"name": "HI",
"rocket": "FRIENDS",
"timestamp": "2021-12-22T18:38:09.805832+00:00",
"twitter": null
},
"users:c2317843-8481-4cb6-87e1-16d8f4aa7092": {
"id": "c2317843-8481-4cb6-87e1-16d8f4aa7092",
"__typename": "users",
"name": "simeooone",
"rocket": "tha_rocket",
"timestamp": "2021-12-22T16:14:50.431972+00:00",
"twitter": "#galfh"
},
"ROOT_QUERY": {
"__typename": "Query",
"users": [
{
"__ref": "users:a75bf714-30e4-4219-8335-e413f8f127ef"
},
{
"__ref": "users:c2317843-8481-4cb6-87e1-16d8f4aa7092"
},
{
"__ref": "users:f6358c49-7ce3-491e-8103-48e9e4b847cd"
},
{
"__ref": "users:a04c9b78-3406-4585-ba16-0a4c540fdc23"
}
]
},
"users:f6358c49-7ce3-491e-8103-48e9e4b847cd": {
"id": "f6358c49-7ce3-491e-8103-48e9e4b847cd",
"__typename": "users",
"name": "aemilio",
"rocket": "yo_mum",
"timestamp": "2021-12-22T16:11:14.728876+00:00",
"twitter": "#yo_mum"
},
"users:a04c9b78-3406-4585-ba16-0a4c540fdc23": {
"id": "a04c9b78-3406-4585-ba16-0a4c540fdc23",
"__typename": "users",
"name": "",
"rocket": "oy",
"timestamp": "2021-12-22T16:10:24.420815+00:00",
"twitter": "asd"
}
}
And when I navigate back to show these exact items, still apollo makes network requests!
For other's that are new to Apollo like me and have this question, I figured out that fetchMore function always force network request no matter what. That's by design. If you want to read from cache you shouldn't use fetchMore and do something like this instead:
const [offset, setOffset] = useState(0)
const { loading, data, error } = useUsersQuery({
variables: { offset, limit: 2 },
})
const fetchMoreHandler = (): void => {
const currentLength = data?.users.length || 0
setOffset((ofsset) => ofsset + currentLength)
}
const fetchPrevHandler = (): void => {
let currentLength = data?.users.length || 0
if (currentLength === 0) {
currentLength = 2
}
setOffset((ofsset) =>
ofsset - currentLength < 0 ? 0 : ofsset - currentLength
)
}
and this would be your instance of InMemoryCache:
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
users: {
...offsetLimitPagination(),
read(existing, { args }) {
let res
if (existing) {
res = existing.slice(
args?.offset,
args?.offset + args?.limit
)
}
return res && res.length === args?.limit
? res
: undefined
},
},
},
},
},
})

data not match with response from axios vuejs

im new in vuejs
I have button to get detail data like this:
<button class="btn btn-sm btn-primary" title="Detail" #click="showDetail(task.id)"><span class="fa fa-eye"></span></button>
and the script like this
export default {
data(){
return {
tasks: [],
taskDetail: [],
categoryName: "",
typeName: "",
detailExist: false
}
},
created(){
this.getTasks()
},
methods: {
getTasks(){
axios.get("/task-lists/")
.then(res => {
this.tasks = res.data.data
})
},
showDetail(id){
this.detailExist = false
axios.get("/task-detail/"+id)
.then(res => {
console.log(res)
this.taskDetail = res.data.data
this.detailExist = true
this.collectCategory(this.taskDetail.category)
this.collectType(this.taskDetail.type)
}).catch(error => {
console.log(error)
})
},
startTask(id){
axios.post('/start-task', {id: id, status: 1})
.then(res => {
this.getTasks()
console.log(res.data)
})
},
finishDev(id){
axios.post('/finish-dev', {id: id, status: 2})
.then(res => {
this.getTasks()
})
},
collectCategory(val){
switch (val) {
case 2:
this.categoryName = 'Normal';
break;
case 3:
this.categoryName = 'Emergency';
break;
default:
this.categoryName = 'Standard';
break;
}
},
collectType(val){
switch (val) {
case 2:
this.typeName = 'New Feature';
break;
case 3:
this.typeName = 'Bug Fixing';
break;
default:
this.typeName = 'Revamp';
break;
}
}
}
}
But i got confuse because there is a difference between what i get in res in axios and response api if i see from browser > inspect > network. In browser i get like this
{
"data": {
"id": 1,
"task_no": "RFC123XYZ",
"task_name": "Task View",
"mandays": 2,
"start_date": "2021-10-12",
"status": 2,
"category": 2,
"type": 2,
"description": null,
"cycle": [],
}
}
but in axios i always get value 1 in "status" when i console.log(res).

How to Edit a row in Datatable .net core

I try to update a row in my datatable with .net core. Datatable show data and have a new/delete button that works. But when I try to edit a row, I can't get it to work.
Here is mi index.cshtml. Thanks
"ajax": {
"url": "../LoadIntervaloTrabajo",
"type": "POST",
"data": { "codigo": #Model.codigo},
"datatype": "json"
},
"columns": [
{ "data": "horario", "autowidth": true },
{ "data": "codigo", "autowidth": true },
{ "data": "descripcion", "autowidth": true },
{ "data": "horainicio", "autowidth": true },
{ "data": "duracion", "autowidth": true },
{ "data": "cortentrada", "autowidth": true },
{ "data": "cortintermedia", "autowidth": true },
{ "data": "cortsalida", "autowidth": true },
{ "render": function (data, type, row) {
return "<a href='#' class='btn btn-info' onclick=EditData('" + row.codigo + "'); >Editar</a>";
}
},
function EditData(codigo) {
var table = $("#customerDatatable").DataTable();
var r = table.rows(".selected").nodes()[0];
if ($(table.buttons(".editButton")[0].node).find("span").text() == "Cancel") {
$(r).children("td").each(function (i, it) {
if (i > 0) {
var od = table.cells(it).data()[0];
$(it).html(od);
}
});
setButtons('cancel');
} else {
$(r).children("td").each(function (i, it) {
if (i > 0) {
var h = $("<input type='text'>");
h.val(it.innerText);
$(it).html(h);
}
});
setButtons('edit');
}
I try to update a row in my datatable with .net core.
To implement updating row functionality, you can refer to the following code snippet.
Render two buttons for updating row within the last column
"columns": [
{
"data": "horario", "autowidth": true
},
{ "data": "codigo", "autowidth": true },
{ "data": "descripcion", "autowidth": true },
{ "data": "horainicio", "autowidth": true },
{ "data": "duracion", "autowidth": true },
{ "data": "cortentrada", "autowidth": true },
{ "data": "cortintermedia", "autowidth": true },
{ "data": "cortsalida", "autowidth": true },
{
"render": function (data, type, row) { return "<a href='#' class='btn btn-info' onclick = EditData(this); >Editar</a><a href='#' class='btn btn-info btn-hidden' onclick = UpdateData(this); >Updatear</a>"; }
}
]
JS function
function EditData(btnedit) {
//find current row
var $row = $(btnedit).parent().parent();
var $tds = $row.find("td").not(':nth-child(2)').not(':last');
$.each($tds, function (i, el) {
var txt = $(this).text();
$(this).html("").append("<input type='text' value=\"" + txt + "\">");
});
$(btnedit).siblings("a").removeClass("btn-hidden");
$(btnedit).addClass("btn-hidden");
}
function UpdateData(btnupdate) {
var $row = $(btnupdate).parent().parent();
var horario = $row.find("td:nth-child(1)").find("input").val();
var codigo = $row.find("td:nth-child(2)").text();
var descripcion = $row.find("td:nth-child(3)").find("input").val();
var horainicio = $row.find("td:nth-child(4)").find("input").val();
var duracion = $row.find("td:nth-child(5)").find("input").val();
var cortentrada = $row.find("td:nth-child(6)").find("input").val();
var cortintermedia = $row.find("td:nth-child(7)").find("input").val();
var cortsalida = $row.find("td:nth-child(8)").find("input").val();
var data_for_update = { "horario": horario, "codigo": codigo, "descripcion": descripcion, "horainicio": horainicio, "duracion": duracion, "cortentrada": cortentrada, "cortintermedia": cortintermedia, "cortsalida": cortsalida };
//console.log(data_for_update);
//make request to update data
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
url: "/{controller_name_here}/Update",
data: JSON.stringify(data_for_update),
success: function (json) {
console.log(json);
var $tds = $row.find("td").not(':nth-child(2)').not(':last');
$.each($tds, function (i, el) {
var txt = $(this).find("input").val()
$(this).html(txt);
});
$(btnupdate).siblings("a").removeClass("btn-hidden");
$(btnupdate).addClass("btn-hidden");
},
//...
});
}
CSS style
.btn-hidden{
display:none;
}
Test Result

Transforming object data to array for d3plus-react

I have an api that returns data in the following format:
{
"Information Technology": {
"Name": "Information Technology",
"Change": "0.82%"
},
"Consumer Staples": {
"Name": "Consumer Staples",
"Change": "0.19%"
}
}
I want to convert it to the following format inside my d3plus visualizations:
[
{
"Name": "Information Technology",
"Change": "0.82%"
},
{
"Name": "Consumer Staples",
"Change": "0.19%"
}
]
How do I do this. Here's my React component that uses d3plus:
function Chart() {
const methods = {
groupBy: 'Name',
data: 'https://example.com/api/sectors-performance',
size: d => d.Change
};
return <Treemap config={methods} />;
}
There was a small hint in the docs which helped me come up with this solution:
function Chart() {
const methods = {
groupBy: 'id',
data: 'https://example.com/api/sectors-performance',
size: d => d.value
};
const formatter = d =>
Object.keys(d).map(key => ({
id: d[key].Name,
value: numeral(d[key].Change).value()
}));
return <Treemap config={methods} dataFormat={formatter} />;
}
The trick is to send a formatter as a property!

Laravel vue-router getting single data

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?

Resources