Tag Archives: responsive

Reactive Extensions Example for the Browser

Introduction

This is the next post in the reactive examples series. Previous articles focused on building a MVVM-style ReactiveUI-based Windows application in C# with the help of Reactive Extensions. The example application had some simple word counting logic and a background ticker, demonstrating an implementation without using error-prone callbacks or explicit threading. This article will try to re-create the same application for the web browser using Vue.js, Bootstrap-Vue and vue-rx.

The result looks like this:

an input form, counting words and ticking (Vue-Rx reactive example by d-led)

In the Meanwhile

The Actor Model

After several attempts to implement the example with RxJavaFX, I gave up on RxJava for a UI, and focused on another approach to writing concurrent reactive software: the Actor Model. This lead me to converge on two* Actor Model languages, Pony and Elixir/Erlang, and later, on one framework: Vlingo (thanks to a serendipitous meeting and a kind invitation to an IDDD workshop by Vaughn Vernon).

The venture resulted in several presentations, including one at the Lightweight Java User Group München Meetup. In the preparation for the meetup, I have demonstrated how Reactive Extensions can enhance actor model code with time-based operators, and how the transition between the paradigms is achieved (see vlingo_experiments/batching_with_rx). 

As late Pieter Hintjens said and wrote, alluding to Conway’s Law, “read about the Actor model, and become a message-driven, zero shared state Actor”. The 1973 paper by Carl Hewitt and others on the Actor Model was published in proceedings of an artificial intelligence conference of the time. There are good indications that this concurrency model is a good fit for a computational model of the brain (see 1, 2).

All this deserves another series of blog posts.

In the Browser

The Actor Model is coming to the browser too: it is a natural fit for the modern web. See the talk: Architecting Web Apps – Lights, Camera, Action! (Chrome Dev Summit 2018) and the related Github project: PolymerLabs/actor-boilerplate. It has been seen in other places too, such as in the emerging framework Tarant.

Alas, I can’t show an actor model example in the browser, yet. Thus, back to Reactive Extensions!

How to get to vue-rx?

It seems, in the world of web front-end programming, there are numerous diverging paths, all of which, in the end, converge on downloading half the internet of little script files in various dialects of JavaScript. But don’t despair, commit often and small. I am not native to the JS world, and previous attempts to re-create the example in the browser failed miserably.

Vue.cli

The path chosen here is to start with a boilerplate generated with Vue CLI 3

vue create vue-rx-example

Dependencies

Install the dependencies via npm install

  • vue – the sensible MVVM library for the browser
  • moment – to format time
  • rxjs, rxjs-compat, vue-rx – the Rx libraries required in this context
  • bootstrap-vue – a responsive web page design pattern

The View Component

an input form, counting words and ticking

Replacing the generated view boilerplate, the following remains:

<template>
  <b-form>
    <b-form-group label="Background ticker">
      <b-form-input readonly type="text" v-model="ticker" />
    </b-form-group>

    <b-form-group label="Word count">
      <b-form-input readonly type="text" v-model="countWords" />
    </b-form-group>

    <b-form-group label="Enter some text">
      <b-form-textarea v-model="text" style="min-height: 200px" />
    </b-form-group>
  </b-form>
</template>

which is a simple form with two read-only text fields, and one input text area, all declaratively bound to the viewmodel via the v-model directive

The ViewModel & Vue Extensions

The dependencies must be registered with Vue in the <script /> tag in order for them to work together as intended (excluding some CSS/other boilerplate):

import Vue from "vue";
import VueRx from "vue-rx";
import Rx from "rxjs/Rx";
import BootstrapVue from "bootstrap-vue";
Vue.use(BootstrapVue, VueRx, Rx);
// here comes the ViewModel

The following is all of the ViewModel with the explanations in the comments:

export default {
  name: "HelloWorld",
  data() {
    // input field is bound to this
    return {
      text: ""
    };
  },

  // rx-vue part
  subscriptions: function() {
    // watch the input data as an observable stream
    const countWords = this.$watchAsObservable("text")
      // update only if not typing for 1/2 s
      .debounceTime(500)
      .pluck("newValue")
      .startWith("")
      // count the words
      .map(val => {
        const s = val.trim();
        return s == "" ? 0 : s.split(/\s+/).length;
      });

    // tick the timestamp every second
    const ticker = Observable.interval(1000 /* ms */).map(_ =>
      new moment().format("H:mm:ss A")
    );

    return { countWords, ticker };
  }
};

which a Rx.Net developer might find familiar:

