Menambahkan Inputan Money Menggunakan V-Money
Inputan nilai money berguna untuk aplikasi yang mengharuskan pengguna memasukkan jumlahnya. Membangun component input yang didedikasikan untuk input moneter adalah tugas yang membosankan. Anda perlu menambahkan label untuk menunjukkan bahwa itu adalah entri money dan Anda perlu memastikan bahwa entri tersebut valid. Beberapa input juga memerlukan prefix, suffix, dan input mask, yang membuat input sulit dibuat. Untungnya, Vue.js memiliki pustaka V-Money yang siap digunakan untuk pengembang.
Pada artikel ini, kami akan membuat aplikasi pelacak faktur yang melacak pengeluaran Anda. Hal ini memungkinkan pengguna untuk memasukkan nama faktur, jumlah, tanggal jatuh tempo, dan mengedit dan menghapusnya. Untuk mulai membangun proyek, jalankan VueCLI dengan menjalankan perintah berikut:
npx @vue/cli create bill-tracker
Saat wizard berjalan, pilih Manually select features dan pilih Babel, CSS preprocessor, Vuex, dan Vue router.
Selanjutnya, instal beberapa paket. Axios diperlukan untuk mengirim permintaan HTTP ke backend. Anda memerlukan Bootstrap-Vue untuk penataan, Vee-Validate untuk validasi form, dan V-Money untuk pemasukan money. Untuk menginstal paket, jalankan npm i axios bootstrap-vuevee-validatev-money. Setelah menginstal paket, Anda dapat mulai membuat aplikasi pelacak faktur.
Pertama, buat form yang memungkinkan pengguna untuk menambahkan dan mengedit faktur. Di direktori component, buat file bernama BillForm.vue dan tambahkan berikut ini:
<template>
<ValidationObserver ref="observer" v-slot="{ invalid }">
<b-form @submit.prevent="onSubmit" novalidate>
<b-form-group label="Name">
<ValidationProvider name="name" rules="required" v-slot="{ errors }">
<b-form-input
type="text"
:state="errors.length == 0"
v-model="form.name"
required
placeholder="Name"
name="name"
></b-form-input>
<b-form-invalid-feedback :state="errors.length == 0">Name is requied.</b-form-invalid-feedback>
</ValidationProvider>
</b-form-group><b-form-group label="Amount">
<ValidationProvider name="amount" rules="required|min_value:0" v-slot="{ errors }">
<money
v-model="form.amount"
v-bind="money"
class="form-control"
:class="{'is-valid': errors.length == 0, 'is-invalid': errors.length > 0}"
></money>
<b-form-invalid-feedback :state="errors.length == 0">{{errors.join('. ')}}</b-form-invalid-feedback>
</ValidationProvider>
</b-form-group><b-form-group label="Due Date">
<ValidationProvider name="dueDate" rules="required|date" v-slot="{ errors }">
<b-form-input
type="text"
:state="errors.length == 0"
v-model="form.dueDate"
required
placeholder="Due Date"
name="dueDate"
></b-form-input>
<b-form-invalid-feedback :state="errors.length == 0">{{errors.join('. ')}}</b-form-invalid-feedback>
</ValidationProvider>
</b-form-group><b-button type="submit" variant="primary" style="margin-right: 10px">Submit</b-button>
<b-button type="reset" variant="danger" @click="cancel()">Cancel</b-button>
</b-form>
</ValidationObserver>
</template><script>
import { requestsMixin } from "@/mixins/requestsMixin";export default {
name: "BillForm",
mixins: [requestsMixin],
props: {
bill: Object,
edit: Boolean
},
methods: {
async onSubmit() {
const isValid = await this.$refs.observer.validate();
if (!isValid) {
return;
}const offDate = new Date(this.form.date);
const correctedDate = new Date(
offDate.getTime() + Math.abs(offDate.getTimezoneOffset() * 60000)
);const params = {
...this.form,
date: correctedDate
};if (this.edit) {
await this.editBill(params);
} else {
await this.addBill(params);
}
const { data } = await this.getBills();
this.$store.commit("setBills", data);
this.$emit("saved");
},
cancel() {
this.$emit("cancelled");
}
},
data() {
return {
form: {},
money: {
decimal: ".",
thousands: ",",
prefix: "$ ",
precision: 2,
masked: false
}
};
},
watch: {
bill: {
handler(val) {
this.form = JSON.parse(JSON.stringify(val || {}));
},
deep: true,
immediate: true
}
}
};
</script>
form ini memungkinkan pengguna untuk mencari data yang tersedia dengan kata kunci tertentu, mengembalikan daftar bahan untuk data yang tersedia, menghapus duplikat dan menambahkannya ke daftar. Validasi input Anda menggunakan Vee-Validate. Gunakan component ValidationObserver untuk memantau validitas form di component dan ValidationProvider untuk melihat aturan validasi untuk nilai input dalam component. Di dalam ValidationProvider, ada input BootstrapVue untuk field input teks. b-form-input component. Juga, tambahkan validasi Vee-Validate untuk memverifikasi bahwa pengguna memasukkan tanggal sebelum mengirimkan. Buat field nama, jumlah, dan batas waktu yang diperlukan untuk properti aturan sehingga pengguna harus memasukkan semuanya untuk menyimpan faktur.
Memasuki field jumlah menggunakan component money dari library V-Money untuk menambahkan entri jumlah untuk jumlah yang ditagih. Arahan v-bind digunakan untuk mengatur opsi untuk memasukkan money. Objek money di field data memiliki opsi. Titik desimal ditandai dengan titik, koma dipisahkan oleh seribu opsi setiap tiga digit, dan jumlahnya ditentukan untuk didahului dengan tanda dolar untuk kejelasan. Precision 2 berarti pengguna dapat memasukkan hingga 2 digit, dan masked false berarti mask input telah dinonaktifkan. Saya menerapkan kelas CSS Bootstrap langsung ke component money untuk mencocokkan gaya dengan dua input lainnya. Kelas statis dan dinamis bekerja dengan baik dengan component money.
Jalankan this.$refs.observer.validate() untuk memvalidasi nilai fungsi onSubmit. Jika itu true, panggil fungsi di blok if untuk mengeksekusi kode yang menyimpan data, lalu panggil getNotes untuk mendapatkan catatan. Fungsi-fungsi ini berasal dari requestMixin yang Anda tambahkan. Data yang diperoleh adalah ini. Itu disimpan di toko Vuex dengan memanggil this.$store.commit.
component ini juga memiliki blok pemantau yang memantau jumlah tagihan dari toko Vuex yang perlu dibuat. Saat nilai tagihan diperbarui, daftar bahan terbaru diambil sehingga pengguna dapat mengedit yang terbaru saat menyalin nilai ke form ini.
Kemudian buat direktori mixins dan tambahkan requestMixin.js ke direktori mixins. Tambahkan yang berikut ini ke file:
const APIURL = "http://localhost:3000";
const axios = require("axios");export const requestsMixin = {
methods: {
getBills() {
return axios.get(`${APIURL}/bills`);
}, addBill(data) {
return axios.post(`${APIURL}/bills`, data);
}, editBill(data) {
return axios.put(`${APIURL}/bills/${data.id}`, data);
}, deleteBill(id) {
return axios.delete(`${APIURL}/bills/${id}`);
}
}
};
Ini adalah fungsi yang digunakan oleh component untuk membuat permintaan HTTP ke backend untuk menyimpan faktur. Kemudian di Home.vue, ganti kode yang ada dengan:
<template>
<div class="page">
<h1 class="text-center">Bill Tracker</h1>
<b-button-toolbar>
<b-button @click="openAddModal()">Add Bill</b-button>
</b-button-toolbar>
<br />
<b-table-simple responsive>
<b-thead>
<b-tr>
<b-th>Name</b-th>
<b-th>Amount</b-th>
<b-th>Due Date</b-th>
<b-th></b-th>
<b-th></b-th>
</b-tr>
</b-thead>
<b-tbody>
<b-tr v-for="b in bills" :key="b.id">
<b-td>{{b.name}}</b-td>
<b-td>${{b.amount}}</b-td>
<b-td>{{b.dueDate}}</b-td>
<b-td>
<b-button @click="openEditModal(b)">Edit</b-button>
</b-td>
<b-td>
<b-button @click="deleteOneBill(b.id)">Delete</b-button>
</b-td>
</b-tr>
</b-tbody>
</b-table-simple> <b-modal id="add-modal" title="Add Bill" hide-footer>
<BillForm @saved="closeModal()" @cancelled="closeModal()" :edit="false"></BillForm>
</b-modal> <b-modal id="edit-modal" title="Edit Bill" hide-footer>
<BillForm @saved="closeModal()" @cancelled="closeModal()" :edit="true" :bill="selectedBill"></BillForm>
</b-modal>
</div>
</template><script>
import BillForm from "@/components/BillForm.vue";
import { requestsMixin } from "@/mixins/requestsMixin";export default {
name: "home",
components: {
BillForm
},
mixins: [requestsMixin],
computed: {
bills() {
return this.$store.state.bills;
}
},
beforeMount() {
this.getAllBills();
},
data() {
return {
selectedBill: {}
};
},
methods: {
openAddModal() {
this.$bvModal.show("add-modal");
},
openEditModal(bill) {
this.$bvModal.show("edit-modal");
this.selectedBill = bill;
},
closeModal() {
this.$bvModal.hide("add-modal");
this.$bvModal.hide("edit-modal");
this.selectedBill = {};
this.getAllBills();
},
async deleteOneBill(id) {
await this.deleteBill(id);
this.getAllBills();
},
async getAllBills() {
const { data } = await this.getBills();
this.$store.commit("setBills", data);
}
}
};
</script>
Di sinilah Anda akan melihat faktur Anda di tabel BootstrapVue. Kolomnya adalah nama, jumlah, dan tanggal jatuh tempo, dan ada tombol Edit untuk membuka modal edit dan tombol Hapus untuk menghapus entri saat diklik. Kami juga telah menambahkan tombol Tambahkan Faktur untuk membuka modal sehingga pengguna dapat menambahkan faktur. Catatan diambil dari backend dengan menjalankan fungsi this.getAllBills di hook beforeMount, yang menyimpan data di Vuex store.
openAddModal, openEditModal, dan closeModal masing-masing membuka dan menutup modal terbuka dan menutup modal. Saat openEditModal dipanggil, setel variabel this.selectedNote agar dapat diteruskan ke NoteForm.
Kemudian di App.vue, ganti kode yang ada dengan:
<template>
<div id="app">
<b-navbar toggleable="lg" type="dark" variant="info">
<b-navbar-brand to="/">Bill Tracker</b-navbar-brand> <b-navbar-toggle target="nav-collapse"></b-navbar-toggle> <b-collapse id="nav-collapse" is-nav>
<b-navbar-nav>
<b-nav-item to="/" :active="path == '/'">Home</b-nav-item>
</b-navbar-nav>
</b-collapse>
</b-navbar>
<router-view />
</div>
</template><script>
export default {
data() {
return {
path: this.$route && this.$route.path
};
},
watch: {
$route(route) {
this.path = route.path;
}
}
};
</script><style lang="scss">
.page {
padding: 20px;
}button,
.btn.btn-primary {
margin-right: 10px !important;
}.button-toolbar {
margin-bottom: 10px;
}
</style>
Tambahkan bilah navigasi bootstrap di bagian atas halaman dan tambahkan Tampilan Router untuk menampilkan rute yang ditentukan. Bagian gaya ini tidak tercakup, sehingga gaya diterapkan secara global. Tambahkan padding ke halaman dengan pemilih .page. Tambahkan beberapa padding ke tombol kode gaya yang tersisa.
Kemudian, di main.js, ganti kode yang ada dengan:
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import money from "v-money";
import VueFilterDateFormat from "vue-filter-date-format";
import BootstrapVue from "bootstrap-vue";
import { ValidationProvider, extend, ValidationObserver } from "vee-validate";
import { required, min_value } from "vee-validate/dist/rules";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";extend("required", required);
extend("min_value", min_value);
extend("date", {
validate: value => {
return /([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/.test(value);
},
message: "Date must be in YYYY-MM-DD format."
});
Vue.use(BootstrapVue);
Vue.component("ValidationProvider", ValidationProvider);
Vue.component("ValidationObserver", ValidationObserver);
Vue.use(money, { precision: 4 });
Vue.use(VueFilterDateFormat);Vue.config.productionTip = false;new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
Saya telah menambahkan semua library di sini, termasuk JavaScript BootstrapVue dan component CSS dan Vee-Validate, dan menambahkan aturan validasi yang diperlukan dan aturan tanggal untuk memvalidasi bahwa tanggal jatuh tempo dalam format YYYY-MM-DD.
Di router.js, ganti kode yang ada dengan:
import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";Vue.use(Router);export default new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/",
name: "home",
component: Home
}
]
});
Sertakan halaman beranda Anda di root sehingga pengguna dapat melihat halaman tersebut.
Kemudian, di store.js, ganti kode yang ada dengan:
import Vue from "vue";
import Vuex from "vuex";Vue.use(Vuex);export default new Vuex.Store({
state: {
bills: []
},
mutations: {
setBills(state, payload) {
state.bills = payload;
}
},
actions: {}
});
Tambahkan status faktur ke toko sehingga Anda dapat mengamatinya di blok terhitung component BillForm dan HomePage. Ada fungsi setBills yang memperbarui status catatan, kemudian Digunakan oleh component dengan memanggil this.$store.commit ("setBills", data);. Seperti yang saya lakukan pada BillForm dan HomePage.
Terakhir, di index.html, ganti kode yang ada dengan:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>Bill Tracker</title>
</head>
<body>
<noscript>
<strong
>We're sorry but v-money-tutorial-app doesn't work properly without
JavaScript enabled. Please enable it to continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
Ubah judul aplikasi.
Setelah selesai dengan kerja keras, Anda dapat menjalankan npm run server untuk meluncurkan aplikasi.
Untuk memulai backend, pertama jalankan npm i json-server untuk menginstal paket json-server. Kemudian buka direktori proyek Anda dan jalankan perintah berikut:
json-server --watch db.json
Di db.json, ubah teks sebagai berikut:
{
"bills": []
}
Oleh karena itu, titik akhir bills yang ditentukan dalam request.js tersedia. Setelah semua kerja keras, terlihat seperti ini: