Bug #13115
closedWidgets removed from disabled parents aren't rerendered correctly
100%
Description
When a parent widget is disabled, it will set a disabled flag which propagates to all child widgets.
The child widgets themselves won't get a disabled flag themselves.
They will keep their state to ensure that once the parent widget is enabled, the child widgets will get their previous state back.
Concretely:
- Create a view with some items
- Disable item 2
- Disable the view
- Enable the view
- Item two is still disabled
Say we were to remove an enabled child widget from a disabled parent widget, and add that child widget to the DOM tree again.
That child widget would still appear disabled. Even if we would manually call childWidget->enable()
, the widget remains disabled.
This issue is caused by the optimization within the following method. The child widget itself wasn't disabled, so it won't trigger a rerender.
void WWebWidget::setDisabled(bool disabled)
{
if (canOptimizeUpdates() && (disabled == flags_.test(BIT_DISABLED)))
return;
...
}
We should actually avoid this optimization when the parent widget changed, since the disabled state depends on the parent widget.
Test case to reproduce the issue:
#include <Wt/WApplication.h>
#include <Wt/WEnvironment.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WPushButton.h>
#include <Wt/WServer.h>
class ExtractDisabledChildApplication : public Wt::WApplication
{
public:
ExtractDisabledChildApplication(const Wt::WEnvironment& env)
: Wt::WApplication(env)
{
auto container = root()->addNew<Wt::WContainerWidget>();
auto text = container->addNew<Wt::WText>("I'm disabled due to the parent widget");
container->disable();
auto button = root()->addNew<Wt::WPushButton>("Click me!");
button->clicked().connect([this, button, container, text] {
button->disable();
auto w = container->removeWidget(text);
w->enable(); // This doesn't have any effect
w->setText("I should be enabled now, since I'm part of an enabled root widget and I'm not disabled myself");
root()->addWidget(std::move(w));
});
}
};
int main(int argc, char *argv[])
{
return Wt::WRun(argc, argv, [](const Wt::WEnvironment &env) {
return std::make_unique<ExtractDisabledChildApplication>(env);
});
}
Updated by Marnik Roosen 2 months ago
- Status changed from New to InProgress
- Assignee set to Marnik Roosen
Updated by Marnik Roosen 2 months ago
- Status changed from InProgress to Review
- Assignee deleted (
Marnik Roosen) - Target version set to 4.11.1
Updated by Matthias Van Ceulebroeck 2 months ago
- Assignee set to Matthias Van Ceulebroeck
Updated by Matthias Van Ceulebroeck 2 months ago
- Status changed from Review to Implemented @Emweb
- Assignee changed from Matthias Van Ceulebroeck to Marnik Roosen
- % Done changed from 0 to 100
Updated by Matthias Van Ceulebroeck 2 months ago
- Status changed from Implemented @Emweb to Implemented @Test
Updated by Matthias Van Ceulebroeck about 2 months ago
- Status changed from Implemented @Test to Closed