简体   繁体   中英

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>

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM