Sinau Coding
Berbincang santai perihal pemrograman
Tukang ketik yang sedang belajar pemrograman
9/09/2021 09:11:00 PM

Cara insert data ke dalam list atau table tanpa menutup Modal

Vue

Desain halaman dan dialog tambah data biasanya adalah, User klik tombol yang akan memunculkan dialog, dimana dialog akan otomatis tertutup setelah User menekan tombol simpan dan proses simpan berhasil. Tetapi, adakalanya User ingin dialog tidak otomatis tertutup setelah berhasil simpan data. Ini biasanya berguna jika perlu input banyak data sekaligus. Kali ini kita akan mencoba meng-implementasikan kebutuhan insert data tanpa menutup modal dengan menggunakan Vue.js.

Untuk contoh ini, penulis menggunakan UI framework Vue Material. Anda tidak harus menggunakan Vue Material, yang penting framework yang anda gunakan menyediakan komponen Modal.

Kemudian yang paling penting, solusi ini akan menjadi berguna jika komponen halaman utama/daftar terpisah dengan dialog. Maksudnya, jika halaman utama dan dialog tidak dipisah, maka solusi ini menjadi kurang menarik karena bisa langsung Anda selesaikan dengan mudah dengan memodifikasi langsung state-nya.

Jika halaman utama dan dialog dipisah, maka akan menjadi lebih menarik dan modular, dimana sekarang Modal/Dialog tidak boleh bergantung dengan parent yang memanggil dia.

0. Membuat halaman utama dan modal secara terpisah

Seperti disebutkan disebutkan sebelumnya, kita akan membuat 2 buah komponen, yaitu halaman utama dan dialog. Secara umum struktur folder dan file yang saya buat kurang lebih seperti gambar dibawah ini.

Struktur file dan folder

Komponen untamanya adalah App.vue, sedangkan komponen untuk modal dialognya adalah Modal.vue yang berada di folder components.

App.vue
<template>
  <div id="app">
    <md-toolbar>
      <md-button @click="addData" class="md-primary">Add Data</md-button>
    </md-toolbar>
    <md-list class="md-double-line">
      <md-list-item  v-for="(i, index) in items" :key="index">
        <div class="md-list-item-text">
          <span>{{ i.nama }}</span>
          <span>{{ i.alamat }}</span>
        </div>
      </md-list-item>
    </md-list>
    <Modal ref="dlg" />
  </div>
</template>

<script>
import Modal from "./components/Modal";
export default {
  name: "App",
  data() {
    return {
      items: [
        { nama: "Fulan", alamat: "Jl. Berbatu nan terjal" },
        { nama: "Fulana", alamat: "Jl. Berkelok nan menanjak" },
      ],
    };
  },
  components: {
    Modal,
  },
  methods: {
    addData() {
      this.$refs.dlg.open();
    },
  },
};
</script>
Modal.vue
<template>
  <md-dialog :md-active.sync="showDialog">
    <md-dialog-title>Add data</md-dialog-title>
    <md-card>
      <md-card-content>
        <md-field>
          <label>Nama</label>
          <md-input v-model="nama"></md-input>
        </md-field>

        <md-field>
          <label>Alamat</label>
          <md-textarea v-model="alamat"></md-textarea>
        </md-field>
      </md-card-content>
    </md-card>
    <md-dialog-actions>
      <md-button class="md-primary" @click="showDialog = false"
        >Close</md-button
      >
      <md-button class="md-primary" @click="apply">Save</md-button>
    </md-dialog-actions>
  </md-dialog>
</template>

<script>
export default {
  data() {
    return {
      showDialog: false,
      resolve: null,
      reject: null,

      nama: "",
      alamat: "",
    };
  },
  methods: {
    open() {
      return new Promise((resolve, reject) => {
        this.resolve = resolve;
        this.reject = reject;
        this.showDialog = true;
      });
    },
    apply() {},
  },
};
</script>

<style>
</style>

Tampilan awalnya kurang lebih seperti ini.

Tampilan awal

Pada kode awal di atas. Pada halaman utama (App.vue), user akan menekan tombol Add Data yang akan membuka dialog. Setelah user mengisi dan menekan tombol Save, maka data akan otomatis bertambah pada halaman utama tanpa perlu menutup Dialog.


Baca juga :
Vue+Vuetify : Menggunakan VDialog/v-dialog agar menjadi Promise based komponen
1. Komunikasi Child to Parent dengan menggunakan event

Design halaman Utama dengan Modal seperti ini bisa disebut dengan Parent (App.vue) Child (Modal.vue). Komponen Modal perlu berkomunikasi dengan Parent (yang memanggil) pada saat ditekan tombol Save. Maka solusinya adalah dengan menggunakan custom event yang dikirim dengan menggunakan $emit.

Untuk contoh ini, kita akan menambahkan custom event bernama on-save di komponen Modal.vue, yang akan di trigger pada saat user menekan tombol save. Pada contoh ini, pada saat tombol Save ditekan, akan memanggil method apply.

Tambahkan custom event dengan menggunakan $emit(<nama event>,<data yang dikirim>) pada method apply di komponen Modal.vue.

<template>
  ...
</template>

<script>
export default {
  ...
  methods: {
    ...
    apply() {
      this.$emit("on-save", {
        nama: this.nama,
        alamat: this.alamat,
      });
      // reset
      this.nama = "";
      this.alamat = "";
    },
  },
};
</script>
on-save adalah nama custom event yang di trigger. Dan data yang dikirimkan adalah object yang berisi nama dan alamat yang diinput user.

Untuk menangkap event on-save ini, silahkan tambahkan v-on:<nama_event> di halaman utama (App.vue). Dalam hal ini adalah v-on:on-save atau disingkat dengan @on-save.

<template>
  <div id="app">
    ...
    <Modal ref="dlg" v-on:on-save="simpan" />
  </div>
</template>

<script>
import Modal from "./components/Modal";
export default {
  ...
  methods: {
    ...
    simpan(obj) {
      this.items.push(obj);
    },
  },
};
</script>
v-on:on-save="simpan" artinya, pada saat terjadi event on-save pada komponen Modal, panggil method simpan. Dimana pada method simpan, data yang diinput akan dimasukkan ke dalam array.

Di bawah ini kira-kira hasil akhirnya.

Mudah sekali bukan. Dalam banyak kasus, custom event ini akan sangat membantu aliran data child ke parent. Dimana hal ini akan sering terjadi jika Anda membagi aplikasi ke dalam komponen-komponen terpisah, yang harus saling berkomunikasi.

Sekian tip/trik kali ini. Selamat mencoba dan semoga yang sedikit ini bermanfaat.

Komentar

Load more