Guangyu
Guangyu

Reputation: 25

How to update webpage after creation in wt(c++)

I am new to wt and just started adding web interface to a lagacy c++ program. The example hello_world works fine.

However the examples given are all about create a webpage and the page can react to events from webpage (i.e. a button, a tick box), I want to modify the webpage AFTER starting a session. More like HMI responding to changes of data, instead of buttons from webpake.

It should be doable, as the wt document says: The actual request handling and rendering is abstracted, with as benefit that a full page rendering model (plain HTML) or incremental updates (Ajax/WebSockets) can be used depending on configuration and browser properties.

I add an "updateText" method to hello_world:

class HelloApplication : public WApplication 
{
public:
    HelloApplication(const WEnvironment& env);
    void updateText(std::string value); // I add this and rest are from helloworld
private:
    WLineEdit *nameEdit_;
    WText *greeting_;
    void greet();
};

Here is the implementation:

HelloApplication::HelloApplication(const WEnvironment& env)
: WApplication(env) 
{
    setTitle("Trading Platform Status");                               // application title

    root()->addWidget(new WText("Starting... "));  // show some text
    nameEdit_ = new WLineEdit(root());                     // allow text input
    nameEdit_->setFocus();                                 // give focus

    WPushButton *button
        = new WPushButton("Greet me.", root());              // create a button
    button->setMargin(5, Left);                            // add 5 pixels margin

    root()->addWidget(new WBreak());                       // insert a line break

    greeting_ = new WText(root());                         // empty text


    /* Connect signals with slots - simple Wt-way*/
    button->clicked().connect(this, &HelloApplication::greet);

    /* using an arbitrary function object (binding values with boost::bind())*/
    nameEdit_->enterPressed().connect
        (boost::bind(&HelloApplication::greet, this))
}

void HelloApplication::greet() {
    /*Update the text, using text input into the nameEdit_ field.*/
    greeting_->setText("Hello there, " + nameEdit_->text());
}

Greet() is from original helloworld, and I add the updateText method.

void HelloApplication::updateText(std::string value)
{
    /*
    * Update the text, using text input into the nameEdit_ field.
    */
    greeting_->setText(value);
}

WApplication *createApplication(const WEnvironment& env)
{
    /*
    * You could read information from the environment to decide whether
    * the user has permission to start a new application
    */
    return new HelloApplication(env);
}

In the main I start the host in a seperate thread.

the manual has pointed out:

At all times, the WApplication instance is accessible using the static method WApplication::instance(), and is useful to inspect startup arguments and settings (using WApplication::environment()), to set or change the application title (WApplication::setTitle()), to specify a locale (WApplication::setLocale()) for rendering, and many other application-wide settings. In a multi-threaded environment, access to this instance is implemented using thread local storage.

int main(int argc, char* argv[])
{
    //start in new thread or it blocks the following work
    thread website_thread(&WRun,argc, argv, &createApplication);
    //balabalabala some work
    ((HelloApplication*)WApplication::instance())->updateText("Finished");
    //balabala more work
    return 0
}

The updateText fails, because "this" is null. Obviously it is not the correct way to do the task. Any suggestions?

Upvotes: 1

Views: 1039

Answers (1)

user52875
user52875

Reputation: 3058

You'll need to:

  • maintain a list of sessions you want to signal, e.g. by putting the WApplication objects in a global list when a WApplication is constructed, and removing it in the destructor. You may also do this more fine-grained.
  • enable server push for each application that can be updated by a server-side event (simply call WApplication::enableUpdates())
  • ensure somehow that the widget tree is locked when you modify it server-side, either by grabbing the WApplication::updateLock, or by using WServer::post() to post the execution of a function in the context of a session
  • call WApplication::triggerUpdate() when the widget tree was modified, so that the changes will be pushed to the client

Additionally, you may want to enable websockets support in the wt_config.xml file.

The simplechat example demonstrates pretty much all of this.

WApplication::instance uses thread-local storage, which is set by Wt when a thread is allocated to handle a session object, so it is normal that it returns null in your main thread.

Upvotes: 1

Related Questions