0

i'm working on an laravel vuejs spa. I try to update a post from the admin. I send the form datas on creating a new FromData who are sending with and axios request.

But the controller send me the error:

message: "The given data was invalid."
errors: {name: ["The name field is required."], description: ["The description field is required."]}
  • Here is the post/edit.vue
<template>
  <div class="post-edit">
    <form id="form" @submit.prevent="createPost">
      <!-- Title -->
      <div class="form-group">
        <label for="title" class="form-label">Title</label>
        <input id="title" v-model="post.title" :title="post.title" type="text"
               name="title" class="form-control"
        >
      </div>

      <!-- Category -->
      <div class="form-group">
        <label for="category" class="form-label">Category</label>
        <select id="category" v-model="post.category" :value="post.category" :category="post.category"
                name="category" class="form-control"
        >
          <option disabled :value="post.category">
            Choisir une catégorie
          </option>
          <option v-for="(category) in categories" :key="category.id" :value="post.category">
            {{ category.name }}
          </option>
        </select>
      </div>

      <div class="post-edit-image">
        <img :src="path + post.image" alt="">
      </div>

      <!-- Image -->
      <div class="form-group post-edit-select-image">
        <label for="content" class="form-label">Image</label>
        <input type="file" name="image" class="form-control" @change="selectedImage">
      </div>

      <!-- Content -->
      <div class="form-group">
        <label for="content" class="form-label">Content</label>
        <editor
          id="content"
          v-model="post.content"
          api-key="the-api-key"
          :init="{
            height: 500,
            menubar: false,
            plugins: [
              'advlist autolink lists link image charmap print preview anchor',
              'searchreplace visualblocks code fullscreen',
              'insertdatetime media table paste code help wordcount'
            ],
            toolbar:
              'undo redo | formatselect | bold italic backcolor | \
               alignleft aligncenter alignright alignjustify | \
               bullist numlist outdent indent | removeformat | help'
          }"
          name="content"
          :content="post.content"
        />
      </div>

      <!-- Submit Button -->
      <button type="submit" class="btn btn-primary">
        Sauvegarder
      </button>
    </form>
  </div>
</template>

<script>
import axios from 'axios'
import { mapGetters } from 'vuex'
import Editor from '@tinymce/tinymce-vue'

export default {
  middleware: 'auth',

  components: {
    'editor': Editor
  },

  props: ['id'],

  data () {
    return {
      post: {
        id: '',
        user_id: '',
        title: '',
        category: '',
        image: null,
        content: ''
      },
      path: '/images/post/thumbnail/'
    }
  },

  computed: {
    ...mapGetters({
      user: 'auth/user',
      categories: 'categories/categories'
    })
  },

  beforeCreate () {
    this.$store.dispatch('categories/fetchCategories')
  },

  created () {
    this.getPostById(this.$route.params.id)
  },

  methods: {
    selectedImage (event) {
      this.post.image = event.target.files[0]
    },

    getPostById (id) {
      axios.get('/api/posts/edit/' + id)
        .then((response) => {
          this.post.id = response.data.id
          this.post.user_id = response.data.user_id
          this.post.title = response.data.title
          this.post.category = response.data.category
          this.post.image = response.data.image
          this.post.content = response.data.content
        })
        .catch((error) => {
          console.log(error)
        })
    },
    createPost (e) {
      this.post.userId = this.user.id
      let formData = new FormData(e.target)
      let id = this.post.id

      formData.append('title', this.post.title)
      formData.append('category', this.post.category)
      formData.append('image', this.post.image)
      formData.append('content', this.post.content)

      axios.patch('/api/posts/update/' + id, formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      })
        .then((response) => {
          console.log(response)
          this.$store.dispatch('posts/fetchPosts')
        })
        .catch((error) => {
          console.log(error)
        })

      this.$router.push({ name: 'admin' })
    }
  }
}
</script>
  • And here the laravel controller PostController@update method
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(PostUpdateRequest $request, $id)
    {
        $post = Post::findOrFail($id);
        $post->update($request->getValidRequest());
        return response()->json($request, 200);
    }
  • And the custom validator PostUpdateRequest.php
/**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title' => 'required|max:250|unique:posts,title',
            'category' => 'required',
            'image' => 'mimes:jpg,jpeg,png,bmp',
            'content' => 'required'
        ];
    }

    public function getValidRequest()
    {
        $image = $this->file('image');
        $slug = Str::slug($this->input('title'));

        if (isset($image)) {

            $imageExt = $image->getClientOriginalExtension();
            $currentDate = Carbon::now()->toDateString();
            $imageName = $slug . '-' . $currentDate . '-' . uniqid() . '.' . $imageExt;

            if (!Storage::disk('public')->exists('post')) {
                Storage::disk('public')->makeDirectory('post');
            }
            if (!Storage::disk('public')->exists('post/thumbnail')) {
                Storage::disk('public')->makeDirectory('post/thumbnail');
            }

            $path = "images/";

            $postImage = Image::make($image)->resize(null, 1060, function ($constraint){
                $constraint->aspectRatio();
            })->save(public_path($path).'post/'.$imageName);

            $thumbnail = Image::make($image)->fit(550, 550)
                ->save(public_path($path).'post/thumbnail/'.$imageName);

        }

        return [
            'user_id' => Auth::user()->getAuthIdentifier(),
            'category_id' => $this->input('category'),
            'title' => $this->input('title'),
            'slug' => $slug,
            'content' => $this->input('content'),
            'image' => $imageName,
            'is_published' => $this->input('is_published') ?? false,
        ];
    }
  • The api route in laravel
Route::patch('/update/{id}', 'Backend\PostController@update');

I use practically the same things to store a post, and it work's fine, the only difference is here i pass an id for the post to update and i not use the post method but patch for axios and the route (and i try with put, it's the same error).

thank's for your time !

1 Answer 1

1

append '_method' field with value 'PATCH' to formData

    formData.append('_method', 'PATCH')

and send axios request post request to update data

   axios.post('/api/posts/update/' + id, formData, {
    headers: {
        'Content-Type': 'multipart/form-data'
    }
})
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.