Validate expense/reimbursement forms
Adds some general helpers and styles for minimalistic form validation.
This commit is contained in:
@@ -2,6 +2,7 @@ import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
import moment from 'moment';
|
||||
import isValidAmount from 'kredits-web/utils/is-valid-amount';
|
||||
|
||||
export default class AddExpenseItemComponent extends Component {
|
||||
// @tracked newExpense = Expense.create();
|
||||
@@ -22,6 +23,14 @@ export default class AddExpenseItemComponent extends Component {
|
||||
{ code: 'GBP' }
|
||||
];
|
||||
|
||||
get isValidAmount () {
|
||||
return isValidAmount(this.amount);
|
||||
}
|
||||
|
||||
get amountInputClass () {
|
||||
return this.isValidTotal ? 'valid' : '';
|
||||
}
|
||||
|
||||
get submitButtonEnabled () {
|
||||
return true;
|
||||
}
|
||||
@@ -30,6 +39,27 @@ export default class AddExpenseItemComponent extends Component {
|
||||
return !this.submitButtonEnabled;
|
||||
}
|
||||
|
||||
validateForm () {
|
||||
const formEl = document.querySelector('form#add-expense-item');
|
||||
let validity = true;
|
||||
|
||||
if (!this.isValidAmount) {
|
||||
document.querySelector('input[name=expense-amount]').classList.add('invalid');
|
||||
validity = false;
|
||||
}
|
||||
|
||||
if (!formEl.checkValidity()) {
|
||||
document.querySelectorAll('form#add-expense-item input').forEach(i => {
|
||||
if (!i.validity.valid) {
|
||||
i.classList.add('invalid');
|
||||
validity = false;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return validity;
|
||||
}
|
||||
|
||||
@action
|
||||
submit (e) {
|
||||
e.preventDefault();
|
||||
@@ -38,17 +68,21 @@ export default class AddExpenseItemComponent extends Component {
|
||||
this.date[0] : this.date;
|
||||
const [ date ] = dateInput.toISOString().split('T');
|
||||
|
||||
// TODO validate form
|
||||
const expense = {
|
||||
amount: parseFloat(this.amount),
|
||||
currency: this.currency,
|
||||
date: date,
|
||||
title: this.title,
|
||||
description: this.description,
|
||||
url: this.url,
|
||||
tags: this.tags.split(',').map(t => t.trim())
|
||||
}
|
||||
const isValid = this.validateForm();
|
||||
|
||||
this.args.addExpenseItem(expense);
|
||||
if (isValid) {
|
||||
const expense = {
|
||||
amount: parseFloat(this.amount),
|
||||
currency: this.currency,
|
||||
date: date,
|
||||
title: this.title,
|
||||
description: this.description,
|
||||
url: this.url,
|
||||
tags: this.tags.split(',').map(t => t.trim())
|
||||
}
|
||||
this.args.addExpenseItem(expense);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
<form id="add-expense-item" onsubmit={{action "submit"}}>
|
||||
<form id="add-expense-item" onsubmit={{action "submit"}} novalidate>
|
||||
<fieldset class="horizontal">
|
||||
<label>
|
||||
<p class="label">Amount:</p>
|
||||
<p>
|
||||
{{input name="expense-amount" type="text"
|
||||
placeholder="10" value=this.amount}}
|
||||
{{input name="expense-amount"
|
||||
type="text"
|
||||
placeholder="10"
|
||||
value=this.amount
|
||||
required=true
|
||||
pattern="([0-9]*[.])?[0-9]+"
|
||||
class=this.amountInputClass}}
|
||||
</p>
|
||||
</label>
|
||||
<label>
|
||||
@@ -35,7 +40,10 @@
|
||||
<label>
|
||||
<p class="label">Title:</p>
|
||||
<p>
|
||||
{{input name="expense-title" type="text" value=this.title}}
|
||||
{{input name="expense-title"
|
||||
type="text"
|
||||
value=this.title
|
||||
required=true}}
|
||||
</p>
|
||||
</label>
|
||||
<label>
|
||||
@@ -47,7 +55,7 @@
|
||||
<label>
|
||||
<p class="label">URL (optional):</p>
|
||||
<p>
|
||||
{{input name="expense-url" type="text" value=this.url}}
|
||||
{{input name="expense-url" type="url" value=this.url}}
|
||||
</p>
|
||||
</label>
|
||||
<label>
|
||||
|
||||
Reference in New Issue
Block a user