Form data post to Laravel backend

Published 5 days ago by boldstar

Hi, i am trying to submit data to my laravel backend using axios. I need to be able to capture the id of the client that the engagement will be linked to and im struggling to understand how i can access that information so i can send it with the post request.

this is the form component

 <form @submit.prevent="addEngagement" class="d-flex-column justify-content-center">
          <div class="form-group">
            <input type="text" class="form-control mb-3" placeholder="Client" v-model="engagement.client_id">
            <select class="form-control mb-3" id="type" v-model="engagement.return_type">
              <option v-for="type in types" :key="type.id" :value="type">{{ type }}</option>
            </select>
            <input type="text" class="form-control mb-3" placeholder="Year" v-model="engagement.year">
            <input type="text" class="form-control mb-3" placeholder="Assign To" v-model="engagement.assigned_to">
            <input type="text" class="form-control mb-3" placeholder="Status" v-model="engagement.status">

            <button type="submit" class="btn btn-lg btn-primary d-flex justify-content-start">Create</button>
          </div>
        </form>

this is the form component data

engagement: {
        client_id: '',
        return_type: null,
        year: '',
        assigned_to: '',
        status: '',
      },

this is the form component method

 methods: {
    addEngagement(e) {
      if(!this.engagement.client_id || !this.engagement.return_type || !this.engagement.year ){
        return
      } else {
        this.$store.dispatch('addEngagement', {
          id: this.idForEngagement,
          client_id: this.engagement.client_id,
          return_type: this.engagement.return_type,
          year: this.engagement.year,
          assigned_to: this.engagement.assigned_to,
          status: this.engagement.status,
        })
        e.preventDefault();
      }
      e.preventDefault();
      this.engagement = "" 
      this.idForEngagement++
      this.$router.push('/engagements')
    },
  },

Now when i capture the data from here it dispatches my store for the method addEngagement below

