forio Toggle navigation

How To: Call a Model Operation Each Time a Model Variable Changes

This example steps through how to use Flow.js to have a model operation called after every time a particular model variable changes.

This model variable may be one that end users of your project can change directly (for example, through an <input> element). Or, it may be one that changes indirectly (for example, as a result of another operation). Either way, you want to call an operation each time the model variable changes.

What You Need

Solution Outline

  1. Bind your model variable to an input element.
  2. Use the Flow.js variables channel to subscribe to changes for this variable.
  3. In the callback function for the subscription, call the operation.
  4. View the complete example.

Solution Implementation

  1. Bind your model variable to an input element.

    You can bind variables from your project's model to your project's user interface by setting the data-f-bind attribute of any HTML element. For example:

     <div>Enter this year's sales: <input data-f-bind="Sales"></input></div>
    

    More information: Flow.js Variables and Attributes; Binding: data-f-bind.

  2. Use the Flow.js variables channel to subscribe to changes for this variable.

    Flow.js provides a channel between the variables and operations in your model and the HTML elements in your interface.

    In general, you simply reference model variables directly within HTML elements, and these values automatically update as the model changes; Flow.js takes care of all of the details.

    However, you also can work directly with the channels yourself, which is what we want to do in this case: we want to listen for any changes being made to a particular model variable. This is called subscribing.

    You can do it in the JavaScript on your HTML page:

     <script>
    
         Flow.initialize();
         Flow.channel.variables.subscribe('Sales');
    
     </script>
    

    More information: Flow.js Variables Channel.

  3. In the callback function for the subscription, call the operation.

    The variables channel subscribe() function also takes a callback function as a parameter. This callback function is called each time the value of the variable being subscribed to changes.

    To call a model operation each time a variable changes, call the operation as part of this callback:

     <script>
    
         Flow.initialize();
         Flow.channel.variables.subscribe('Sales', 
             function() {
                 Flow.channel.run.do('updateProfits');
             });
    
     </script>
    

    More information: Flow.js Variables Channel, Epicenter.js Run Service.

  4. View the complete example. Here's the complete code:

     <html>
     <head>
         <script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
         <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
         <script src="//forio.com/tools/js-libs/2.3.0/epicenter.min.js"></script>
         <script src="//forio.com/tools/js-libs/flow/0.11.0/flow.js"></script>
     </head>
    
     <body data-f-model="myModel.py">
    
         <div>Enter this year's sales: <input data-f-bind="Sales"></input></div>
    
         <script>
    
             Flow.initialize();
             Flow.channel.variables.subscribe('Sales', 
                 function() {
                     Flow.channel.run.do('updateProfits');
                 });
    
         </script>
    
     </body>
     </html>
    

Variations.

There are a couple of variations on this that may also be useful, depending on how your interface and model are structured:

  • You can subscribe to multiple variables at once. Use an array with the variable names: Flow.channel.variables.subscribe(['Sales', 'Costs']).
  • You can optionally pass additional options in a third argument to the subscribe() call. In particular, if you are subscribing to multiple variables, the default behavior is that the callback function is called once for each variable to which you subscribe. However, you can pass in a batch option so that the callback function is only called once, no matter how many variables you are subscribing to: Flow.channel.variables.subscribe(['Sales', 'Costs'], function() {...}, { batch: true });.
  • If your model operation takes arguments, you can pass in the arguments as an array of parameters: Flow.channel.run.do({name: 'updateProfits', params: [true, 2017]});. The Run Service documentation has more details. (The run in channel.run.do is a Run Service object that's part of this instance of Flow.)

Related Examples.

  • If you want to update a graph or chart when your model variable changes, rather than call a model operation, see Flow.js and Graphing for another example of what you can do inside the subscribe() callback.

  • If you want to update a UI element when a model operation is called, you can use a similar pattern to subscribe to the Flow.js operations channel instead of the variables channel. See How To: Update a UI Element Each Time a Model Operation is Called.

  • For information on handling other common uses cases involving binding UI elements to model variables or model operations, see the Flow.js working with variables and working with operations pages.