this.WhenAnyValue(x => x.TextInput)
    .Where(x => !string.IsNullOrWhiteSpace(x))
    .Select(x => x
        .Split()
        .Count(word => !string.IsNullOrWhiteSpace(word)))
    .ToProperty(this, vm => vm.WordCount, out _WordCount)
;

Observable
    .Interval(TimeSpan.FromSeconds(1))
    .Select(_ => DateTime.Now.ToLongTimeString());
    .ToProperty(this,
        ticker => ticker.BackgroundTicker,
        out _BackgroundTicker)
;

Conclusion

Reactive Extensions have proven to be a suitable paradigm for building reactive user interfaces, landing them on the Thoughtworks Radar into the Adopt ring. Rx implementations can be used in variety of technologies, as the Reactive Trader project has shown.

While the Actor Model shines on the server, reactive, message-driven technologies play well together, and, perhaps, soon it will be natural to structure applications as a mix of stream-based and actor-based components.

Source code: https://github.com/d-led/vue-rx-example
Demo: https://ledentsov.de/static/vue-rx-example

No Events: ReactiveUI Windows Forms MVVM-Style

Review

designed using http://viperneo.github.io/winforms-modernui/

This is the next post in the series, looking first at Reactive Extensions (RX) to simplify writing Windows Forms UI logic, then using a viewmodel shared between a WPF gui implementation and a rewritten WinForms version using ReactiveUI, stopping at a short article on testing the viewmodels.

passedtest

ReactiveUI News

ReactiveUI API has been quite volatile for the last year, and this series is in need of an update[0. See ReactiveUI Design Guidelines]. A CodeProject author gardner9032 published a nice teaser article, showing the ReactiveUI mechanism for writing simplified Viewmodel-View bindings [1. see article @CodeProject], which serves as primary trigger for this post.

There’s plenty of news and updated articles on Paul Betts’ log, providing a good resource for updates on the API. Phil Haack’s blog is also a superb resource for explanations and commentaries on the use of ReactiveUI in real-world applications.

The ReactiveUI project is quite active, as the community seems to have grokked the jist of it, while the list of supported platforms has become more than convincing.

Getting rid of events

The enabling feature of ReactiveUI is writing declarative UI glue code, and if the viewmodels are based on Reactive Extensions, then declarative C# style can be used throughout the project. The previous ReactiveUI Windows Forms examples converted an event sequence into an observable sequence of values. In this example, that will be accomplished conveniently by the ReactiveUI WinForms lbrary. The viewmodels also contained some imperative code. For this article, the viewmodels will not be reused from the previous articles, but written from scratch.

ViewModel

s. code

The viewmodel’s task is the same: something is ticking in the background, while words are counted in the input text asynchronously, and the calculation is throttled to 0.5 seconds. The viewmodel boilerplate is simplified using ReactiveUI.ReactiveObject.

Output (read-only) properties

The ReactiveUI-way of creating output properties is through ObservableAsPropertyHelper.

private readonly ObservableAsPropertyHelper<string> backgroundTicker;
public string BackgroundTicker
{
    get
    {
        return backgroundTicker.Value;
    }
    //...
}

The constructor of the viewmodel receives an IScheduler for scheduling on the correct thread, and an IObservable, which will be a stream of input from the view. Observe the ToProperty helper:

public MyViewModel(IScheduler scheduler, IObservable<string> input)
{
    Observable.Interval(TimeSpan.FromSeconds(1))
        .ObserveOn(scheduler)
        .Select(_ => DateTime.Now.ToLongTimeString())
        .ToProperty(this, x => x.BackgroundTicker, out backgroundTicker);
    //...
}

Word counting logic is implemented in a similar fashion by transforming the incoming stream of strings.

View

s. code

To remove yet more boilerplate code, WinForms Form specialization implements the ReactiveUI.IViewFor interface. This allows for largely simplified run-time and compile-time checked bindings, avoiding using strings for property names. The implementation is straightforward, and pays off once the views become more complex than this example:

IViewFor

public MyViewModel VM { get; private set; }

object IViewFor.ViewModel
{
    get { return VM; }
    set { VM = (MyViewModel)value; }
}

MyViewModel IViewFor<MyViewModel>.ViewModel
{
    get { return VM; }
    set { VM = value; }
}

Bindings

None of the controls in the designed WinForm have wired events or bindings set from the designer. The glue code is reduced to instantiating the viewmodel …

VM = new MyViewModel(
    new System.Reactive.Concurrency.ControlScheduler(this),
    this.WhenAnyValue(x => x.inputBox.Text)
);

