inline events in HTML using dynamically created WContainerWidget
Added by Dmitry Bagaev over 1 year ago
Hi!
I trying to use WContainerWidget (Wt 4.10), created dynamically, but in this case all widgets events inside container becomes inline in HTML (onclick property has set). App works, but html become unattractive. Help me please to solve problem. Next example shows it. Need fo solve case [3].
#include <Wt/WApplication.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WPushButton.h>
class SeparateButton : public Wt::WPushButton {
public:
SeparateButton() : Wt::WPushButton() {
auto btn = this;
btn->setText("X1");
btn->clicked().connect([] {
std::cout << "Button X1 clicked" << std::endl;
});
}
};
class ButtonInContainer : public Wt::WContainerWidget {
public:
ButtonInContainer() : Wt::WContainerWidget() {
auto btn = addNew<Wt::WPushButton>();
btn->setText("X2");
btn->clicked().connect([] {
std::cout << "Button X2 clicked" << std::endl;
});
}
};
class Example : public Wt::WApplication {
public:
explicit Example(const Wt::WEnvironment &env)
: WApplication{env} {
// [1] OK! <button id="ocg9yu3" type="button" class="Wt-btn with-label">X2</button>
root()->addNew<ButtonInContainer>();
root()->addNew<Wt::WPushButton>("make buttons")->clicked().connect([this]() {
// [2] OK! <button id="o1ut9whd" type="button" class="Wt-btn with-label">X1</button>
root()->addNew<SeparateButton>();
// [3] Not ok! <button id="o1ut9whf" type="button" onclick="var e=event||window.event,o=this;if(o.classList.contains('Wt-disabled')){Wt4_10_0.cancelEvent(e);return;}Wt._p_.update(o,'s9',e,true);" class="Wt-btn with-label">X2</button>
root()->addNew<ButtonInContainer>();
});
}
};
int main(int argc, char *argv[]) {
return Wt::WRun(argc, argv, [](const Wt::WEnvironment &env) {
return std::make_unique<Example>(env);
});
}
Replies (2)
RE: inline events in HTML using dynamically created WContainerWidget - Added by Matthias Van Ceulebroeck over 1 year ago
Hello Dmitry,
First, let me say that for me this example also adds the onclick
in HTML for the [1] case. And I suspect this is also what it does for you.
This is due to how we render items in Wt. In this case, the WPushButton
is part of another widget (a WContainerWidget
here). In which case to reduce the Javascript/client overhead, we ensure that the button is rendered on the server end, and added in pure HTML to the root (as part of the WContainerWidget
).
The SeparateButton
is simply added to the root
(a WContainerWidget
that is ALREADY RENDERED), and thus sent as a button to be added by the Javascript/client.
Were you for example to add a button in the lambda like:
auto container = root()->addNew<Wt::WContainerWidget>();
container->addNew<SeparateButton>();
You would see the same behavior (namely the onclick
handler in the HTML).
If you look at how Wt sets those up you can see that for the SeparateButton
you have:
var j8=document.createElement('button');j7.appendChild(j8);
j8.setAttribute('id', 'o1c68fgg');
j8.setAttribute('type','button');
j8.className='Wt-btn with-label';
function f9(event) { var e=event||window.event,o=this;if(o.classList.contains('Wt-disabled')){Wt4_10_1.cancelEvent(e);return;}Wt._p_.update(o,'s1a',e,true);}
j8.onclick=f9;
Wt4_10_1.setHtml(j8,'X1');
Whereas for the ButtonInContainer
you will get this:
var j11=document.createElement('div');j7.appendChild(j11);
j11.setAttribute('id', 'o1c68fgj');
Wt4_10_1.setHtml(j11,'<div><button id="o1c68fgk" type="button" onclick="var e=event||window.event,o=this;if(o.classList.contains(\'Wt-disabled\')){Wt4_10_1.cancelEvent(e);return;}Wt._p_.update(o,\'s1c\',e,true);" class="Wt-btn with-label">X2</button></div>');
Now, I agree that it is more sightly to have the event be generated in Javascript, and not be displayed in HTML, however this is functionality that is very ingrained in how we currently render content, which is not easily changed.
RE: inline events in HTML using dynamically created WContainerWidget - Added by Dmitry Bagaev over 1 year ago
Hello Matthias! Thank you for such a well-researched response, it’s motivating :) Now it’s clear that this is a feature of the implementation, justified by performance. I was worried that I was doing something wrong.