joomla-cms icon indicating copy to clipboard operation
joomla-cms copied to clipboard

Problems with replacing Form:getInstance

Open prinswebdevelopment opened this issue 1 month ago • 3 comments

Joomla 5.4 (but I see the same problem in 6.1):

Form:getInstance (libraries/src/Form/Form.php:1691) is deprecated. The replacement doesn't work the same way, however, because the old method uses a singleton pattern. If you currently use Model:preprocessForm in your model and want to edit a subform, it will no longer work. In the 'old' method, you can do this:

protected function preprocessForm(Form $form, $data, $group = 'content')
    {
        parent::preprocessForm($form, $data, $group);

        $subFormField = $form->getField('subform');

        $i = 0;
        foreach ($data->surveys as $key => $row) {
        
            $subForm = Form::getInstance('subform.surveys' . $i, $subFormField->__get('formsource'), ['control' => 'jform[surveys][survey' . $i . ']']);

			// create new field
			$field = new \SimpleXMLElement('<field></field>');
			$field->addAttribute('name', 'readonly_spacer');
            $field->addAttribute('type', 'spacer');
            $field->addAttribute('hiddenLabel', 'true');
            $field->addAttribute('description', Text::_('TEXT'));
            
            // Voeg het veld toe aan het formulier
            $subForm->setField($field);

        }
        $i++;
    }
}

But in the new method:

$subForm = Form::getInstance('subform.surveys' . $i, $subFormField->__get('formsource'), ['control' => 'jform[surveys][survey' . $i . ']']);

replaced:

$formFactory = Factory::getContainer()->get(FormFactoryInterface::class);
$subForm = $formFactory->createForm('subform.surveys' . $i, ['control' => 'jform[surveys][survey' . $i . ']']);
$subForm->load($subFormField->__get('formsource'));

This doesn't work because if the form is loaded in libraries/src/Form/Field/SubformField.php:385, a new object is created and the old one isn't reused. Furthermore, I believe it's impossible to edit a subform in the model.

prinswebdevelopment avatar Nov 28 '25 10:11 prinswebdevelopment

The issue is similar to

  • https://github.com/joomla/joomla-cms/issues/46369

But I would keep it open because it is more specific

Fedik avatar Dec 06 '25 08:12 Fedik

@prinswebdevelopment can you be more precisely? you copy code from 2 functions where I'm not sure which one is where and what code you mean has changed and what is no longer possible. please link the code in the cms where you no longer get the form object the way you need it. Or where you expect the form object and don't get the right one.

thanks

HLeithner avatar Dec 06 '25 09:12 HLeithner

It’s not that complicated. Create a component with a form that contains a subform. In the component’s model, implement the preprocessForm() method. Modify the subform there by loading it via Form::getInstance(). When Joomla later renders the subform in the layout, the same instance is used, because getInstance() acts as a cache.

Although it is recommended to create Form objects via $formFactory->createForm(), doing so here is pointless. That method always creates a new form instance and does not use a cache. As a result, the subform used in the layout is recreated and any earlier changes are lost.

Joomla does not provide any other mechanism to preprocess subforms.

prinswebdevelopment avatar Dec 08 '25 18:12 prinswebdevelopment