? ? No Code Attached Yet
avatar Hackwar
Hackwar
24 Nov 2022

Problem identified

Joomla has different ways to render a form or single form elements. There is the Joomla\CMS\Form\ library, which can read an XML and in conjunction with the FormField classes render different form elements. Then there is the Joomla\CMS\HTML\HTMLHelper class and the classes it is loading. This class essentially allows to render arbitrary HTML and is used among other things to render (partials of) select inputs. Both use different sets of layouts. None of these support code-hinting in common IDEs, both have different sets of features and while we grew accustomed to using them, they aren't exactly easy to handle. All these inconsistencies lead to nasty stuff like for example https://github.com/joomla/joomla-cms/blob/4.2-dev/administrator/components/com_menus/tmpl/items/default_batch_body.php#L59 where we have a partial select input hardcoded in the batch function and then additional options are rendered in the next few lines.

Proposed solution

The solution consists of several parts. First of all, HTMLHelper should be deprecated to render form elements. Then we introduce a new set of classes to render different form elements. These classes use layouts from /layouts/joomla/form/ and provide setters to handle the different options. For simple options we should have a base class with magic methods (and which handles the rendering similar to Joomla\CMS\Layout\FileLayout) and then child classes which inherit from said class. With appropriate hints in the docblocks, this should allow for code-hinting in IDEs. To allow for overrides and all that stuff, we should have a registry similar to HTMLHelper, but in contrast to that, it wouldn't return a string, but an object of the appropriate class.

With rendering of all form elements being moved to these classes, we should then adapt the FormField classes to use these new classes to generate their output. That would mean that all FormField classes have the same features as their none-Form counterparts and the FormField classes would mainly be delegated to convert the XML to a configuration for the rendering class and validation/conversion of input data as it does now. Ideally, the FormField classes would use other API calls to retrieve the necessary data instead of doing direct SQL queries.

This could also be the point to move these classes to the framework, maybe in 2 packages, one for the form element rendering and one for the XML forms. All of this could be easily made backwards compatible. Moving it to its own package(s) could also help with naming conflicts, considering that we probably would want to use something like Form.

Open questions

How should all this be named? Is the effort worth it?

We do have several parts which already work similar to this, some of which I mentioned here already. Unfortunately, the parts we have are not working together and they are stopping just inches short of what is described here. In the end, the goal is to reduce duplicate code, inconsistencies and difficulties for developers, while providing a better enduser experience.

avatar Hackwar Hackwar - open - 24 Nov 2022
avatar Hackwar Hackwar - change - 24 Nov 2022
Labels Added: ?
avatar Hackwar Hackwar - labeled - 24 Nov 2022
avatar joomla-cms-bot joomla-cms-bot - change - 24 Nov 2022
Labels Added: No Code Attached Yet
avatar joomla-cms-bot joomla-cms-bot - labeled - 24 Nov 2022
avatar brianteeman
brianteeman - comment - 24 Nov 2022

Should this not be on the rfc portal? @HLeithner @nibra


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/39303.

avatar dgrammatiko
dgrammatiko - comment - 24 Nov 2022

Both use different sets of layouts.

That's NOT true, ie calendar in the HTMLHelper is using joomla.form.field.calendar

return LayoutHelper::render('joomla.form.field.calendar', $data, null, null);

which is the exact same Layout on the CalendarField
protected $layout = 'joomla.form.field.calendar';

But I agree that the HTMLHelper methods that render a filed should be deprecated and removed as it's should be straight forward to use the Layout::render() already to render ALL the fields. That's since 3.5 when I and @phproberto moved the majority of the fields to layouts, separating the logic from the templating part.

In short, if the idea is to introduce yet another way of templating the end result would be to make it even harder than it already is for front end devs to use efficiently Joomla. Forms have other issues, deep architecture faults, but the templating is already solved.

My 2c

avatar Hackwar
Hackwar - comment - 25 Nov 2022

Both use different sets of layouts.

