Form as component, its handler and possible BC break in 2.3.0?

5 years ago

Jan Mikeš
Member | 777
+
0
-

Hey, I am using forms wrapped by components as components and after upgrading from 2.2 to 2.3 i am encountering following error: Component '' is not attached to ‘Nette\Application\UI\Presenter’ in presenter, when trying to set callback for onSuccess event.

Just to mention, i am using Kdyby\Autowired, not using this does not affect this issue

// XyPresenter.php
protected function createComponentXyForm(IControlFactory $factory)
{
    $control = $factory->create();
    $control["form"]->onSuccess[] = function($form) { // On this line error is occuring
        $this->redirect("default");
    };
    return $control;
}

// Control.php (created by IControlFactory)
protected function createComponentForm(FormFactory $factory)
{
    return $factory->create($this->entity);
}

I was able to fix this error adding Nette event to Control and passing form callback to it, instead of directly to the form, like this:

// XyPresenter.php
protected function createComponentXyForm(IControlFactory $factory)
{
    $control = $factory->create();
    $control->onFormSuccess[] = function($form) {
        $this->redirect("default");
    };
    return $control;
}

// Control.php
public $onFormSuccess = [];

protected function createComponentForm(FormFactory $factory)
{
    $form = $factory->create($this->entity);
    $form->onSuccess[] = function($form) {
        $this->onFormSuccess($form);
    };
    return $form;
}

I believe that my fix for the problem is much cleaner solution, but is not this unmentioned BC break or why code, which worked on previous version is not working anymore?

Last edited by Lexi (2015-03-13 11:56)

4 years ago

urug
Member | 4
+
0
-

I quess the problem is that Nette is proccessing components after the whole presenter lifecycle is done ( which is really retarded if you ask me). This includes calling those “createComponent” factories and attaching created components to presenter (yes the component is attached to presenter after the presenter is done, you can observe that with a little dumping in action/render/shutdown/createComponent).
However you can create a component in your presenter's action and attach it to presenter there, so it's available to presenter for the rest of the presenter lifecycle.

Last edited by urug (2015-11-27 16:59)

4 years ago

Jan Mikeš
Member | 777
+
0
-

Yes, this was not intended to be question about how to solve this problem, but to point out that this is possible undocumented BC break – worked before 2.3, after composer update not anymore.

4 years ago

Milo
Nette Core | 1151
+
0
-

@Lexi The replacement seems to be non equivalent. In old code, you are adding event on $control['form']. In new code, you are adding event directly to $control. Is that intentional?

4 years ago

Jan Mikeš
Member | 777
+
0
-

@Milo yes it is, notice control's component factory for form. Form's onSuccess[] is invoking control event “onFormSuccess”, so the functionality is same as i would declare $control["form"]->onSuccess[] in presenter.

Edit: The difference is when i was trying to access nested component in component i had the exception not attached to presenter… When accessing only top level component everything is fine

Last edited by Lexi (2015-12-02 12:03)