import $ from '$qui/lib/jquery.module.js'
import FormField from '../form-field.js'
/**
* A form field composed by multiple subfields.
* @alias qui.forms.commonfields.CompositeField
* @extends qui.forms.FormField
*/
class CompositeField extends FormField {
/**
* @constructs
* @param {qui.forms.FormField[]} fields the list of subfields
* @param {String} [flow] arrange subfield widgets vertically (`"vertical"`) or horizontally (`"horizontal"`,
* default)
* @param {Number} [columns] number of columns (unlimited by default, when `flow` is `"horizontal"`, otherwise
* defaults to `1`)
* @param {Number} [rows] number of rows (unlimited by default, when `flow` is `"vertical"`, otherwise defaults to
* `1`)
* @param {Boolean} [equalSize] set to `true` to make all cells of equal width/height (defaults to `false`)
* @param {...*} args parent class parameters
*/
constructor({fields, flow = 'horizontal', columns = null, rows = null, equalSize = false, ...args}) {
super(args)
this._fields = fields.map(this._preprocessField)
this._flow = flow
this._columns = columns
this._rows = rows
this._equalSize = equalSize
}
focus() {
/* Focus the first field */
this._fields.some(f => f.focus(), true)
}
makeWidget() {
let div = $('<div></div>', {class: 'qui-composite-field-container'})
let sizeSpec = this._equalSize ? '1fr' : 'auto'
if (this._flow === 'horizontal') {
if (this._columns) {
div.css('grid-template-columns', `repeat(${this._columns}, ${sizeSpec})`)
div.css('grid-auto-flow', 'row')
}
else {
div.css('grid-auto-flow', 'column')
}
}
else {
if (this._rows) {
div.css('grid-template-rows', `repeat(${this._rows}, ${sizeSpec})`)
div.css('grid-auto-flow', 'column')
}
else {
div.css('grid-auto-flow', 'row')
}
}
this._fields.forEach(function (field) {
div.append(field.getHTML())
})
return div
}
validateWidget(value) {
/* Return the first validation error among fields */
let error = null
this._fields.some(function (field) {
let e = field.validateWidget(value[field.getName()])
if (e != null) {
error = e
return true
}
})
return error
}
valueToWidget(value) {
this._fields.forEach(f => f.valueToWidget(value[f.getName()]))
}
widgetToValue() {
return Object.fromEntries(this._fields.map(f => [f.getName(), f.widgetToValue()]))
}
setWidgetReadonly(readonly) {
this._fields.forEach(f => f.setWidgetReadonly(readonly))
}
enableWidget() {
this._fields.forEach(f => f.enableWidget())
}
disableWidget() {
this._fields.forEach(f => f.disableWidget())
}
setForm(form) {
super.setForm(form)
this._fields.forEach(f => f.setForm(form))
}
/**
* Return the subfield with a given name. If no such field is found, `null` is returned.
* @param {String} name the name of the subfield
* @returns {?qui.forms.FormField}
*/
getField(name) {
return this._fields.find(f => f.getName() === name) || null
}
_preprocessField(field) {
field.setLabel('') /* Subfields of composite field can't have label */
field.setValueWidth(100) /* The value always occupies the entire space */
field._forceOneLine = true // TODO: this should be a field setter
return field
}
}
export default CompositeField