… and declaring the bindings[2. The ReactiveUI WinForms implementation seems not to support fully read-only fields using default bindings yet, hence an empty setter in the viewmodel] [3. The scheduler is from Windows Forms helpers].

this.Bind(VM, x => x.BackgroundTicker, x => x.tickerBox.Text);
this.Bind(VM, x => x.WordCount, x => x.wordCountBox.Text);

Source

@github

The WPF + ReactiveUI Refactored Version of the Responsive UI Hello World

Overview

To recapitulate, the first article in the series used Reactive Extensions (Rx) directly in Windows Forms UI logic to implement a UI with a simulated background calculation, which delivered a timestamp each second. The rest of the application was an input text box, for which, when the user inputs the text, the word count is calculated asynchronously and posted into another read-only text box.

The second article introduced a WPF version of the same UI with a viewmodel that implements the INotifyPropertyChanged interface and supplies the ticker text and the word count as bindable properties. The text being input was delivered to the viewmodel via an event converted to an observable sequence, which was used to update the TextInput property of the viewmodel. The WordCount was updated from the setter of TextInput.

The third article recreated the WPF implementation in WinForms using the same viewmodel, which is shared between the two projects. The third UI implementation introduced throttling of the TextInput changes to 0.3 seconds so that the word count is updated only when the user pauses for at least a third of a second to take a look at the result.

The Refactored WPF Version

In this article, the WPF UI is further refactored, so that the concerns are separated further. These are organized as follows:

Create a sequence of some calculation results

These are timestamps in this case, implemented as an object, providing an IObservable<string> property Ticker:

public class BackgroundTicker
{
    public IObservable<string> Ticker
    {
        get
        {
            return Observable
                .Interval(TimeSpan.FromSeconds(1))
                .Select(_ => DateTime.Now.ToLongTimeString());
        }
    }
}

The observable sequence is active, delivering a value every second.

Count words in text asynchronously and provide another property calculated in the background

This viewmodel is finally implemented using ReactiveUI:

public class WordCounterModel : ReactiveObject

The word count and the input text are ReactiveUI boilerplate:

string _TextInput;
public string TextInput
{
    get { return _TextInput; }
    set { this.RaiseAndSetIfChanged(ref _TextInput, value); }
}

ObservableAsPropertyHelper<int> _WordCount;
public int WordCount
{
    get { return _WordCount.Value; }
}

The value sequence of the background ticker is injected at construction time using its observable member. The word count and the background ticker properties are implemented using an ObservableAsPropertyHelper.
The results of the background ticker are exposed via a property:

ObservableAsPropertyHelper<string> _BackgroundTicker;
public string BackgroundTicker
{
    get { return _BackgroundTicker.Value; }
}

the helper is initialized from the constructor-supplied observable:

someBackgroundTicker
    .ToProperty(this, ticker => ticker.BackgroundTicker, out _BackgroundTicker);

And finally, the word count logic is implemented as an output property, transforming the sequence of strings into a sequence of integers:

this.WhenAnyValue(x => x.TextInput)
    .Where(x => !string.IsNullOrWhiteSpace(x))
    .Select(x => x
        .Split()
        .Where(word => !string.IsNullOrWhiteSpace(word))
        .Count())
    .ToProperty(this, vm => vm.WordCount, out _WordCount);

The throttling can be removed from the viewmodel, as the WPF 4.5 has a Delay binding property, which can be used for the same purpose on the view side, freeing the viewmodel from that concern.

Provide a Graphical UI

Now let’s look at the view. The event subscription is gone and data binding is implemented in XAML declaratively. The DataContext of the main window is initialized with an instance of the viewmodel, which is initialized with an observable from an instance of a background ticker:

ViewModels.BackgroundTicker Ticker=new ViewModels.BackgroundTicker();
ViewModels.WordCounterModel VM = new ViewModels.WordCounterModel(Ticker.Ticker);
DataContext = VM;

This instantiation can be definitely made in XAML as well, nullifying the amount of C# code for the view, as for example in the following article.

The background ticker and the word count are now bound one-way and marked asynchronous.

<TextBox ... Text="{Binding BackgroundTicker,IsAsync=True,Mode=OneWay}"></TextBox>
<TextBox ... Text="{Binding WordCount,IsAsync=True,Mode=OneWay}"></TextBox>

And finally, the binding of the input text is configured in XAML to be throttled to 300 milliseconds and bind on PropertyChanged events of the Text property of the text box:

<TextBox ... Text="{Binding TextInput, UpdateSourceTrigger=PropertyChanged, Delay=300}"></TextBox>

Source Code

https://github.com/d-led/reactiveexamples