Jim E Russel
Jim E Russel

Reputation: 495

Vue.js and Laravel without page refresh using axios

Hello everyone I'm new to vue.js and I'm confused whether it is possible to reload a data table (server side rendering) without refreshing the page using a component embedded in a blade.php?

Here is a my code. All of these components are attached in a blade.php file.

Department.vue Component (for adding)

    <template>
      <div class="container">
        <div class="row justify-content-center">
          <div class="col-md-8">
            <div class="card">
              <div class="card-header">Add Department / Section</div>
              <div class="card-body">
                <form @submit.prevent="addData()">

                <div class="form-group">
                  <label class="form-control-label" for="name">Department</label>
                  <input type="text" class="form-control" v-model="department">
                  <div v-if="errors.department" :class="['invalid-feedback']">{{ errors.department[0] }}</div>
                </div>

                <div class="form-group">
                  <label class="form-control-label" for="name">Section</label>
                  <input type="text" class="form-control" v-model="section" v-bind:class="{'is-invalid': validate && attemptSubmit && missingName }">
                  <div v-if="errors.section" :class="['invalid-feedback']">{{ errors.section[0] }}</div>
                </div>

                <button type="submit" class="btn btn-primary btn-block">Submit</button>
                <button class="btn btn-primary btn-block">Edit</button>
                </form>
                <strong>Output:</strong>
                <pre>
                {{output}}
                </pre>
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>

<script>
  export default {
    mounted() {
      axios.get('/api/departments')
      .then(response => this.rows = response.data)
      .catch(error => console.log(error))
        },
    data() {
      return {
        department: '',
        section: '',
        output: '',
        attemptSubmit: false,
        validate: false,
        errors: [],
      };
    },
    computed: {
      missingName() {
        return this.section === ''
      },
    },
    methods: {
      addData() {
        this.attemptSubmit = true;
        this.validate = true;
        this.errors = [];
        if (this.errors) event.preventDefault();

        axios
        .post('/api/department', {
                    department: this.department,
                    section: this.section
        })
        .then(response => {
          this.validate = false;
          this.department = '';
          this.section = '';
          this.errors = '';
          this.output = response.data;
        })
        .catch(error => this.errors = error.response.data.errors)
      },
      deleteData(id) {
        if(confirm('Are you sure?')) {
          axios
          .delete(`/api/department/${id}`)
          .then(response => {this.output = response.data;})
          .catch(error => console.log(error))
        }
      }
    }
  }
</script>

Project.vue Component (data table)

<template>
  <div class="projects">
    <div class="tableFilters">
      <input class="input" type="text" v-model="tableData.search" placeholder="Search Table"
           @input="getProjects()">

      <div class="control">
        <div class="select">
          <select v-model="tableData.length" @change="getProjects()">
            <option v-for="(records, index) in perPage" :key="index" :value="records">{{records}}</option>
          </select>
        </div>
      </div>
    </div>
    <datatable :columns="columns" :sortKey="sortKey" :sortOrders="sortOrders" @sort="sortBy">
      <tbody>
        <tr v-for="project in projects" :key="project.id">
          <td>{{project.id}}</td>
          <td>{{project.department_name}}</td>
          <td>{{project.created_at}}</td>
                    <td> <a href="" @click="deleteData(project.id)"><i class="fas fa-trash" ></i></a></td>
        </tr>
      </tbody>
    </datatable>
    <pagination :pagination="pagination"
          @prev="getProjects(pagination.prevPageUrl)"
          @next="getProjects(pagination.nextPageUrl)">
    </pagination>
  </div>
</template>

<script>
import Datatable from './Datatable.vue';
import Pagination from './Pagination.vue';
export default {
  components: { datatable: Datatable, pagination: Pagination },
  created() {
    this.getProjects();
  },
  data() {
    let sortOrders = {};

    let columns = [
      {width: '33%', label: 'Deadline', name: 'id' },
      {width: '33%', label: 'Budget', name: 'department_name'},
      {width: '33%', label: 'Status', name: 'created_at'}
    ];

    columns.forEach((column) => {
       sortOrders[column.name] = -1;
    });
    return {
      projects: [],
      columns: columns,
      sortKey: 'id',
      sortOrders: sortOrders,
      perPage: ['5', '20', '30'],
      tableData: {
        draw: 0,
        length: 5,
        search: '',
        column: 0,
        dir: 'desc',
      },
      pagination: {
        lastPage: '',
        currentPage: '',
        total: '',
        lastPageUrl: '',
        nextPageUrl: '',
        prevPageUrl: '',
        from: '',
        to: ''
      },
    }
  },
  methods: {
    getProjects(url = '/api/departments') {
      this.tableData.draw++;
      axios
        .get(url, {params: this.tableData})
        .then(response => {
          let data = response.data;
          if (this.tableData.draw == data.draw) {
            this.projects = data.data.data;
            this.configPagination(data.data);
          }
        })
        .catch(errors => {
          console.log(errors);
        });
    },
    configPagination(data) {
      this.pagination.lastPage = data.last_page;
      this.pagination.currentPage = data.current_page;
      this.pagination.total = data.total;
      this.pagination.lastPageUrl = data.last_page_url;
      this.pagination.nextPageUrl = data.next_page_url;
      this.pagination.prevPageUrl = data.prev_page_url;
      this.pagination.from = data.from;
      this.pagination.to = data.to;
    },
    sortBy(key) {
      this.sortKey = key;
      this.sortOrders[key] = this.sortOrders[key] * -1;
      this.tableData.column = this.getIndex(this.columns, 'name', key);
      this.tableData.dir = this.sortOrders[key] === 1 ? 'asc' : 'desc';
      this.getProjects();
    },
    getIndex(array, key, value) {
      return array.findIndex(i => i[key] == value)
        },
         deleteData(id) {
        if(confirm('Are you sure?')) {
          axios.delete(`/api/department/${id}`)
          .then(response => {
            this.output = response.data;
            this.$parent.reload();
          })
          .catch(error => console.log(error))
                }
         }
  }
};
</script>

Upvotes: 1

Views: 2894

Answers (1)

Shailesh Matariya
Shailesh Matariya

Reputation: 840

If you want to use laravel routing then it will refresh when you change the route. There is few ways to create SPA.

  1. Using separate vuejs project
  2. You can use https://inertiajs.com/
  3. You can use laravel livewire. Livewire

I will prefer to use inertiajs/livewire in your case and it can easily integrate with laravel and vuejs.

Upvotes: 2

Related Questions