10

I have a single page application I'm working on in which a variable x can change for many reasons. I want the value displayed in the DOM (the div below) to at all times match the value of the javascript variable.

I understand frameworks like angular are good for this, but I'm looking for a more lightweight and simple solution. I'm already using JQuery and underscore.js on the page if that helps.

 <script>
    var x = 100
    </script>

    <div id="value_display">100</div>

Ideally I'd like something where I just need to provide the variable and the element as arguments. For example:

bind(x,'#value_display')
corycorycory
  • 1,026
  • 1
  • 16
  • 34
  • There is no super simple solution for this.. you could take a look here: http://stackoverflow.com/questions/1759987/listening-for-variable-changes-in-javascript-or-jquery or maybe try some lightweight framework like: https://vuejs.org/guide/ – Philipp Dahse Aug 26 '16 at 14:25
  • If you insist on performing updates to the data via simple assignment, you could use [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to listen for changes, however [it's not supported in a number of browsers](http://caniuse.com/#feat=proxy). Otherwise, consider assigning data via function calls. – zzzzBov Sep 01 '16 at 20:49

2 Answers2

3

My proposition is to create special Class to encapsulate those variables. It is very lightweight solution no intervals and value watching.

var ViewModel=function(selector){

  this.dom=document.querySelector(selector);//here DOM element
  this.value=null;

};

//method sets value
ViewModel.prototype.set=function(value){

   if (value===this.value)
   return;//the same value

   this.value=value;//new value


   this.dom.innerText=this.value; //most important changing in DOM

};

//method gets value
ViewModel.prototype.get=function(){

  return this.value;

};

Usage:

var x=new ViewModel("#selector");

x.set(100);

Check example in jsFiddle -https://jsfiddle.net/maciejsikora/wrd14kwk/

Maciej Sikora
  • 16,060
  • 3
  • 38
  • 38
1

You ask for a simple implementation (no large frameworks) of an observer pattern, ideally just by providing the variable name and the element's id as arguments.

What you ask for is possible, if we define the bind() function to repeatedly poll x to see if it has changed. Note that bind then has to be called like this:

bind('x','value_display');

A working example:

var x = 100;

function bind(varName, elementId){
  var lastValue;
  function check(){
    if(lastValue !== window[varName]){
      lastValue = window[varName];
      document.getElementById(elementId).innerHTML = lastValue; 
    }
  }
  //poll for changes every 50 milliseconds
  setInterval(check, 50); 
}

//bind x to value_display

bind('x','value_display');

//test function by changing x every 100th millisecond

setInterval(function(){
    x = +new Date;
  },
  100
);
<div id="value_display"></div>

Personally, I would prefer a lightweight publisher/subscriber module over using a polling function, but that would require assignment to the variable x to be controlled by a function/method (some kind of setter). If you research (google) observer pattern or pub/sub pattern, you will find easy ways of implementing this in much less code than a large framework—but probably not as lightweight as the polling approach.

Tomas Langkaas
  • 3,795
  • 1
  • 14
  • 29
  • I must disagree with your last statement, "not as lightweight as the polling approach", and what it suggests -- that polling is somehow lightweight. Dozens, hundreds, thousands, or potentially millions of useless function calls, if the value does not change, in my opinion does not constitute lightweight. But you are correct, "some kind of setter" can be used instead. Please consider the following https://repl.it/@dexygen/DemystifyingOneWayBinding which is merely a first attempt but works. The object constructor may seem unnecessary but it is something I'm using in my own framework – Dexygen Nov 19 '17 at 15:30