You need to enable JavaScript to run this website.

(See messages in the debug console.)

Subtleties when using dependencies on elements of an observable array

Consider a simple html-block generated using forEach binding:

← must display 0 1 2 3 9 10

We can alter an array by (i) adding/removing its elements and (ii) changing the value of its elements. The first type of alteration works ok when we declare that a variable depends on the observable array; but this is will not work if we just change the value of its elements.

Changing the second element of an observable array

(Dependent on obsArray) firstElement= does not change when we type command obsArray()[0].vv(11) in the console.

(Dependent on obsArray()[1].vv) secondElement= equals to its original value -123, which is updated after command obsArray()[1].vv(11).

It is bad to set explicit dependences on elements of an observable array because usually we want to be able to alter the array's width without limitations.

Let us try to calculate the sum of elements totalSum= ← it produces the correct value (25), taking into account insertion of a new element into the observable array.

But what if we change the second array element by executing obsArray()[1].vv(11) in the debug console?

Then

We could try to use totalSum.DB.update(), which gives the correct updated value (35), but the corresponding DOM is not updated

The solution

We define
betterSum=new DB.observable([DB.everyElement(obsArray,'vv')],{'type':'int',compute:()=>obsArray().map(x=>x.vv()).reduce((x,y)=>x+y,0)});

Then we ensure that the DOM bound to betterSum (sum of all elements) gets properly updated when the dynamic array obsArray is changed. In fact, the command
obsArray()[0].vv(100)
correctly updates the aforementioned DOM.

Finally let us make sure that there are no problems with observables depending on betterSum:
betterSum times 10 is equal to ;
and if we then divide it by 2 we get

Changing the values of elements of an array

Removing elements from obsArray

03/23 I've noticed that command obsArray.drop(5) does not alter the value of betterSum.

May be later I will invent a more lelgant way to solve this problem, but for now I will explicitly mention the dependence on the array itself:

betterSum2=new DB.observable([obsArray,DB.everyElement(obsArray,'vv')],{'type':'int',compute:()=>obsArray().map(x=>x.vv()).reduce((x,y)=>x+y,0)})

Result:

Inserting new elements into obsArray

2022-05-28 There is a similar problem with inserting numerous new elements into obsArray. If we right something like

allDays(logData.map(thisDay=>new logDay(thisDay))) что соответствует в данном примере

obsArray([new OAelement(1),new OAelement(2),new OAelement(3)])

noone will know that the value of these new array elements will affect betterSum!

Conclusion: we add new elements to an observable array using only push method! This is not optimal because on every push call all dependents will be recalculated, and sometimes this may take a long time, especially for nested forEach bindings. As of 2022-07-01 I have only a non-elegant solution to this problem: specify minimal time interval (maximal frequency) at which an observable will be recalculated. To do that, specify dT parameter – time (period) in miliseconds.