Project

General

Profile

Image example as client side without JS

Added by Victor Corchez 8 months ago

Is there a way to implement the Image example from the widget gallery as client side without having to write JS code?
I've read a bit about implementStateless but I don't really understand what are the limitations..

I've tried like this but doesn't seem to work..

#include <Wt/WApplication.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WImage.h>
#include <Wt/WLink.h>
#include <Wt/WText.h>

using namespace Wt;
using namespace std;

class Container : public WContainerWidget
{
public:
    Container()
    {
        Wt::WImage *image = addNew<Wt::WImage>(Wt::WLink("icons/wt.png"));
        image->setAlternateText("Wt logo");

        out = addNew<Wt::WText>();
        out->setMargin(10, Wt::Side::Left);

        implementStateless(&Container::setTextOut);

        image->clicked().connect([&] (const Wt::WMouseEvent& e) {
            x = e.widget().x;
            y = e.widget().y;
            cout << x << " " << y << endl;
            setTextOut();
        });
    }
private:
    void setTextOut()
    {
        out->setText("You clicked the Wt logo at "
                     "(" + std::to_string(x) +
                     "," + std::to_string(y) +
                     ").");
    }

    Wt::WText *out;
    int x;
    int y;
};

class TestApp: public WApplication
{
public:
    TestApp(const WEnvironment &env): WApplication(env) {

        setTitle("TEST");
        //useStyleSheet("painting.css");

        root()->addWidget(std::make_unique<Container>());
    }
};

std::unique_ptr<WApplication> createApplication(const WEnvironment& env)
{
    return std::make_unique<TestApp>(env);
}

int main(int argc, char **argv)
{
    return WRun(argc, argv, &createApplication);
}


Replies (1)

RE: Image example as client side without JS - Added by Matthias Van Ceulebroeck 8 months ago

Hi Victor,

this example seems to function just fine for me? Or do you mean to say whether there is a way for Wt to not send a request to the server and having some JS in the response that dictates how the content changes?

If that is what you are trying to do, I'm afraid this is not a correct use-case for implementStateless. As the documentation states:

When this slot is connected to an EventSignal (such as those exposed by WInteractWidget and WFormWidget), the Wt library may decide to cache the visual effect of this slot in JavaScript code at client-side: this effect will be learned automatically at the first invocation. This has no consequences for the normal event handling, since the slot implementation is still executed in response to any event notification. Therefore, it is merely an optimization of the latency for the visual effect, but it does not change the behaviour of the application.

You need to mark the function that would be handled by the EventSignal to the stateless slot, meaning the whole lambda that "parses" the WMouseEvent as well. However, the stateless slot does not take any function that takes arguments.

Additionally, this is mostly for visual effects (like hiding an item, changing its colour or background, ...) small HTML/CSS changes essentially. Here you are also change some HTML content itself.

You can for example do something like:

public:
  Container()
  {
    implementStateless(&Container::expand, &Container::shrink);

    auto btn1 = addNew<Wt::WPushButton>("Expand");
    btn1->clicked().connect(this, &Container::expand);

    auto btn2 = addNew<Wt::WPushButton>("Shrink");
    btn2->clicked().connect(this, &Container::shrink);
  }

private:
  void expand()
  {
    setWidth(Wt::WLength("200"));
    setHeight(Wt::WLength("200"));
  }

  void shrink()
  {
    setWidth(Wt::WLength("100"));
    setHeight(Wt::WLength("100"));
  }

I hope this helps!

Regards,
Matthias

    (1-1/1)