Skip to content

Commit

Permalink
externalized common code and fixed revalidation for expense type type…
Browse files Browse the repository at this point in the history
…ahead
  • Loading branch information
Michael Mueller committed Jan 20, 2017
1 parent d9e17f7 commit aa45b0b
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 74 deletions.
Empty file removed src/common/ui/formHelpers.ts
Empty file.
35 changes: 35 additions & 0 deletions src/common/ui/forms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as ReactDOM from 'react-dom'

export function addFormValidation(inputs: any[], revalidate: (input: any) => void) {
for (let input of inputs) {
input.addEventListener('input', event => revalidate(event.target))

input.addEventListener('invalid', (event) => {
const input: any = event.target;
input.closest('.form-group').classList.add('has-error')
})
}
}

export function resetFormValidationErrors(inputs: any[]) {
inputs.forEach(input => input.closest('.form-group') !.classList.remove('has-error'))
}

export function getInputs(component) {
return [...ReactDOM.findDOMNode(component).querySelectorAll('input,textarea')]
}

export function revalidateInput(input: any) {
input.closest('.form-group').classList.remove('has-error')
setTimeout(() => input.checkValidity())
}

export function enableTypeaheadFeatures(typeahead: any, name: string, required: boolean) {
const typeaheadInput =
ReactDOM.findDOMNode(typeahead.getInstance()).querySelector(`input[name=${name}]`)
typeaheadInput.setAttribute('id', name)

if (required) {
typeaheadInput.setAttribute('required', 'true')
}
}
46 changes: 8 additions & 38 deletions src/main/BillsEditorComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { listBillTypes, getBillTypeById, createBillType } from '../common/servic
import { listCustomers, createCustomer, getCustomerById, deleteCustomerById } from '../common/services/customersService'
import t from '../common/helpers/i18n'
import { numberFormatterDb, numberFormatterView, dateFormatterView, dateFormatterDb, getFilename } from '../common/ui/formatters'
import { enableTypeaheadFeatures, getInputs, resetFormValidationErrors, addFormValidation, revalidateInput } from '../common/ui/forms'
import Textarea from 'react-textarea-autosize'

const Datetime = require('react-datetime')
Expand Down Expand Up @@ -71,7 +72,7 @@ export default class BillsEditorComponent extends React.Component<Props, {}> {
this.fetchTypeaheadData()
process.nextTick(() => this.refs.invoice.focus())
this.dragCounter = 0
this.resetFormValidationErrors()
resetFormValidationErrors(getInputs(this))
}

