BLOG ب LARAVEL & VUE JS الجزء العاشر
نظرة سريعة بالفيديو
1- حذف post
//
<template>
<div class="container">
<div class="row mt-5 mb-3">
<div class="col-md-12">
<a
data-target="#addPost"
data-toggle="modal"
class="btn mt-5 btn-sm btn-success text-white mb-2"
>
<i class="fa fa-plus"></i>
</a>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Catégorie</th>
<th>Titre</th>
<th>Description</th>
<th>Image</th>
<th>Ajouté par</th>
<th>Le</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="(post,index) in posts.data" :key="index">
<td>{{post.id}}</td>
<td>{{post.category.name}}</td>
<td>{{post.title}}</td>
<td>{{post.body.substr(0,100)}}...</td>
<td>
<img
:src="post.photo"
class="img-fluid mr-2 rounded shadow-sm"
alt
height="60"
width="60"
srcset
/>
</td>
<td>{{post.user.name}}</td>
<td>{{post.added}}</td>
<td class="d-flex flex-row justify-content-center align-items-center">
<router-link :to="post.path" class="btn mr-1 btn-sm btn-primary text-white">
<div class="fa fa-eye"></div>
</router-link>
<a @click="deletePost(post.slug)" class="btn btn-sm btn-danger">
<i class="fa fa-trash"></i>
</a>
</td>
</tr>
</tbody>
</table>
<div class="card-footer d-flex justify-content-center">
<pagination :data="posts" @pagination-change-page="getPosts"></pagination>
</div>
</div>
<AddPost @added="postAdded" />
</div>
</div>
</template>
<script>
import AddPost from "./AddPost";
export default {
data() {
return {
posts: {},
loading: true
};
},
components: { AddPost },
created() {
if (User.isLogged() && User.isAdmin()) {
this.getPosts();
} else {
this.$router.push({ name: "home" });
}
},
methods: {
getPosts(page) {
if (typeof page === "undefined") {
page = 1;
}
axios
.get("/api/posts?page=" + page)
.then(response => {
console.log(response.data);
this.posts = response.data;
})
.catch(err => console.log(err));
},
postAdded() {
this.getPosts();
},
deletePost(slug) {
Swal.fire({
title: "êtes vous sûr?",
text: "Vous ne pouvez pas récupérer cet article",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
cancelButtonText: "Annuler",
confirmButtonText: "Oui supprimer!"
}).then(result => {
if (result.value) {
axios
.delete(`/api/posts/${slug}`)
.then(response => {
Swal.fire({
position: "center",
type: "success",
title: response.data.message,
showConfirmButton: false,
timer: 1500
});
this.getPosts();
})
.catch(error => console.log(error));
}
});
}
}
};
</script>
2- إضافة ل component الخاص بالتعديل
//
<template>
<div class="container">
<div class="row my-4">
<div class="col-md-8 mx-auto mt-5">
<div class="card bg-light">
<h3 class="card-header" id="exampleModalCenterTitle">Modifier un article</h3>
<div class="card-body">
<form @submit="updatePost" enctype="multipart/form-data">
<div class="form-group">
<label for>Catégorie</label>
<option value disabled selected>Veuillez choisir une catégorie</option>
<select v-model="post.category" class="form-control" name="category" required id>
<option
:value="category.id"
v-for="(category,index) in categories"
:key="index"
>{{category.name}}</option>
</select>
</div>
<div class="form-group">
<label for>Titre*</label>
<input
type="text"
name="title"
id
v-model="post.title"
class="form-control"
placeholder="Titre"
required
aria-describedby="helpId"
/>
</div>
<div class="form-group">
<label for></label>
<textarea
v-model="post.body"
class="form-control"
name="body"
id
rows="5"
placeholder="Description"
></textarea>
</div>
<div class="form-group">
<label for>Photo*</label>
<input
type="file"
v-on:change="onImageChange"
class="form-control-file"
name="image"
id="image"
placeholder
aria-describedby="fileHelpId"
/>
</div>
<button type="submit" class="btn btn-primary">Valider</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
post: { title: "", body: "", category: "" },
categories: [],
image: null
};
},
created() {
this.getPost();
this.getCategories();
},
methods: {
onImageChange(e) {
console.log(e.target.files[0]);
this.image = e.target.files[0];
},
getCategories() {
axios
.get("/api/categories")
.then(response => (this.categories = response.data.categories))
.catch(err => console.log(err));
},
getPost() {
axios
.get(`/api/posts/${this.$route.params.slug}`)
.then(res => {
this.post = res.data.post;
this.image = res.data.post.photo;
})
.catch(err => console.log(err));
},
updatePost(e) {
e.preventDefault();
const config = {
headers: { "content-type": "multipart/form-data" }
};
let formData = new FormData();
formData.append("image", this.image);
formData.append("title", this.post.title);
formData.append("body", this.post.body);
formData.append("category_id", this.post.category);
formData.append("user_id", User.isLogged().id);
formData.append("_method", "put");
axios
.post(`/api/posts/${this.post.slug}`, formData, config)
.then(res => {
this.post.title = "";
this.post.body = "";
this.post.category = "";
this.image = null;
Swal.fire({
position: "center",
icon: "success",
title: "Article modifié",
showConfirmButton: false,
timer: 1500
});
this.$router.push({ name: "admin" });
})
.catch(err => console.log(err));
}
}
};
</script>
3- إضافة route التعديل
//
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../components/Home.vue';
import PostDetails from '../components/PostDetails.vue';
import PostCategory from '../components/PostCategory.vue';
import Login from '../components/Login.vue';
import Signup from '../components/Signup.vue';
import Logout from '../components/Logout.vue';
import AdminPanel from '../components/AdminPanel.vue';
import EditPost from '../components/EditPost.vue';
Vue.use(VueRouter)
const routes = [
{
path: '/', component: Home, name: 'home'
},
{
path: '/login', component: Login, name: 'login'
},
{
path: '/signup', component: Signup, name: 'signup'
},
{
path: '/logout', component: Logout, name: 'logout'
},
{
path: '/post/:slug',
component: PostDetails,
name: 'postDetails'
},
{
path: '/post/edit/:slug',
component: EditPost,
name: 'editPost'
},
{
path: '/posts/category/:slug',
component: PostCategory,
name: 'postCategory'
},
{
path: '/admin',
component: AdminPanel,
name: 'admin'
}
];
const router = new VueRouter({
routes,
hashbang: false,
mode: 'history'
})
export default router;
4- إضافة رابط التعديل
//
<template>
<div class="container">
<div class="row mt-5 mb-3">
<div class="col-md-12">
<a
data-target="#addPost"
data-toggle="modal"
class="btn mt-5 btn-sm btn-success text-white mb-2"
>
<i class="fa fa-plus"></i>
</a>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Catégorie</th>
<th>Titre</th>
<th>Description</th>
<th>Image</th>
<th>Ajouté par</th>
<th>Le</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="(post,index) in posts.data" :key="index">
<td>{{post.id}}</td>
<td>{{post.category.name}}</td>
<td>{{post.title}}</td>
<td>{{post.body.substr(0,100)}}...</td>
<td>
<img
:src="post.photo"
class="img-fluid mr-2 rounded shadow-sm"
alt
height="60"
width="60"
srcset
/>
</td>
<td>{{post.user.name}}</td>
<td>{{post.added}}</td>
<td class="d-flex flex-row justify-content-center align-items-center">
<router-link :to="post.path" class="btn mr-1 btn-sm btn-primary text-white">
<div class="fa fa-eye"></div>
</router-link>
<router-link
:to="{path: '/post/edit/' + post.slug}"
class="mr-1 btn btn-sm btn-warning"
>
<i class="fa fa-edit"></i>
</router-link>
<a @click="deletePost(post.slug)" class="btn btn-sm btn-danger">
<i class="fa fa-trash"></i>
</a>
</td>
</tr>
</tbody>
</table>
<div class="card-footer d-flex justify-content-center">
<pagination :data="posts" @pagination-change-page="getPosts"></pagination>
</div>
</div>
<AddPost @added="postAdded" />
</div>
</div>
</template>
<script>
import AddPost from "./AddPost";
export default {
data() {
return {
posts: {},
loading: true
};
},
components: { AddPost },
created() {
if (User.isLogged() && User.isAdmin()) {
this.getPosts();
} else {
this.$router.push({ name: "home" });
}
},
methods: {
getPosts(page) {
if (typeof page === "undefined") {
page = 1;
}
axios
.get("/api/posts?page=" + page)
.then(response => {
console.log(response.data);
this.posts = response.data;
})
.catch(err => console.log(err));
},
postAdded() {
this.getPosts();
},
deletePost(slug) {
Swal.fire({
title: "êtes vous sûr?",
text: "Vous ne pouvez pas récupérer cet article",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
cancelButtonText: "Annuler",
confirmButtonText: "Oui supprimer!"
}).then(result => {
if (result.value) {
axios
.delete(`/api/posts/${slug}`)
.then(response => {
Swal.fire({
position: "center",
type: "success",
title: response.data.message,
showConfirmButton: false,
timer: 1500
});
this.getPosts();
})
.catch(error => console.log(error));
}
});
}
}
};
</script>