atk4 / ui

Robust and easy to use PHP Framework for Web Apps
https://atk4-ui.readthedocs.io
MIT License
440 stars 105 forks source link

When add()/init() is called right after the object is created it should have no effect on the result. #1027

Open mvorisek opened 4 years ago

mvorisek commented 4 years ago

Example:

$form = \atk4\ui\Form::addTo($personModal, ['segment']);
$personDropDown = \atk4\ui\FormField\DropDown::addTo($form);

// move submit button to the end of the form
$form->layout->removeElement(array_search($form->buttonSave, $form->layout->elements, true));
$form->layout->add($form->buttonSave);
DarkSide666 commented 4 years ago

Currently the only way to change order of elements after they are added is to mess with elements array of parent (or remove element and add it at the end) I think. At least that's what I have also done in some places. Probably there should be some nice-named method for that.

ibelar commented 4 years ago

Form rely on a layout View to add field and buttons. This layout view is added to the form template inside the Content tag.

In your code above, when creating the form instance, initLayout method is called, thus inserting the layout view within the Content region of the form. Then, your code added the $dropdown field within the same Content region of the form template.

Since the save button is part of the layout view, not the form view, and that it was added to the form template Content region first, then the button will always render first.

Hope this help.

mvorisek commented 4 years ago

@ibelar Thank you - yes, the issue with my example is that I added Dropdown to Form but the button is added to a layout... This moved the button to the end:

$form->removeElement(array_search($form->layout, $form->elements, true));
$form->add($form->layout);

But when I changed the second line of the original example to add the Dropdown to layout like:

$personDropDown = \atk4\ui\FormField\DropDown::addTo($form->layout);

Then I received an Exception:

Error: Call to a member function getCaption() on null (in .../vendor/atk4/ui/src/FormLayout/Generic.php:164)

Is this a bug? I am using this for one use case where I do not need model, thus I do not / can not easily use Form->addField().

ibelar commented 4 years ago

@mvorisek - no - this is not a bug. When rendering the form layout, it see that the object is a field type and try to set caption on it.

Not sure what you are trying to do but if you do not meed model, then why not just use form without model?

$form = \atk4\ui\Form::addTo($personModal, ['segment']);
$personDropDown = $form->addField('person', ['DropDown']);
mvorisek commented 4 years ago

I need a html form and single dropdown element with save button. Nothing else.

This works:

$personDropDown = new \atk4\ui\FormField\DropDown();
$form->addField('x', $personDropDown);

image

but the Field name (x in this example) is rendered.

To sum it up - I understand the logic, initially I tried to reorder elements in $form instead of $form->layout by a mistake. The order is given by the order of elements.

Currently Form supports AboveFields region. Wdyt to introduce region like afterInit for all elements that add some elements the the layout?

I am still thinking calling add() / init() should have optimally zero impact on the result. With the new ::addTo() method, which is used to create an object instance and to add it to the parent immediatelly, this is important. I am assigning this under myself and I will propose a PR for it.

Then reordering should not be needed that much thus renamed the title of this issue.

PhilippGrashoff commented 4 years ago

Hi, if you want to hide the fields caption (in your case the X), you can use the parameter inline of a FormLayout, e.g. $form->layout->inline = true. This, IIRC, leads to only the fields being rendered without the labels.

mvorisek commented 4 years ago

@PhilippGrashoff Thanks for pointing it out! It does not solve the that the result after add() / init() is different, but the labels are gone: image

But the property name inline is very confusing - @PhilippGrashoff, time to rename to noLabels?

PhilippGrashoff commented 4 years ago

I agree its confusing. More confusing even when regarding that Fomantic UI means by "inline" that the label is left of the input instead of above: https://fomantic-ui.com/collections/form.html#inline-field

@ibelar you are our form master. What do you think?

romaninsh commented 4 years ago

Form layout is a custom view that relies on fields getInput and augments it with labels, captions etc. There is a class for a form without any layout engine or you can use custom form layout.

ibelar commented 4 years ago

@PhilippGrashoff - I believe class inline in Fomantic-UI is meant to be applied on a group of fields. Having the first field in the group to have its label set to the left of it and the remaining fields in the group to appear next to each other.

mvorisek commented 4 years ago

@PhilippGrashoff - I believe class inline in Fomantic-UI is meant to be applied on a group of fields. Having the first field in the group to have its label set to the left of it and the remaining fields in the group to appear next to each other.

@ibelar But in atk the inline is used for noLabels :), see https://github.com/atk4/ui/issues/1027#issuecomment-606271988 , time to change it?

georgehristov commented 4 years ago

Wdyt to introduce region like afterInit for all elements that add some elements the the layout?

We were discussing introducing hooks into the init method for this purpose as some operations in init can only be performed when all elements added.

ibelar commented 4 years ago

@mvorisek - sorry was not clear enough. It also has the same behavior for atk4/ui. Declaring 'inline' field does remove the label because it follow Fomantic-UI rule. See demos/form.php in Layout Control tab

$gr = $f->addGroup(['Name', 'inline' => true]);
$gr->addField('first_name', ['width' => 'eight']);
$gr->addField('middle_name', ['width' => 'three', 'disabled' => true]);
$gr->addField('last_name', ['width' => 'five']);
Screen Shot 2020-03-31 at 10 22 55 AM
mvorisek commented 4 years ago

@ibelar Ok, thanks for the demo, in atk, "noLabels" is only side effect of inline.

PhilippGrashoff commented 4 years ago

well, "inline" class in Fomatic-UI can be used two ways, at least 2 I know of: 1) On a single field. <div class="inline field"> Causes the label to be left of the input instead of above, as FUI docs state. 2) In a group of fields, so far I used <div class="inline fields"><div class="field">...</div><div class="field">...</div></div> This also leads to all labels to appear left of the input instead of below. None of the FUI uses of "inline" class removes the labels...