addEngagement(context, engagement) {
      axios.post('http://traxit.test/api/engagements', {
        id: engagement.id,
        client_id: engagement.client_id,
        return_type: engagement.return_type,
        year: engagement.year,
        assigned_to: engagement.assigned_to,
        status: engagement.status,
        done: false
      })
      .then(response => {
        context.commit('getClientEngagement', response.data)
      })
      .catch(error => {
        console.log(error)
      })

and sends it the laravel backend to my api route here

Route::post('/engagements', '[email protected]');

From here it would be process by the EngagementsController...

So currently i have the the client_id as a basic input but Im wondering if there is away to capture the id of the client i am trying to create the engagement for because in laravel the engagement will have belongsTo() relationship with the client.

The client id is supposed to be referencing my client table and i dont know how to capture that data without having to manually put it in each time before submitting

this is the controller handling the form post

public function store(Request $request)
    {
        $data = $request->validate([
            'client_id' => 'required|integer',
            'return_type' => 'required|string',
            'year' => 'required|string',
            'status' => 'required|string',
            'assigned_to' => 'required|string',
            'done' => 'required|boolean'
        ]);

        $engagement = Engagement::create([
            'client_id' => $request->client_id,
            'return_type' => $request->return_type,
            'year' => $request->year,
            'status' => $request->status,
            'assigned_to' => $request->assigned_to,
            'done' => $request->done,
        ]);

        return response($engagement, 201);
    }

Hopefully I am being detailed enough on what my issue is. Please as for my more clarity if needed!!

tykus
tykus
5 days ago (657,630 XP)

Is the client_id somehow related to the authenticated user (if any); or, do you want to be able to select a client from a list of clients; or, is the client_id in your URI?

boldstar

@tykus, It is not related to the authenticated user.

I would prefer to have the client_id already attached to the form when inputting the rest of the data.

But selecting the client from a list of clients would work to, just not ideal for my goal.

Ive seen where laravel will handle the logic of the associated data for the user but im not sure how it will know the association of the table outside of that relationship..

tykus
tykus
5 days ago (657,630 XP)

If it is not the authenticated user, then the client_idwill most probably need to come from the request (the server-side is not going to know anything about it).

I would prefer to have the client_id already attached to the form

Where is the client_id going to come from; how are you going to get the client_id into the client-side application?

boldstar

well im already retrieving a list of the clients here from the store

retrieveClients(context) {
      this.loading = true
      axios.get('http://traxit.test/api/clients')
      .then(response => {
        this.loading = false
        context.commit('retrieveClients', response.data)
      })
      .catch(error => {
        this.loading = false
        console.log(error)
      })
    },

and if i were doing a list of the clients i had a created function to dispatch that request

created: function() {
    this.engagement.client_id = this.$store.dispatch('retrieveClients')
  },

But as far as how it would know that im adding an engagement for a particular client i am not sure..

tykus
tykus
5 days ago (657,630 XP)

How are you going to determine the particular client though; do you click on an action from a table, of click on a profile (show view), something???

tykus
tykus
5 days ago (657,630 XP)

I don't know the wider context of your app, what is your workflow leading to the form?

boldstar

okay so when I VIEW a client, I can see a list of the engagements associated with them only

here is the vue component

<div>
        <div class="header p-0 d-flex flex-row justify-content-between mt-2 mb-4 shadow-sm">
            <i class="ml-3 pr-2 far fa-folder-open h3 text-primary align-self-center m-0"></i>
            <router-link to="/add-engagement" class="mr-3 btn btn-success btn-sm m-0 align-self-center"><i class="mr-2 fas fa-plus-square"></i>Engagement</router-link>
        </div>

        <div class="row mx-1">
            <div class="card mb-3 mr-3 shadow-sm col-4 p-0" v-for="(engagement, index) in engagement" :key="index">
                <div class="d-flex justify-content-between card-header">
                    <h3 class="m-0 text-muted">{{ index + 1 }}</h3>
                    <h5 class="align-self-center m-0"><span>Return Type: </span> {{ engagement.return_type }} </h5>
                </div>
                <div class="card-body text-left p-0 my-1">
                    <h5 class="p-4"><span class="desc">Assigned To: </span> {{ engagement.assigned_to }} </h5>
                    <hr class="my-1">
                    <h5 class="p-4"><span class="desc">Status: </span> {{ engagement.status}} </h5>
                </div>
                <div class="card-footer d-flex justify-content-between">
                    <router-link to="#" class="btn">View</router-link>
                    <router-link to="#" class="btn">Edit</router-link>
                </div>
            </div>
        </div>
    </div>

here is the script for that component

<script>
import { mapGetters } from 'vuex'

export default {
    name: 'client-engagements',
    computed: {
    ...mapGetters(['engagement'])
    },
    created() {
        this.$store.dispatch('getClientEngagement', this.$route.params.id)
    },    
}
</script>

Now notice the the

<router-link to="/add-engagement" class="mr-3 btn btn-success btn-sm m-0 align-self-center"><i class="mr-2 fas fa-plus-square"></i>Engagement</router-link>
        </div>

when i click on that button it takes me to the view for adding a new engagement...

Is this helping you understand or am I not going the right direction?

boldstar

So workflow of the app would be a User is able to view Clients and from there, view list of Engagements associated with the client. The Engagements will have a relationship with a Task that will be tied back to the User..

The engagements have know direct relationship with users

  1. Tasks belongs to Users

  2. Engagements belongs to Clients

  3. Engagements and Tasks have many to many

tykus
tykus
5 days ago (657,630 XP)

Ok. So you have two options as I see it (i) add the client_id to the link URI or (ii) set a selected client_id property on a common parent component.

My personal preference would be the first option since you could browse directly to the URL and know that the client_id is set, otherwise you might get to the add engagement page without the client_id being set.

boldstar

So would I do a nested route for the client engagements in the router.js file?

Like

client/{client_id}/add-engagement?
tykus
tykus
5 days ago (657,630 XP)

Yes, that would work; you would see that URI and understand that the id referred to the client.

boldstar

Okay I will give it a shot and respond back with results later, I have to leave for the moment!

Thank you for your help!

boldstar

@tykus, sorry for the late response

So at this point I am able to capture the ID of the client in the URL. It is not exactly how I intended for it to be structured but none the less it is there

add-engagement\{client_id}

I use my getters from vuex for the client data on that instance..

client(state) {
      return state.client;
    },

So Im not sure what your knowledge is with laravel but how do I know that the client_id is being passed with the rest of the form submission?

this is the AddEngagement component again

 <template>
  <div class="page-wrapper mt-1">
    <div class="add-engagement container">
      <div class="card-body bg-light border-primary mb-2">
        <h4 class="text-left text-primary m-0"><i class="mr-3 far fa-folder-open"></i>New Engagement</h4>
      </div>
        <form @submit.prevent="addEngagement" class="d-flex-column justify-content-center">
          <div class="form-group">
            <select class="form-control mb-3" id="type" v-model="engagement.return_type">
              <option v-for="type in types" :key="type.id" :value="type">{{ type }}</option>
            </select>
            <input type="text" class="form-control mb-3" placeholder="Year" v-model="engagement.year">
            <input type="text" class="form-control mb-3" placeholder="Assign To" v-model="engagement.assigned_to">
            <input type="text" class="form-control mb-3" placeholder="Status" v-model="engagement.status">

            <button type="submit" class="btn btn-lg btn-primary d-flex justify-content-start">Create</button>
          </div>
        </form>
      </div>  
  </div>
</template>

<script>


export default {
  name: 'add-engagement',
  data() {
    return {
      engagement: {
        return_type: null,
        year: '',
        assigned_to: '',
        status: '',
      },
      types: [ 
        'Choose Return Type...', 
        '1040', 
        '1120',
      ],
    }
  },
   methods: {
    addEngagement(e) {
      if(!this.engagement.return_type || !this.engagement.year ){
        return
      } else {
        this.$store.dispatch('addEngagement', {
          id: this.idForEngagement,
          return_type: this.engagement.return_type,
          year: this.engagement.year,
          assigned_to: this.engagement.assigned_to,
          status: this.engagement.status,
        })
        e.preventDefault();
      }
      e.preventDefault();
      this.engagement = "" 
      this.idForEngagement++
      this.$router.push('/engagements')
    },
  },
  created: function() {
    this.engagement.return_type = this.types[0]
  },

}
</script>

and this is the store action

addEngagement(context, engagement) {
      axios.post('http://traxit.test/api/engagements', {
        return_type: engagement.return_type,
        year: engagement.year,
        assigned_to: engagement.assigned_to,
        status: engagement.status,
        done: false
      })
      .then(response => {
        context.commit('getClientEngagement', response.data)
      })
      .catch(error => {
        console.log(error)
      })
    },

Basically at this point when i submit the form with client_id in the url I get a 500 internal server error response...

Please sign in or create an account to participate in this conversation.