Part 3: How to build a job board with vue js and the Laravel 5.5 API ?

Commissioning the back end series

Created on: April 01, 2018

Updated on: April 01, 2018

In part 2 we created the front view containing a series of buttons that we will use to invoke actions. Since we are now concentrating on the front end our task is to create the methods that are associated with these buttons so that our application is wired up and ready to go.

We need to go back to our masterblade file; do you remember when we added a fetchJobs function that was necessary to fetch our job listings and present it to the view?

Next, we will add the delete, update and storeJob methods (CRUD methods) just underneath it to ensure that our buttons and input fields are wired up.

In part 2 we created a vue component and this contained a method called fetchJobs. As a reminder here is the code that we added earlier.

vue component

<script type="text/javascript">
    Vue.component('job' , {
        template: "#template-job-raw",
        props:  ['job' ]
    });

    var  vm = new  Vue({
        el: '#app' ,
        data:  {
        jobs:  []
    },
    mounted: function (){
        this.fetchJobs()
    },
        methods: {
            fetchJobs: function() {
                var vm = this;
                axios.get('/api/jobs')
                    .then(function (response) {
                        // set data on vm
                        var jobsReady = response.data.map(function (job) {
                            job.editing = false;
                            return job
                        })
                        Vue.set(vm, 'jobs', jobsReady)
                    });
                }

        }
    })
</script>

As you can see we have a fetchJobs method and its task is to go and grab the jobs from the Jobs model. A listing is produced and assigned as a response and the variable is set.

The next stage is to add a new method called deleteJob.

How to delete a job

On the array the index method is initialised and we pass in the list of jobs and then we use the splice method to remove a job from it.

We then move to the back end and we make a delete request using the RESTFUL API to delete the job from the database.

Add a new method to the component so that the deleteJob method can be rendered this is shown below:

vue component