That's NOT true, ie calendar in the HTMLHelper is using joomla.form.field.calendar

Yes, some of them use the same layout, some of them don't.

But I agree that the HTMLHelper methods that render a filed should be deprecated and removed as it's should be straight forward to use the Layout::render() already to render ALL the fields. That's since 3.5 when I and @phproberto moved the majority of the fields to layouts, separating the logic from the templating part.

Layout::render() is NOT the same as HTMLHelper right now and even if it were, it doesn't solve the issue of code-hinting which I consider to be a major one. Without code-hinting, we also have no chance of automatically testing all configuration options of a field and will have broken fields for all eternity.

In short, if the idea is to introduce yet another way of templating the end result would be to make it even harder than it already is for front end devs to use efficiently Joomla. Forms have other issues, deep architecture faults, but the templating is already solved.

The idea is NOT to introduce yet another way of templating, but to actually remove one templating system. Right now HTMLHelper and FormField are 2 separate things and when you introduce an option in one, you still have to implement it in the other. My proposal would couple the two, forcing them to be in sync. In addition, having the code-hinting available would mean we could generate (partial) documentation from this.

avatar HLeithner
HLeithner - comment - 25 Nov 2022

Can't we move everything which looks like a form field to JForm only?

avatar Hackwar
Hackwar - comment - 25 Nov 2022

Do you really want to have all the overhead of an XML file and by default the jform[] namespace for all values? I don't think forcing everything to have such an overhead is a good solution...

avatar HLeithner
HLeithner - comment - 25 Nov 2022

Doesn't mean that jform can't be optimised.
It's possible to use jformfields with another driver/adapter which doesn't use it xmls. It's just an idea. Having one framework that works good is better then having 3 which are may work better for some tasks but difficult to use and to maintain.

What's an example element to get rid of? HTML.select right?

Don't you think it would be cool to jform::create element('list',xyz) and you use the needed subset of jformfields?

avatar dgrammatiko
dgrammatiko - comment - 25 Nov 2022

FWIW JLayout supports composition, so a select could have the sub layout options or groups and options or...

avatar Fedik
Fedik - comment - 29 Nov 2022

In my opinion, that batch thing should have own JFrom instance, and do render it, instead of hardcoding the fields.

avatar phproberto-bluebox
phproberto-bluebox - comment - 29 Nov 2022

Hello! I'm disconnected but adding a new way of rendering things sounds wrong to me. I agree that HTMLHelper should be deprecated and move everything it renders to layouts. Not sure why you need something new when current layout system already supports everything you want and is known by devs.

If you want something to render a class then just create a select field that creates the logic supporting optgroups, options, etc. that then is sent to a layout to get it rendered.

Something like:

$select = new SelectField('name');
$select->setId();
$select->setDisabled(false);
$optionDisabled = false;
$option = new Option('text', 'value', $optionDisabled);
$select->addOption($option);
$optgroup = new OptGroup();
$option2 = new Option('text2', 'value2', false);
$optgroup->addOption($option2);
$select->addOptgroup($optgroup); 

I wrote that directly here so it's probably wrong, etc. but I hope you get the concept. Then you can render that inside a layout just passing that object. And of course that object is not tied to a form or XML.

Inside joomla form fields you just have to run converters to map the XML of the options, optgroups, disable, etc.

Select, Option, Optgroups objecs > joomla form field creating them from XML > layout rendering the field

Of course you can create a new form class that contains the pure logic to render the form and do the same that I suggested for the select field but I think that would be quite complex and is better to just render the fields and the form using HTML. When a frontender sees all that logic to hide fieldsets, etc. they just want to remove everything and style things from scratch.

Summary: Keep migrating everything to layouts. Avoid creating new ways to render things.

avatar Hackwar
Hackwar - comment - 29 Nov 2022

Which is exactly what I described above...

avatar Hackwar Hackwar - change - 22 Feb 2023
Labels Added: ?
avatar Hackwar Hackwar - labeled - 22 Feb 2023

Add a Comment

Login with GitHub to post a comment