Project

General

Profile

Actions

Bug #11974

closed

Wt's Dbo Forms has no support for dynamically making fields visible

Added by Yoika Ghysens 7 months ago. Updated 6 months ago.

Status:
Closed
Priority:
Normal
Assignee:
Target version:
Start date:
09/22/2023
Due date:
% Done:

100%

Estimated time:

Description

Whenever we would make a field dynamically (in)visible by using WFormModel::setVisible the widget would be changed in the view by WTemplateFormView::updateViewField. The changing of the widget can either be removing it from the WTemplate when the widget is set to be invisible or binding it again when we're making it visible.

When using Wt's Dbo Forms and setting the model in the FormView the widgets are correctly constructed using the default/custom delegates that are defined for the fields in the model.
If we would then make one of the fields invisible, updateViewField will remove the widget from the template. If we make it visible after a while updateViewField will try to either resolve the widget from the template (but it has been previously removed so cannot be found) or create it using WTemplateFormView::createFormWidget.
The default implementation of createFormWidget simply returns std::unique_ptr<WWidget> so it has no effect and no widget will be bound.

Solution: FormView needs to override createFormWidget to recreate the widget based on the delegate set for the field.

The bug can be tested by making the below changes to the dbo forms example found in examples/dbo-form/DboForm.C

class TestDboModel : public Wt::Form::Dbo::FormModel<TestDboObject>
{
public:
  TestDboModel(Wt::Dbo::Session& session, Wt::Dbo::ptr<TestDboObject> item)
    : Wt::Form::Dbo::FormModel<TestDboObject>(session, item)
  {
    addAllDboColumnsAsFields();
    initDboValues();

    // ADD THIS LINE
    setVisible("bool_value", false);
  }
};

class TestDboView : public Wt::Form::Dbo::FormView<TestDboObject>
{
public:
  TestDboView(const Wt::WString& text, std::shared_ptr<TestDboModel> model)
    : Wt::Form::Dbo::FormView<TestDboObject>(text)
  {
    // ADD THESE LINES
    auto btn = std::make_unique<Wt::WPushButton>("Show bool field");
    btn-> clicked().connect([this] {
      this->model()->setVisible("bool_value", true);
      updateViewValue(this->model().get(), "bool_value");
    });
    bindWidget("show-bool-btn", std::move(btn));

    ...
  }
};

In example/dbo-form/approot/templates.xml you will then need to add the show-bool-btn placeholder to the message to ensure that the button is visible.

Running the modified example will then give the following behavior.

Initial view (note that the bool field isn't visible):

After clicking the button:

The label becomes visible but the widget isn't bound.


Files

Actions #1

Updated by Yoika Ghysens 7 months ago

  • Status changed from InProgress to Review
  • Assignee deleted (Yoika Ghysens)
  • Target version set to 4.10.2
Actions #2

Updated by Marnik Roosen 7 months ago

  • Assignee set to Marnik Roosen
Actions #3

Updated by Matthias Van Ceulebroeck 7 months ago

  • Assignee changed from Marnik Roosen to Matthias Van Ceulebroeck
Actions #4

Updated by Matthias Van Ceulebroeck 7 months ago

  • Status changed from Review to Implemented @Emweb
  • Assignee changed from Matthias Van Ceulebroeck to Yoika Ghysens
  • % Done changed from 0 to 100
Actions #5

Updated by Matthias Van Ceulebroeck 6 months ago

  • Status changed from Implemented @Emweb to Closed
Actions

Also available in: Atom PDF