Files
budget_analyser/node_modules/@inertiajs/inertia-vue3/src/useForm.js
TiclemFR 076ec32c3b 🔧
2023-12-29 17:47:40 +01:00

208 lines
5.3 KiB
JavaScript

import isEqual from 'lodash.isequal'
import { reactive, watch } from 'vue'
import cloneDeep from 'lodash.clonedeep'
import { Inertia } from '@inertiajs/inertia'
export default function useForm(...args) {
const rememberKey = typeof args[0] === 'string' ? args[0] : null
const data = (typeof args[0] === 'string' ? args[1] : args[0]) || {}
const restored = rememberKey ? Inertia.restore(rememberKey) : null
let defaults = cloneDeep(data)
let cancelToken = null
let recentlySuccessfulTimeoutId = null
let transform = data => data
let form = reactive({
...restored ? restored.data : data,
isDirty: false,
errors: restored ? restored.errors : {},
hasErrors: false,
processing: false,
progress: null,
wasSuccessful: false,
recentlySuccessful: false,
data() {
return Object
.keys(data)
.reduce((carry, key) => {
carry[key] = this[key]
return carry
}, {})
},
transform(callback) {
transform = callback
return this
},
defaults(key, value) {
if (typeof key === 'undefined') {
defaults = this.data()
} else {
defaults = Object.assign(
{},
cloneDeep(defaults),
value ? ({ [key]: value }) : key,
)
}
return this
},
reset(...fields) {
let clonedDefaults = cloneDeep(defaults)
if (fields.length === 0) {
Object.assign(this, clonedDefaults)
} else {
Object.assign(
this,
Object
.keys(clonedDefaults)
.filter(key => fields.includes(key))
.reduce((carry, key) => {
carry[key] = clonedDefaults[key]
return carry
}, {}),
)
}
return this
},
setError(key, value) {
Object.assign(this.errors, (value ? { [key]: value } : key))
this.hasErrors = Object.keys(this.errors).length > 0
return this
},
clearErrors(...fields) {
this.errors = Object
.keys(this.errors)
.reduce((carry, field) => ({
...carry,
...(fields.length > 0 && !fields.includes(field) ? { [field] : this.errors[field] } : {}),
}), {})
this.hasErrors = Object.keys(this.errors).length > 0
return this
},
submit(method, url, options = {}) {
const data = transform(this.data())
const _options = {
...options,
onCancelToken: (token) => {
cancelToken = token
if (options.onCancelToken) {
return options.onCancelToken(token)
}
},
onBefore: visit => {
this.wasSuccessful = false
this.recentlySuccessful = false
clearTimeout(recentlySuccessfulTimeoutId)
if (options.onBefore) {
return options.onBefore(visit)
}
},
onStart: visit => {
this.processing = true
if (options.onStart) {
return options.onStart(visit)
}
},
onProgress: event => {
this.progress = event
if (options.onProgress) {
return options.onProgress(event)
}
},
onSuccess: async page => {
this.processing = false
this.progress = null
this.clearErrors()
this.wasSuccessful = true
this.recentlySuccessful = true
recentlySuccessfulTimeoutId = setTimeout(() => this.recentlySuccessful = false, 2000)
const onSuccess = options.onSuccess ? await options.onSuccess(page) : null
defaults = cloneDeep(this.data())
this.isDirty = false
return onSuccess
},
onError: errors => {
this.processing = false
this.progress = null
this.clearErrors().setError(errors)
if (options.onError) {
return options.onError(errors)
}
},
onCancel: () => {
this.processing = false
this.progress = null
if (options.onCancel) {
return options.onCancel()
}
},
onFinish: () => {
this.processing = false
this.progress = null
cancelToken = null
if (options.onFinish) {
return options.onFinish()
}
},
}
if (method === 'delete') {
Inertia.delete(url, { ..._options, data })
} else {
Inertia[method](url, data, _options)
}
},
get(url, options) {
this.submit('get', url, options)
},
post(url, options) {
this.submit('post', url, options)
},
put(url, options) {
this.submit('put', url, options)
},
patch(url, options) {
this.submit('patch', url, options)
},
delete(url, options) {
this.submit('delete', url, options)
},
cancel() {
if (cancelToken) {
cancelToken.cancel()
}
},
__rememberable: rememberKey === null,
__remember() {
return { data: this.data(), errors: this.errors }
},
__restore(restored) {
Object.assign(this, restored.data)
this.setError(restored.errors)
},
})
watch(form, newValue => {
form.isDirty = !isEqual(form.data(), defaults)
if (rememberKey) {
Inertia.remember(cloneDeep(newValue.__remember()), rememberKey)
}
}, { immediate: true, deep: true })
return form
}