extends |
Control |
|---|
Creates a Multiline field within a table, which allows adding/editing multiple data rows.
Using hasMany reference will required to save reference data using Multiline::saveRows() method.
$form = Form::addTo($app); $form->setModel($invoice, []);
// add Multiline form control and set model for Invoice items $ml = $form->addControl('ml', [Multiline::class]); $ml->setReferenceModel('Items', null, ['item', 'cat', 'qty', 'price', 'total']);
$form->onSubmit(function (Form $form) use ($ml) { // save Form model and then Multiline model $form->model->save(); // saving invoice record $ml->saveRows(); // saving invoice items record related to invoice return new JsToast('Saved!'); });
If Multiline's model contains expressions, these will be evaluated on the fly whenever data gets entered.
Multiline input also has an onChange callback that will return all data rows in an array. It is also possible to fire onChange handler only for certain fields by passing them as an array to the method.
Note that deleting a row will always fire the onChange callback.
You can use the returned data to update other related areas of the form. For example, updating Grand Total field of all invoice items.
$ml->onChange(function (array $rows) use ($form) { $grandTotal = 0; foreach ($rows as $row => $cols) { foreach ($cols as $col) { $fieldName = array_key_first($col); if ($fieldName === 'total') { $grandTotal += $col[$fieldName]; } } }
return $form->js(false, null, 'input[name="grand_total"]')->val($app->uiPersistence->typecastSaveField(new Field(['type' => 'atk4_money']), $grandTotal)); }, ['qty', 'price']);
Finally, it's also possible to use Multiline for quickly adding records to a model. Be aware that in the example below all User records will be displayed. If your model contains a lot of records, you should handle their limit somehow.
$form = Form::addTo($app); $ml = $form->addControl('ml', [Form\Control\Multiline::class]); $ml->setModel($user, ['name', 'is_vip']);
$form->onSubmit(function (Form $form) use ($ml) { $ml->saveRows(); return new JsToast('Saved!'); });
| Methods | ||
|---|---|---|
protected
|
init(): void
|
# |
protected
|
typeCastLoadValues(array $values): array
|
# |
public
|
onLineChange(Closure(mixed, Form): (JsExpressionable|View|string|void) $fx, array $fields): void
|
# |
public
|
getValue(): string
|
# |
public
|
validate(array $rows): array
|
# |
public
|
saveRows(): $this
|
# |
protected
|
addModelValidateErrors(array $errors, string $rowId, Model $entity): array
|
# |
private
|
getMlRowId(array $row): ?string
|
# |
public
|
setModel(Model $model, array<int, string>|null $fields = null): void
|
# |
public
|
setReferenceModel(string $refModelName, Model $entity = null, array $fieldNames = []): void
|
# |
public
|
getFieldDef(Field $field): array
|
# |
protected
|
getSuiTableCellProps(Field $field): array
|
# |
protected
|
getSuiInputProps(Field $field): array
|
# |
protected
|
getDatePickerProps(Field $field): array
|
# |
protected
|
getDropdownProps(Field $field): array
|
# |
protected
|
getLookupProps(Field $field): array
|
# |
public
|
setLookupOptionValue(Field $field, string $value): void
|
# |
protected
|
getComponentDefinition(Field $field): array
|
# |
protected
|
getFieldItems(Field $field, ?int $limit = 10): array
|
# |
protected
|
valuePropsBinding(string $values): void
|
# |
protected
|
renderView(): void
|
# |
private
|
outputJson(): void
|
# |
private
|
getCallbackValues(Model $entity): array
|
# |
private
|
createDummyEntityFromPost(Model $model): Model
|
# |
private
|
getExpressionFields(Model $model): array<string, SqlExpressionField>
|
# |
private
|
getExpressionValues(Model $entity): array
|
# |
private
|
getDummyExpression(SqlExpressionField $exprField, Model $entity): string
|
# |
private
|
getValueForExpression(Field $exprField, string $fieldName, Model $entity): string
|
# |
| Methods inherited from Atk4\Ui\Form\Control |
|---|
set(), renderTemplateToHtml(), onChange(), jsInput() |
| Methods inherited from Atk4\Ui\AbstractView |
|---|
getOwner() |
| Methods used from Atk4\Core\AppScopeTrait |
|---|
assertInstanceOfApp(), issetApp(), getApp(), setApp() |
| Methods used from Atk4\Core\ContainerTrait |
|---|
_uniqueElementName(), _addContainer(), removeElement(), _shorten(), getElement(), hasElement() |
| Methods used from Atk4\Core\InitializerTrait |
|---|
isInitialized(), assertIsInitialized(), invokeInit() |
| Methods used from Atk4\Core\StaticAddToTrait |
|---|
_addToAdd(), addTo(), addToWithCl(), addToWithClUnsafe() |
| Methods used from Atk4\Core\TrackableTrait |
|---|
issetOwner(), setOwner(), unsetOwner(), getDesiredName(), destroy() |
| Constants | ||
|---|---|---|
public
|
INPUT = 'SuiInput'
|
# |
public
|
READ_ONLY = 'AtkMultilineReadonly'
|
# |
public
|
TEXT_AREA = 'AtkMultilineTextarea'
|
# |
public
|
SELECT = 'SuiDropdown'
|
# |
public
|
DATE = 'AtkDatePicker'
|
# |
public
|
LOOKUP = 'AtkLookup'
|
# |
public
|
TABLE_CELL = 'SuiTableCell'
|
# |
| Properties | |||
|---|---|---|---|
public
|
HtmlTemplate|null
|
$multiLineTemplate
|
# |
private
|
View
|
$multiLine
|
# |
public
|
array
|
$componentProps = []
|
# |
public
|
array
|
$tableProps = []
|
# |
protected
|
array<string, array<string, mixed>>
|
$fieldMapToComponent = [
'default' => ['component' => self::INPUT, 'componentProps' => [__CLASS__, 'getSuiInputProps']],
'readonly' => ['component' => self::READ_ONLY, 'componentProps' => []],
'textarea' => ['component' => self::TEXT_AREA, 'componentProps' => []],
'select' => ['component' => self::SELECT, 'componentProps' => [__CLASS__, 'getDropdownProps']],
'date' => ['component' => self::DATE, 'componentProps' => [__CLASS__, 'getDatePickerProps']],
'lookup' => ['component' => self::LOOKUP, 'componentProps' => [__CLASS__, 'getLookupProps']],
]
|
# |
public
|
bool
|
$addOnTab = false
|
# |
private
|
array
|
$fieldDefs
|
# |
private
|
JsCallback
|
$renderCallback
|
# |
protected
|
(Closure(mixed, Form): (JsExpressionable|View|string|void))|null
|
$onChangeFunction
|
# |
protected
|
array
|
$eventFields
|
# |
private
|
array
|
$rowErrors
|
# |
public
|
array
|
$rowFields
|
# |
public
|
array
|
$rowData
|
# |
public
|
int
|
$rowLimit = 0
|
# |
public
|
int
|
$itemLimit = 25
|
# |
private
|
array<string, Closure(Field, string): void>
|
$valuePropsBinding = []
|
# |
public
|
JsFunction
|
$jsAfterAdd
|
# |
public
|
JsFunction
|
$jsAfterDelete
|
# |
| Properties inherited from Atk4\Ui\Form\Control |
|---|
$form, $entityField, $controlClass, $layoutWrap, $renderLabel, $width, $caption, $hint, $disabled, $readOnly |
| Properties inherited from Atk4\Ui\View |
|---|
$_jsActions, $model, $region, $ui, $class, $style, $attr, $template, $defaultTemplate, $content, $element, $executorFactory, $stickyArgs |
| Properties inherited from Atk4\Ui\AbstractView |
|---|
$_addLater, $_rendered, $elements |
| Properties used from Atk4\Core\AppScopeTrait |
|---|
$_app, $maxNameLength, $uniqueNameHashes |
| Properties used from Atk4\Core\ContainerTrait |
|---|
$_elementNameCounts |
| Properties used from Atk4\Core\InitializerTrait |
|---|
$_initialized |
| Properties used from Atk4\Core\NameTrait |
|---|
$name |
| Properties used from Atk4\Core\TrackableTrait |
|---|
$_owner, $shortName |