I've been having difficulty understanding how Knockout Observable Arrays work, more specifically replacing certain vales within them. I keep thinking I've got it right until further down the line when something else doesn't work correctly.
Due to the complexity of my viewmodel (Observable Arrays of Observable Arrays of Observables with subscriptions to update their respective arrays) I won't post the full extent of my actual issue, especially as there is clearly a fundamental misunderstanding here.
I've essentially got it narrowed down to 2 possibilities, examples below, where; groups = KO Array of observable objects/arrays and rightTargetPropertyName = KO array of obs strings
filter().groups()[0].rightTargetPropertyName([ko.observable("placeholder")])[0];
The above works but I feel like it will replace the whole array with a single value as the UI grows
filter().groups()[0].rightTargetPropertyName()[0]("placeholder");
This one above seems like it should be the correct way to change a single observable value in an observable array but the subscriptions/computed values aren't triggered when this code is run.
So in summary, which is the correct way to modify observable values in observable arrays? If the second method is correct (as I suspect) I can debug further.
Thanks in advance
Related
I have one observable array in my store that is deeply nested. Lets called the property people (which contains elements of class Person). Now the Person class has a property products which is an array of Product, a class which also has nesting through ShippingInformation and so on. When the app is loaded I get the people array with all nested data. Now upon any data update I receive the updated peoples array again from the server. A lot of the times the elements in the people array are the same, the only change being some ShippingInformation.
Now how should I update the existing observable array people? I do not want to reassign it because often times the direct Person elements are the same. It is only some nested information on one Person that has changed. Is there a way that I can sync the two arrays without changing the ref on the array with a reassign so that I avoid major rerenders in react? Can mobx help me here or are there any other lib I can use to help me update without triggering unnecessary rerenders? If not, are these rerenders that bad, performance wise, I guess react must go through the diffing process at least
I have a performance question for Angular 1.x. Is there any performance benefits to use function expressions vs filters to get values based on keys? Let me explain with examples.
I currently have a complex angular application with a number of filters used to get values based of an objects key. I have a lot of key/ID references in my data so I use a filter to get field values based of the key.
E.g. {{ ID123 | getField:'object':'field'}}
The custom filter would then do a async call (to DB) to get the object name I specify based on the key (ID123) and return the field I specify (instead of just showing the key).
I'm currently in the process of doing some performance clean up and I've read a lot about avoiding filters since they are a hit on performance. One thing I'm doing is using one-time bindings {{::ID123 | getField:'object':'field'}} but in some scenarios I can't do that (since I need the value to update).
I was then looking at function expressions instead of custom filters, e.g. {{getField(ID123,'object','field')}}. But I'm not sure if it would get any performance benefts.
You can see my plunker example where I compare the two.
https://plnkr.co/edit/hlL2LSOGjq5HsImUyqyu?p=preview
Would there be any performance benefits? Also is there a way to test or benchmark the difference between the two?
Thanks
Short answer: filter is better provided it's idempotent (i.e. the same input always returns the same output) and the input is not an object.
Long answer:
If you use a function, it will be called in each digest cycle, because Angular has to check that the output is the same. That means it will be called several times before the displayed data 'settles'.
If you use a filter and the input is not an object, it will be executed only if the input has changed, since Angular assumes that filters are idempotent unless their $stateful property is set to true.
Objects are an exception to this, because it's costly to check if deep properties of objects are changed, so Angular executes the filter in every digest cycle, making it the same as a function.
Be careful with creating custom filters that are not idempotent, Angular will assume they are and not update the displayed data properly. If you must create one, mark them as $stateful.
Sources
This question is related and pointed me in the right direction:
Custom filter vs filter function in controller performance comparison
And this is the Angular documentation for filters (sections "When filters are executed" and "Stateful filters"):
https://docs.angularjs.org/guide/filter
One of the milestones in learning JS and Angular, is learning that two way data binding with primitives is tricky. If you want to make sure that databinding works, you should always pack it into an object - that is what I was told by some seniors in my company. My question is - why is that happening? What is exactly going on that makes databinding with primitives so compliated in JS?
I found out that Javascript passes objects by reverence, and primitives by value. So what exactly happens in for example AngularJS Controller, that enables us to bind primitive in ngModel?
EDIT
Any articles, pointers are more than welcome!
Here is good post or post.
In short:
"Primitive values (e.g. numbers, strings) are immutable in JavaScript. So whenever a change is made to them it means we are actually throwing away the previous instance and using a different one."
I am using JavaScript's Three.js, and I came to a point where I have an array of complicated elements* that I wish to render only some of those each render iteration.
Up until now I was using a global array for this purpose, but I think it may not be very efficient, using such a "big" variable as global therefore I am looking for another way of doing so.
I have only came to the thought of calling render(myArray) each iteration, but I do not want to pass this big array each iteration as well...
*My basic "complicated" array elements are created by the same constructor, which contains ~10 properties (scalars and meshes) and ~10 methods.
There's ~200 elements in this array.
Needless to say that I am very new to JS and Three.js, therefore I may ask a wrong question and will be glad to receive a correction if needed. Thanks.
For some reordering code I call splice on an array of Breeze entities. Generally this works fine, but on removing an entity using splice from the array, its navigation properties are set to null. After adding the same entity back into the same array on a different position, navigation property seems to be restored, but the entityState has already changed to modified.
The responsible code seems to be this call.
Is there a way to move an entity in an array of entities to a different position without having the entityState to be changed?
As responded by in a GitHub issue: Workaround is to use a temporary standard array instead of an observable array, process the arrays using splice in the temporary array and write them back to the observable array.