Flow architecture with polymer elements

Flow architecture is trending in web applications as well as polymer elements.

Is there any example of building a polymer application that uses flux architecture?

+3


source to share


2 answers


I was thinking about using a Flux template with (polymer) web components. So far, I've come up with three possible solutions, all different from your path, so here they are:

DISCLAIMER I am using the Reflux library, not Facebook.


Actions and Stores as Elements

My first attempt was to create a Flux template into elements so that any view that requires store access and invokes actions will just import them.

<dom-module id="a-view">
  <template>
    <my-actions id="actions"></my-actions>
    <my-store model="{{model}}"></my-store>
    <span>{{model.property}}</span>
    <button on-click="executeAction"></button>
  </template>
</dom-module>

<script>
  Polymer({
    is: 'a-view',
    executeAction: function() {
      this.$.actions.doSomething({});
    }
  });
</script>

      

<my-actions>

and <my-store>

just encapsulate actions and stores. There are some disadvantages to this method. First, potentially numerous non-visual elements are created, which can negatively impact performance. Also the creation of these elements can be tricky if they are to be Polymer elements because they require a static state. For a complete example see this repo


Flux without flow



I recently figured out what web components are again. With WC, your main API is the browser, namely elements, attributes and events. And Flux is essentially an event driven data stream. So why not use Custom Events to communicate between custom elements? Here is an excerpt from my rogue yesterday

<template is="dom-bind">
  <a-view clicks="[[clicks]]" id="one"></a-view>
  <a-view clicks="[[clicks]]" id="two"></a-view>
  <a-view clicks="[[clicks]]" id="three"></a-view>
  <a-store click-history="{{clicks}}"></a-store>
</template>

<script>
    Polymer({ 
      is: 'a-view',
      properties: { clicks: Object }, 
      fireClick: function() {
        // invoking action is simply firing an event
        this.fire('a-view-click', {});
      }
    });

    Polymer({
      is: 'a-store',
      attached: function(){
        document.addEventListener('a-view-click', function(ev) {
          // do work and update store here
        }.bind(this));
      }
    });
</script>

      

This is good because it is not limited to Polymer in any way. Custom elements can be created using native API or another library and simply communicate with the browser acting as the dispatcher. Granted, this doesn't give you sync options out of the box, but it's a simple and clean way without any clutter.

As you will see on Plunker, keep the data binding updates. Another possibility is to fire another event, although I'm not sure which would be better or when


Using Polymer Behavior

Finally, I got an idea that improves the first time around by replacing custom action / store elements with behavior. No code yet, but here's a sketch:

var MyActionsBehaviour = PolymerFlux.createActions({ /*...*/ });
var MyStore = PolymerFlux.createStore({ /*...*/ });

Polymer({
  is: 'a-view',
  behaviours: [ MyActionsBehaviour, MyStore ],
  onClick: function() {
    this.behaviourAction.invoke({});
  }
}});

Polymer({
  is: 'a-store',
  behaviours: [ MyActionsBehaviour, MyStore ],
  attached: function() {
    this.behaviourAction.listen(function() {
      // 1. do work
      // 2. update views
    });
  }
}});

      

I forgot that part of the update has been updated. This will most likely happen by signaling an event, but another possibility will trigger another action (Reflux has a good concept of nested actions ). Also I leave PolymerFlux.createActions

it PolymerFlux.createStore

to your imagination;). The exact internals will depend on the flow implementation you choose.

+4


source


I tried to use flux architecture in a polymer application.

Here is the main-app.html:

<link rel="import" href="./bower_components/polymer/polymer.html">
<link rel="import" href="store-cart.html">
<link rel="import" href="store-cart2.html">
<link rel="import" href="view-cart.html">
<link rel="import" href="view-additems.html">


<dom-module id="main-app">
    <style>
    </style>
    <template>
        <!-- Stores-->
        <store-cart id="cart1" action=[[action]]></store-cart>
        <store-cart2 id="cart2" action=[[action]]></store-cart2>

        <!--Views and other stuff-->
        <view-additems cart="cart1"></view-additems>
        <view-additems cart="cart2" add="3"></view-additems>
        <view-cart update="[[updateView]]"></view-cart>

    </template>
</dom-module>
<script>
    Polymer({
        is: 'main-app',
        properties: {
            action: {
                type: Object,
                value: {}
            },
            updateView: {
                value: ""
            }

        },
        listeners: { //dispatcher event -> action
            'viewAction': 'viewAction', // Action from view to be dispatched to the store/stores
            'storeUpdated': 'storeUpdated' // storeUpdated-event from store to views
        },
        viewAction: function(e) {
            action = e.detail;
            switch (action.type) {
                // "CombineCarts" is needed because both of the stores needs to be updated in order
                case 'combineCarts':
                    this.$.cart1.addItems(this.$.cart2.nbItems);
                    this.$.cart1.updateViews();
                    this.$.cart2.emptyCart();
                    this.$.cart2.updateViews();
                    break;
                // default action when store/stores can be updated independently
                default:
                    this.action = action;
            }
        },
        storeUpdated: function(e) {
            this.updateView = e.detail;
        }
    });
</script>

      

Entire example: https://github.com/grohjy/polymer_flux_example



The basic idea is that the "dispatcher" is located at the very top level of the polymer application, and its role is to route messages from stores to views and vice versa. Each store and view determines which messages they respond to and how. The manager also shows an example of updating multiple stores in the required order.

Stores and some of them are also located at the very top level of the application. A view can also have child views. The store shouldn't have any visual dom elements.

Please feel free to comment and share ideas.

+2


source







All Articles