laravel vuejs vuex project 2022 | Complete crud application using laravel vuejs and vuex

    By: Manu
    2 years ago

    So today we are going to create a complete employee management application. For this we will use Laravel 8 along with Vuejs and Vuex.

    you can follow along and create a project in laravel, vuejs and vuex. We are going to cover some advanced features of vuex. Also we are going to add search feature in this project.

    Follow steps as given below to create this application. If face any issue then check our video guide.

    Code for Video Laravel Vuejs Vuex Employee management Application.

    Code for Video Laravel Vuejs Vuex Employee management Application.


    ---> Step 1

    -----------

     Creating a laravel project

    --------------



    Getting started

    1. create laravel project

    https://laravel.com/docs/8.x#installation-via-composer
    2. composer require laravel/ui
    3. php artisan ui vue --auth
    4.npm install
    


    Additional NPM packages installation


    5. npm install vue-template-compiler vue-loader vue-router vuex axios vue-axios --save-dev --legacy-peer-deps
    


    Compile using 


    npm run dev 
    or 
    npm run watch
    

    ------------------------------------------------------------------------

    ---> Step 2

    -----------

    Setting up vuejs and Vuex for project and Creating model and controller

    --------------

    1. Connect database in env file.


    2. php artisan make:migration create_employee_table
    

    Table fields:


    $table->id();
    $table->string('name');
    $table->string('department');
    $table->string('section');
    $table->string('email');
    $table->integer('status')->default(0);
    $table->timestamps();
    


    Run commands:

    3.php artisan migrate
    4. php artisan make:model Employee
    


    5. in model


    	protected $fillable = [
    		'name',
    		'department',
    		'section',
    		'email'
    	]
    


    6. php artisan make:controller EmployeesController
    


    7. public function create 


    	$data= [
    		'scope' =>'create'
    	];
    	view('employee.form')
    

    8. create form.blade.php in employee folder.

    9. create route 


    	Route::get('add-employee', [EmployeesController::class, 'create']);
    

    10. Create blade file form.blade.php


    extends app.blade.php layout

    create div#app inside blade file.

    create component employee-form


    pass props->

    	<div class="container">
    		<employee-form
    			scope="{$scope}"
    			:id="{$id ?? 0}"
    		>
    		</employee-form>
    	</div>
    


    create folder components/employees

    create file EmployeeForm.vue


    Package to use: element.eleme.io: installation

    https://element.eleme.io/#/en-US/component/installation

    npm i element-ui -S
    

    ----------------------------

    In app.js

    ----------------------------


    	import Vue from 'vue';
    	import ElementUI from 'element-ui';
    	import 'element-ui/lib/theme-chalk/index.css';
    
    
    	Vue.use(ElementUI);
    


    ----------------------------

    In EmployeeForm.vue

    ----------------------------


    	<template>
    		<div>
    			<el-card class="box-card">
    			 <div slot="header" class="clearfix">
    			 	Form page
    			 </div>
    			</el-card>
    		</div>	
    	</template>
    


    go in element.eleme.io sidebar components search for

    page-header


    <template>
    	<div>
    		<el-card class="box-card">
    		 	<div slot="header" class="clearfix">
    				<el-page-header @back="goBack" content="detail">
    				</el-page-header>
    			</div>
    			<div>
    				<el-form ref="form" :model="form" ref="employeeForm">
    				  <el-row :guuter="10">
    				  	<el-form-item label="Name" required prop="name"> 
    				  		<el-input v-model="form.name" aria-placeholder="Employee Name">
    				  	</el-form-item>
    				  	<el-form-item label="Department" required prop="department"> 
    				  		<el-input v-model="form.department" aria-placeholder="Employee Department">
    				  	</el-form-item>
    				  	<el-form-item label="Section" required prop="section"> 
    				  		<el-input v-model="form.section" aria-placeholder="Employee Section">
    				  	</el-form-item>
    				  	<el-form-item label="Email" required prop="email"> 
    				  		<el-input v-model="form.email" aria-placeholder="Employee Email">
    				  	</el-form-item>
    				  <el-row>
    
    				  <el-row :guuter="10">
    				  	<el-form-item>
    				  		<el-button type="success" @click="saveForm('employeeForm')">Save<el-button>
    				  	</el-form-item>
    				  </el-row>
    				</el-form>
    			</div>
    		</el-card>
    	</div>	
    </template>
    <script>
    	export default{
    		name:'employee-form',
    		data(){
    			return{
    				form:{
    					name:null,
    					department:null,
    					section:null,
    					email:null,
    				},
    			}
    		},
    		methods:{
    			goBack(){
    				window.location.href = '/employees'
    			},
    			saveForm(formName){
    
    			}
    		}
    	}
    </script>
    

    -----------------------------------------------------------------------------

    Vuex core concepts


    Go in application structure

    create store folder in js folder

    create files


    	actions.js 
    	mutations.js 
    	getters.js 
    	index.js
    


    ----------------------------

    index.js

    ----------------------------

    import Vue from 'vue';
    import Vuex from 'vuex';
    
    
    import getters from './getters';
    import mutations from './mutations';
    import * as actions from './actions';
    
    import { axios } from 'vue/types/umd';
    Vue.use(Vuex);
    
    export const store = new Vuex.store({
    	modules:{
    
    	},
    	state:{
    
    	},
    	mutations,
    	actions,
    	getters,
    })
    

    -----------------------------

    App.js

    -----------------------------


    import { store } from './store/index.js'
    
    
    const app = new Vue({
    	store,
    	el:'#app'
    })
    


    -----------------------------

    Employee form component

    ----------------------------


    props:{
    	scope:String,
    }
    ,
    saveForm(formName){
    	this.$refs[formName].validate((valid) => {
    		if(valid){
    			this.$store.dispatch('saveEmployee', this.form);
    		}
    	});
    }
    


    ----------------------------

    Actions.js

    ----------------------------

    import Vue from 'vue';
    
    let loader = null;
    function displayLoader(loadingText='loading...'){
    	loader = Vue.prototype.$loading({
    		lock:true,
    		text: loadingText,
    		spinner: 'el-icon-loading',
    		background: 'rgba(255,255,255,0.85',
    	})
    }
    
    function hideLoader(){
    	loader.close();
    }
    
    
    export const saveEmployee = ({commit}, payload) => {
    
    	displayLoader();
    	
    	axios.post(`/save-employee`, pauyload).then(res => {
    		Vue.prototype.$notify({
    			title:'Success',
    			message: 'Employee added successfully',
    			type: 'success',
    		});
    
    		hideLoader();
    
    		setTimeout(()=>{
    			window.location.href = '/employees';
    		},1500);
    
    	});
    }
    


    --------------------

    web.php

    --------------------


    Route::post('save-employee', [EmployeesController::class, 'store'])
    

    ------------------

    EmployeesController

    -----------------

    use Illuminate\Http\Request;
    use Exception;
    use App\Models\Employee;
    
    public function storeEmployee(Request $request)
    {
    	try
    	{
    		$employee = new Employee;
    		$employee->name = $request->name;
    		$employee->department = $request->department;		
    		$employee->section = $request->section;
    		$employee->email = $request->email;
    		$employee->save();
    
    		return response()->json([
    			'status' => 200,
    			'message' => 'Employee saved successfully'
    		])
    
    	}
    	catch(Exception $e)
    	{
    		dd($e);
    	}
    }
    


    ---------------------------------------------------------------------------

    ---> Step 3

    -----------

    Displaying content using vuex on laravel blade and vue component

    --------------

    --------------------

    web.php

    -------------------


    Route::get('employees', [EmployeesController::class, 'index']);
    



    -------------------

    EmployeesController::class

    -------------------

    public function index(){
    	return view('employee.index');
    }
    

    copy content from 

    form.blade.php ------> index.blade.php


    create component employee-list

    EmployeeList.vue


    <template>
    	<div>
    		<el-card class="box-card">
    		 	<div slot="header" class="clearfix">
    				Employee Data
    				<el-button type="success" class="float-right" @click="">
    					Add Employee
    				</el-button>
    			</div>
    			<div>
    				<el-table
    					:data="tableData"
    					style="width:100%"
    					:border="true"
    					hieght="500"
    				>
    
    				<el-table-column v-for="column in tableColumns"
    				:key="column.label"
    				:label="column.label"
    				:prop="column.prop"
    				:column-key = "column.prop"
    				:width="column.minWidth"
    				:sortable="column.sortable"
    				:align="column.align"
    				:header-align="column.align"
    				:format="column.format || null"
    
    				>
    				</el-table-column>
    				<el-table-column align="right"
    					<template slot="header" slot-scope="scope">
    						<el-input v-model="search" size="mini" placeholder="Type to search" />
    					</template> 
    					<template slot-scope="scope">
    						<el-button size="mini" type="success" @click=""></el-button>
    						<el-button size="mini" type="danger" @click=""></el-button>
    					</template>
    				</el-table>
    
    				
    			</div>
    		</el-card>
    	</div>	
    </template>
    
    <script>
    	import { mapGetters } from 'vuex';
    
    	export default{
    		name:'employee-list',
    		mounted(){
    			const loading = this.$loading({
    					lock:true,
    					text: loadingText,
    					spinner: 'el-icon-loading',
    					background: 'rgba(255,255,255,0.85',
    			});
    
    			this.$store.dispatch('getEmployees');
    
    			loading.close();
    		},
    		computed:{
    			...mapGetters({
    				tableData: "tableData"
    			})
    		},
    		data(){
    			return{
    				search:null,
    				form:{
    					
    				},
    				tableColumns:
    				[
    					{
    						prop: 'name',
    						label: 'Name',
    						width: 40,
    						sortable: true,
    						hidden: true,
    						align: 'center',
    						fixed:true
    					},
    					{
    						prop: 'department',
    						label: 'Department',
    						width: 40,
    						sortable: false,
    						hidden: true,
    						align: 'center',
    						fixed:true
    					},
    					{
    						prop: 'section',
    						label: 'Section',
    						width: 40,
    						sortable: false,
    						hidden: true,
    						align: 'center',
    						fixed:true
    					},
    					{
    						prop: 'email',
    						label: 'Email',
    						width: 40,
    						sortable: false,
    						hidden: true,
    						align: 'center',
    						fixed:true
    					}
    				];
    			}
    		},
    		methods:{
    
    		}
    	}
    </script>
    

    -------------------------------------

    Index.js

    -------------------------------------


    state:{
    	tableData: [],
    }
    


    ------------------------------------

    getters.js

    ------------------------------------


    export default {
    	tableData(state){
    		return state.tableData;
    	}
    }
    



    ------------------------------------

    actions.js

    ------------------------------------


    export const getEmployees({commit}, payload) => {
    
    	axios.get(`/get-employees-data`, payload).then(res => {
    		commit('setTableData', res.data);
    	});
    	
    }
    


    ----------------------------------

    web.php

    ----------------------------------


    Route::get('get-employees-data', [EmployeesController::class, 'getEmployeesData']);
    


    ----------------------------------

    EmployeesController

    ----------------------------------


    public function getEmployeesData(){
    	try
    	{
    		returen Employee::all();
    	}
    	catch(Exception $e)
    	{	
    		dd($e);
    	}
    }
    


    ----------------------------------

    mutations.js

    ---------------------------------


    export default {
    	setTableData(state, tableData){
    		state.tableData = tableData;
    	}
    }
    


    ------------------------------------------------------------------------


    ---> Step 4

    -----------

    Update data using Vuex in laravel application.

    --------------

    ---------------------

    EmployeeList.vue

    ---------------------


    <el-button size="mini" type="success" 
    @click="editEmployee(scope.$index, scope.row)">
    Edit</el-button>
    <el-button size="mini" type="danger" >Delete</el-button>
    
    
    
    editEmployee(index,row){
    	window.location.href="/edit-employee/"+row.id+"/edit";
    }
    


    --------------------------

    web.php

    --------------------------


    Route::get('edit-employee/{id}/edit',[EmployeesController::class, 'edit']);
    
    


    -------------------------

    EmployeesController

    -------------------------


    public function edit($id){
    	$data = [
    		'scope' => 'edit',
    		'id' => $id
    	];
    
    	return view('employee.form')->with($data);
    	
    }
    


    ---------------------------

    EmployeeForm.vue

    --------------------------


    props:{
    	scope: String,
    	id: Number
    }
    
    
    mounted(){
    	
    	if(this.scope == 'edit')
    	{
    		axios.get(`/fetch-employee-data/${this.id}`).then(res => {
    			this.$set(this, 'form', res.data.data);
    		});
    
    	}
    }
    


    --------------------------------

    web.php

    --------------------------------


    Route::get('fetch-employee-data/{id}',[EmployeesController::class, 'getEmployeeDataById']);
    



    -------------------------------

    EmployeesController

    -------------------------------


    public function getEmployeeDataById($id)
    {
    	
    	$employee = Employee::find($id);
    	return response()->json([
    		'status' => 200,
    		'data' => $employee
    	]);
    }
    




    -----------------------------------

    EmployeeForm.vue

    ----------------------------------


    saveForm(formName){
    	this.$refs[formName].validate((valid) => {
    		if(valid){
    
    			if(this.scope == 'create'){
    				this.$store.dispatch('saveEmployee', this.form);
    			}else{
    				this.$store.dispatch('updateEmployee', { id: this.id, form:this.form});
    			}
    		}
    	});
    }
    



    ----------------------------------

    action.js

    ----------------------------------

    export const saveEmployee = ({ commit }, payload) => {
    
      displayLoader('Updating employee');
    
      axios.put(`/update-employee/${payload.id}`, payload.form).then(res => {
        Vue.prototype.$notify({
          title: 'Success',
          message: res.data.message,
          type: 'success',
        })
    
        removeLoader();
    
        setTimeout(() => {
          window.location.href = '/employees'
        }, 2000);
      })
    }
    


    -----------------------------------

    web.php

    ----------------------------------


    Route::put('update-employee/{id}', [EmployeesController::class, 'update']);
    


    ------------------------------------

    EmployeesController

    ------------------------------------

    public function update(Request $request, $id)
      {
        try
        {
          $employee = new Employee::find($id);
          $employee->name = $request->name;
          $employee->department = $request->department;
          $employee->section = $request->section;
          $employee->email = $request->email;
          $employee->update();
    
          return response()->json([
            'status' => 200,
            'message' => 'Employee update successfully',
          ]);
    
    
        }
        catch(Exception $e)
        {
          dd($e);
        }
      }
    
    
    


    ------------------------------------------------------------------------


    ---> Step 5

    -----------

    Show content using vuex on laravel blade

    --------------


    --------------------

    Employeelist.vue

    --------------------


    <el-button size="mini" type="info" @click="showEmployeeData(scope.$index, scope.row)">Show</el-button>
    <el-button size="mini" type="success"
                   @click="editEmployee(scope.$index, scope.row)">
                    Edit</el-button>
    <el-button size="mini" type="danger" >Delete</el-button>
    
    <el-table-column align=right min-width="90">
    
    
    
    showEmployeeData(){
    	window.location.href="/show-employee/"+row.id;
    }
    



    --------------------

    web.php

    --------------------

    Route::get('show-employee/{id}', [EmployeesController::class, 'show']);
    



    -------------------

    EmployeesController

    ------------------

    public function show($id)
    {
    	$data = [
    		'scope' => 'show',
    		'id' => $id
    	];	
    
    	return view('employee.form')->with($data);
    }
    



    --------------------

    EmployeeForm.vue

    --------------------


    computed: {
    	readOnlyField(){
    		return this.scope == 'show' ? true : false; 
    	}
    }
    


    in form input we pass


    :readonly="readOnlyField()"
    
    


    for button we add


    v-if="scope != 'show'"
    

    --------------------------------------------------------------------------

    ---> Step 6

    -----------

    Delete data using vuex in laravel

    --------------

    --------------------

    Employeelist.vue

    --------------------

    <el-button size="mini" type="danger" 
    @click="deleteEmployee(scope.$index, scope.row)">Delete</el-button>
    
    
    
    
    deleteEmployee(index, row){
        this.$confirm('Are you sure, You want to delete this Employee', 'Warning', {
         confirmButtonText: 'OK',
         cancelButtonText: 'Cancel',
         type: 'warning'
        }).then(() => {
    
    
        	this.$store.dispatch('deleteEmployee', {
        		id: row.id,
        	});
    
        	this.$store.dispatch('getEmployees');
    
         this.$message({
          type: 'success',
          message: 'Delete completed'
         });
        }).catch(() => {
         this.$message({
          type: 'info',
          message: 'Delete canceled'
         });      
        });
        
    }
    
    


    ---------------------------------

    action.js

    --------------------------------

    export const updateEmployee = ({ commit }, payload) => {
    
      displayLoader('Deleting employee');
    
      axios.delete(`/delete-employee/${payload.id}`).then(res => {
        Vue.prototype.$notify({
          title: 'Success',
          message: res.data.message,
          type: 'success',
        })
    
        removeLoader();
      })
    }
    



    --------------------------------

    web.php

    -------------------------------


    Route::delete('delete-employee/{id}', [EmployeesController::class, 'destroy']);
    


    --------------------------------

    EmployeesController

    --------------------------------


    public function destroy($id)
    {
    	$employee = Employee::find($id);
    
    	$employee->delete();
    
    	return response()->json([
    		'status' => 200,
    		'message' => 'Employee deleted successfully',
    	]);
    }
    


    -------------------------------------------------------------------------


    Search feature

    ----------------

    EmployeeList.vue

    -----------------

     mounted(){
          const loading = this.$loading({
            lock: true,
            text: 'loading...',
            spinner: 'el-icon-loading',
            background: 'rgba(255,255,255,0.85)',
          });
    
          this.$store.dispatch('getEmployeesData', {searchQuery: this.search});
    
          loading.close();
    
        },
    
    
    
    watch:{
    	seach: function(keyword){
    		this.$store.dispatch('getEmployeesData', {searchQuery: this.search});
    	}
    }
    




    ---------------------------

    action.js

    --------------------------


    //change to post
    
    export const getEmployeesData = ({ commit }, payload) => {
      axios.post(`/get-employee-data`, payload)
        .then(response => {
          commit('setTableData', response.data);
        })
    }
    




    --------------------------------

    EmployeesController

    --------------------------------


    public function getEmployeeData(Request $request)
      {
        try
        {
    			$query = Employee::select('name', 'department','section','email')
        	if($request->searchQuery){
        		$query->where(function($q) use $request) {
        			$q->orWhere('name', 'like', '%'.$request->searchQuery.'%')
    
        			$q->orWhere('department', 'like', '%'.$request->searchQuery.'%')
        		})
        	}
    
        	$employees = $query->get();
    
          return $employees;
        }
        catch(Exception $e)
        {
          dd($e);
        }
      }