BLOG ب LARAVEL & VUE JS الجزء العاشر


فهاد الجزء العاشر من blog ب laravel & vuejs غادي نزيدو الكود لي غادي يمكنا من حذف post إختاريناه أيضا غادي نزيدو الإمكانية ديال تعديل post.

نظرة سريعة بالفيديو


1- حذف post


باش نمسح post من قاعدة البيانات كنمشي ل AdminPanel كنزيد رابط الحذف لي فاش كنضغط عليه كنفذ ل fonction deletePost لي كتاخذ slug ديال ل post من بعد كتعرض رسالة تأكيد يلا ضغطت على نعم كيتمسح ل post من قاعدة البيانات.

الكود ديال AdminPanel بعد التعديل هو :

                                    
                                        //
<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 الخاص بالتعديل


من بعد غادي نمشي ل dossier components فيه غادي تزيد fichier جديد سميه EditPost.vue لي فيه غادي يكون الكود ديال التعديل.

بالنسبة للكود ديال التعديل هو نفس الكود لي زدنا ف AddPost الفرق هو هنا فقط كنسترجعوا ال post لي غادي نعدلوا ونعرضوا المعلومات ديالو فالفورم.

الكود ديال الملف هو :

                                    
                                        //
<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 التعديل


باش يمكنا نديرو التعديل خاص نزيدو route الخاص بالتعديل غادي نمشي ل fichier routes.js فيه كنسترجع ل component EditPost ولي كنزيد route الخاص به ولي كياخذ slug ك paramétre.

الكود ديال الملف routes.js بعد التعديل هو :

                                      
                                        //
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- إضافة رابط التعديل


غادي نرجع ل AdminPanel ونزيد رابط التعديل لي كيدي ل route لي زدنا مع slug ديال ل post لي بغينا نعدلوا.

دبا ل admin ديالنا غادي يخدم كما بغينا بقاو ل users ول catégories ممكن تزيدهم وهذا تمرين ليلك باش تعرف واش قادر تخدم بوحدك.

الكود ديال الملف AdminPanel بعد التعديل هو :

                                        
                                            //
<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>
                                        
                                    

كلمات مفاتيح :