import { Component, NewState, Util, $ } from '@web/state'
import { HTTP } from './http.js'
Component.register('AutoForm', container => {
if (!container.state.schema) container.state.schema = []
container.vertical = container.hasAttribute('vertical')
container.inline = container.hasAttribute('inline')
container.request = { method: 'POST' }
container.response = {}
container.result = null
// 立即初始化数据代理,避免异步延迟导致 Select 等组件初始化时找不到值而重置
if (!container.data || !container.data.__watch) {
container.data = NewState(container.data || {})
}
container.data.__watch('*', () => {
if (container.inline) {
const dt = container.closest('DataTable')
if (dt && dt.refresh) dt.refresh()
}
})
container.form = $(container, 'form')
container.submit = (opt = {}) => {
if (!container.form.reportValidity()) return globalThis.UI?.toast?.('{#verify failed#}', { type: 'danger' })
if (!container.dispatchEvent(new CustomEvent('submit', { detail: container.data, cancelable: true, bubbles: false }))) return
const req = { ...container.request, data: container.data, noui: true, ...opt }
let task = null
if (container.api) task = container.api.do(req)
else if (container.request.url) task = HTTP.request(req)
else return console.warn('{#please config .api or .request.url to auto submit#}')
task.then(resp => {
container.response = resp
container.result = resp.result
if (typeof resp.result === 'object' && resp.result.error) throw new Error(resp.result.error)
container.dispatchEvent(new CustomEvent('response', { detail: resp, bubbles: false }))
}).catch(err => {
if (globalThis.UI?.toast) UI.toast(err.message, { type: 'danger' })
container.dispatchEvent(new CustomEvent('error', { detail: err, bubbles: true }))
})
}
}, Util.makeDom(/*html*/`
`), Util.makeDom(/*html*/``))
const _pendingAutoFormComponents = []
export const AutoForm = {
register: name => {
if (typeof document !== 'undefined') {
if (document.readyState !== 'loading' && Component.getTemplate('AutoForm')) AutoForm._addAutoFormComponent(name)
else _pendingAutoFormComponents.push(name)
}
},
_addAutoFormComponent: name => {
const template = Component.getTemplate('AutoForm')
if (template) {
$(template.content, '[control-wrapper]')?.appendChild(Util.makeDom(`<${name} $if="item.type.toUpperCase() === '${name.toUpperCase()}'" $name="item.name" $.="item.setting || {}" $bind="this.data[item.name]">${name}>`))
}
}
}
if (typeof document !== 'undefined') {
const initAutoForm = () => {
_pendingAutoFormComponents.forEach(name => AutoForm._addAutoFormComponent(name))
_pendingAutoFormComponents.length = 0
}
if (document.readyState !== 'loading') setTimeout(initAutoForm, 100)
else document.addEventListener('DOMContentLoaded', () => setTimeout(initAutoForm, 100), true)
}
Component.register('TagsInput', container => {
container.addEventListener('bind', e => {
container.state.tags = e.detail || []
})
}, Util.makeDom(/*html*/`
{
if (event.isComposing) return
if (['Enter', ',', ' '].includes(event.key)) {
event.preventDefault()
const v = thisNode.value.trim()
if (v && !this.state.tags.includes(v)) {
this.state.tags.push(v)
this.state.tags = this.state.tags
this.dispatchEvent(new CustomEvent('change', { bubbles: false, detail: this.state.tags }))
}
thisNode.value = ''
}
})}">
`), Util.makeDom(/*html*/``))
AutoForm.register('TagsInput')