<script type="text/javascript">
    Vue.component('job' , {
        template: "#template-job-raw",
        props:  ['job' ],

        methods: {
            deleteJob: function (job) {
                var index = this.$parent.jobs.indexOf(job);
                this.$parent.jobs.splice(index, 1)
                axios.delete('/api/jobs/' + job.id)
            }
    });

    var  vm = new  Vue({
        el: '#app' ,
        data:  {
        jobs:  []
    },
    mounted: function (){
        this.fetchJobs()
    },
        methods: {
            fetchJobs: function() {
                var vm = this;
                axios.get('/api/jobs')
                    .then(function (response) {
                        // set data on vm
                        var jobsReady = response.data.map(function (job) {
                            job.editing = false;
                            return job
                        })
                        Vue.set(vm, 'jobs', jobsReady)
                    });
                }

        }
    })
</script>

editJob

We will now add the editJob method and this will set the job editing flag to true. This will trigger the logic that will open the input fields on the template we created earlier.

vue component

<script type="text/javascript">
    Vue.component('job' , {
        template: "#template-job-raw",
        props:  ['job' ],

        methods: {
            deleteJob: function (job) {
                var index = this.$parent.jobs.indexOf(job);
                this.$parent.jobs.splice(index, 1)
                axios.delete('/api/jobs/' + job.id)
            },

             editJob: function (job) {
                job.editing = true;
            } 

    });

    var  vm = new  Vue({
        el: '#app' ,
        data:  {
        jobs:  []
    },
    mounted: function (){
        this.fetchJobs()
    },
        methods: {
            fetchJobs: function() {
                var vm = this;
                axios.get('/api/jobs')
                    .then(function (response) {
                        // set data on vm
                        var jobsReady = response.data.map(function (job) {
                            job.editing = false;
                            return job
                        })
                        Vue.set(vm, 'jobs', jobsReady)
                    });
                }

        }
    })
</script>

updateJob

We will add the updateJob method this will perform a patch request to the backend and it will set the job.editing flag to false.

How to update a view

vue component

<script type="text/javascript">
    Vue.component('job' , {
        template: "#template-job-raw",
        props:  ['job' ],

        methods: {
            deleteJob: function (job) {
                var index = this.$parent.jobs.indexOf(job);
                this.$parent.jobs.splice(index, 1)
                axios.delete('/api/jobs/' + job.id)
            },

             editJob: function (job) {
                job.editing = true;
            },
            updateJob: function (job) {
                axios.put('/api/jobs/' + job.id, job)
                //Set editing to false to show actions again and hide the inputs
                job.editing = false;
            } 

    });

    var  vm = new  Vue({
        el: '#app' ,
        data:  {
        jobs:  []
    },
    mounted: function (){
        this.fetchJobs()
    },
        methods: {
            fetchJobs: function() {
                var vm = this;
                axios.get('/api/jobs')
                    .then(function (response) {
                        // set data on vm
                        var jobsReady = response.data.map(function (job) {
                            job.editing = false;
                            return job
                        })
                        Vue.set(vm, 'jobs', jobsReady)
                    });
                }

        }
    })
</script>

storeJob

Before we work on this upcoming method, it is a good idea if we return to the jobs.blade.php and add ask the user whether they wish to add a new job.

<p class="lead">Are you interested in.....
            <button @click="createJob()" class="btn btn-primary">Adding a new job?</button>
        </p>

resources/views/jobs.blade.php

 <div id="app">
        <h1>Job Board</h1>
        <table class="table table-striped">
            <tr>
                <th>#</th>
                <th>Reference</th>
                <th>Title</th>
                <th>Type</th>
                <th>Description</th>
                <th>Employer</th>
                <th>Location</th>
                <th>Salary</th>
                <th>Post Date</th>
            </tr>
            <tr v-for="job in jobs" is="job" :job="job"></tr>
        </table><!-- /.table -->
        <p class="lead">Are you interested in.....
            <button @click="createJob()" class="btn btn-primary">Adding a new job?</button>
        </p>

    </div><!-- /#app -->

Now that we have accomplished this we can now return to the master.blade.php component section. Our storeJob function will perform a post request to the database on the backend. We will set the job id and we will set the job.editing flag to false.

vue component

<script type="text/javascript">
    Vue.component('job' , {
        template: "#template-job-raw",
        props:  ['job' ],

        methods: {
            deleteJob: function (job) {
                var index = this.$parent.jobs.indexOf(job);
                this.$parent.jobs.splice(index, 1)
                axios.delete('/api/jobs/' + job.id)
            },

             editJob: function (job) {
                job.editing = true;
            },
            updateJob: function (job) {
                axios.put('/api/jobs/' + job.id, job)
                //Set editing to false to show actions again and hide the inputs
                job.editing = false;
            },

            storeJob: function (job) {
                axios.post('/api/jobs/', job).then(function (response) {

                    Vue.set(job, 'id', response.data.id);

                    job.editing = false;
                });

            }
        }     

    })

    var  vm = new  Vue({
        el: '#app' ,
        data:  {
        jobs:  []
    },
    mounted: function (){
        this.fetchJobs()
    },
        methods: {
            fetchJobs: function() {
                var vm = this;
                axios.get('/api/jobs')
                    .then(function (response) {
                        // set data on vm
                        var jobsReady = response.data.map(function (job) {
                            job.editing = false;
                            return job
                        })
                        Vue.set(vm, 'jobs', jobsReady)
                    });
                }

        }
    })
</script>

Do you remember when we created our button called adding a new job? Well this button invokes the createJob function and this is where we will focus our attention on next.

createJob

The createJob method adds a new job this must contain the required fields that are necessary to add a new job.

We have already added the jobs array earlier, if you check the new vue instance we added there are the jobs array and a job variable listed.


 var  vm = new  Vue({
        el: '#app' ,
        data:  {
            jobs: [],
            job: {}
        },

The jobs array is created when we add a new job and click on the adding a new job button.

We need to add the jobs array, to the initialised vue instance to ensure that a new job can be pushed on to the array.

Go to the new Vue instance and underneath the data add jobs [] and add the singular job {}.

Underneath the mounted function that initialises the fetchJobs method. Create a new method called createJob, and include empty fields that are derived from the Job model.

Check out the code below


Vue.component('job' , {
        template: "#template-job-raw",
        props:  ['job' ],
        methods: {
            deleteJob: function (job) {
                var index = this.$parent.jobs.indexOf(job);
                this.$parent.jobs.splice(index, 1)
                axios.delete('/api/jobs/' + job.id)
            },

            editJob: function (job) {
                job.editing = true;
            },

            updateJob: function (job) {
                axios.put('/api/jobs/' + job.id, job)
                //Set editing to false to show actions again and hide the inputs
                job.editing = false;
            },

            storeJob: function (job) {
                axios.post('/api/jobs/', job).then(function (response) {

                    Vue.set(job, 'id', response.data.id);

                    //Set editing to false to show actions again and hide the inputs
                    job.editing = false;
                });

            }
        }

    })

    var  vm = new  Vue({
        el: '#app' ,
        data:  {
            jobs: [],
            job: {}
        },
        mounted: function (){
            this.fetchJobs()
        },
        methods: {
            createJob: function () {
                var newJob = {
                    reference: "",
                    employer: "",
                    title: "",
                    location: "",
                    salary: 0,
                    post_date: "",
                    type: "",
                    description: "",
                    editing: true
                };
                this.jobs.push(newJob);
            },

            fetchJobs: function() {
                var vm = this;
                axios.get('/api/jobs')
                    .then(function (response) {
                        // set data on vm
                        var jobsReady = response.data.map(function (job) {
                            job.editing = false;
                            return job
                        })
                        Vue.set(vm, 'jobs', jobsReady)
                    });
            }
        }
    })
</script>

As you can see within the createJob method the variable newJob is initialised and the empty fields are set. The job.editing flag is set to true meaning that all of the input fields set on the template will open.

A new job is pushed on to the array, and after that the storeJob method is invoked and this is where the post request we discussed earlier is invoked and the job is save on the backend.

Please check out our github repo for the code in full:

https://github.com/ormrepo/jobboard

Today we learnt how to implement the front-end architecture by creating the various table definitions, buttons, vue components and the vue instance that can be applied to specific web development services you offer.

Wiring up a back-end API with a front-end application doesn’t have to be complicated.

Developing API's require careful planning and scrupulous documentation.

As developers we can create our own API's where we can set our own parameters on how to consume then.

Problems can occur if you don't empathise with the consumer of your api and assumptions are made to the level of the developer who is using your api.

Please pay careful attention to the users or consumers of your web development services application because if they are not satisfied with your api then your application is effectively superfluous.

Stay tuned for further tips and tricks from www.ormrepo.co.uk/blogs. The link also provides information about the web development services we offer.