getDefaultState(): State {
Expand Down Expand Up @@ -459,7 +460,6 @@ export default class BillsEditorComponent extends React.Component<Props, {}> {
newSelectionPrefix={t('Kunden anlegen: ')}
paginationText={t('Mehr anzeigen')}
maxResults={20}
tabIndex={1}
/>
<span className="sub-label">
<input
Expand Down Expand Up @@ -600,45 +600,15 @@ export default class BillsEditorComponent extends React.Component<Props, {}> {
)
}

addFormValidation() {
for (let input of this.getInputs()) {
input.addEventListener('input', event => this.revalidate(event.target))

input.addEventListener('invalid', (event) => {
const input: any = event.target;
input.closest('.form-group').classList.add('has-error')
})
}
}

resetFormValidationErrors() {
this.getInputs().forEach(input => input.closest('.form-group') !.classList.remove('has-error'))
}

getInputs() {
return [...ReactDOM.findDOMNode(this).querySelectorAll('input,textarea')]
}

revalidate(input) {
this.state.isDirty = true
input.closest('.form-group').classList.remove('has-error')
setTimeout(() => input.checkValidity())
}

enableTypeaheadFeatures(typeahead: any, name: string, required: boolean) {
const typeaheadInput =
ReactDOM.findDOMNode(typeahead.getInstance()).querySelector(`input[name=${name}]`)
typeaheadInput.setAttribute('id', name)

if (required) {
typeaheadInput.setAttribute('required', 'true')
}
this.state.isDirty = true // manipulate directly to prevent endless loop
revalidateInput(input)
}

componentDidMount() {
this.addFormValidation()
this.enableTypeaheadFeatures(this.refs.customerTypeahead, 'customer', true)
this.enableTypeaheadFeatures(this.refs.billTypeTypeahead, 'billType', false)
addFormValidation(getInputs(this), this.revalidate.bind(this))
enableTypeaheadFeatures(this.refs.customerTypeahead, 'customer', true)
enableTypeaheadFeatures(this.refs.billTypeTypeahead, 'billType', false)
}

componentWillReceiveProps(nextProps: Props) {
Expand All @@ -647,7 +617,7 @@ export default class BillsEditorComponent extends React.Component<Props, {}> {

if (this.state.isDirty && !confirm(t('Möchtest du die Änderungen verwerfen?'))) return

this.resetFormValidationErrors()
resetFormValidationErrors(getInputs(this))

if (isNew) {
this.resetState()
Expand Down
45 changes: 9 additions & 36 deletions src/main/ExpensesEditorComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import t from '../common/helpers/i18n'
import { numberFormatterDb, numberFormatterView, dateFormatterView, dateFormatterDb } from '../common/ui/formatters'
import { stringIsEmpty } from '../common/helpers/text'
import { getNetAmount, getVatAmount, getPreTaxAmount, hasDecimals } from '../common/helpers/math'
import { enableTypeaheadFeatures, getInputs, resetFormValidationErrors, addFormValidation, revalidateInput } from '../common/ui/forms'
import Textarea from 'react-textarea-autosize'

const Datetime = require('react-datetime')
Expand Down Expand Up @@ -55,7 +56,7 @@ export default class ExpensesEditorComponent extends React.Component<Props, {}>
this.setState(this.getDefaultState())
this.refs.expenseTypeTypeahead.getInstance().clear()
this.fetchTypeaheadData()
this.resetFormValidationErrors()
resetFormValidationErrors(getInputs(this))
}

getDefaultState(): State {
Expand Down Expand Up @@ -203,6 +204,8 @@ export default class ExpensesEditorComponent extends React.Component<Props, {}>
} else {
this.setState({ selectedExpenseType: selected })
}

this.revalidate(ReactDOM.findDOMNode(this.refs.expenseTypeTypeahead.getInstance()).querySelector('input[name=expenseType]'))
}

render() {
Expand Down Expand Up @@ -381,44 +384,14 @@ export default class ExpensesEditorComponent extends React.Component<Props, {}>
)
}

addFormValidation() {
for (let input of this.getInputs()) {
input.addEventListener('input', event => this.revalidate(event.target))

input.addEventListener('invalid', (event) => {
const input: any = event.target;
input.closest('.form-group').classList.add('has-error')
})
}
}

resetFormValidationErrors() {
this.getInputs().forEach(input => input.closest('.form-group') !.classList.remove('has-error'))
}

getInputs() {
return [...ReactDOM.findDOMNode(this).querySelectorAll('input,textarea')]
}

revalidate(input) {
this.state.isDirty = true
input.closest('.form-group').classList.remove('has-error')
setTimeout(() => input.checkValidity())
}

enableTypeaheadFeatures(typeahead: any, name: string, required: boolean) {
const typeaheadInput =
ReactDOM.findDOMNode(typeahead.getInstance()).querySelector(`input[name=${name}]`)
typeaheadInput.setAttribute('id', name)

if (required) {
typeaheadInput.setAttribute('required', 'true')
}
this.state.isDirty = true // manipulate directly to prevent endless loop
revalidateInput(input)
}

componentDidMount() {
this.addFormValidation()
this.enableTypeaheadFeatures(this.refs.expenseTypeTypeahead, 'expenseType', true)
addFormValidation(getInputs(this), this.revalidate.bind(this))
enableTypeaheadFeatures(this.refs.expenseTypeTypeahead, 'expenseType', true)
}

componentWillReceiveProps(nextProps: Props) {
Expand All @@ -427,7 +400,7 @@ export default class ExpensesEditorComponent extends React.Component<Props, {}>

if (this.state.isDirty && !confirm(t('Möchtest du die Änderungen verwerfen?'))) return

this.resetFormValidationErrors()
resetFormValidationErrors(getInputs(this))

if (isNew) {
this.resetState()
Expand Down

0 comments on commit aa45b0b

Please sign in to comment.