Diff check with iterable differs slows down datatable, complicates our code and causes issues like 2405. Always use setter instead which is the immutable mode actually, this means we'll remove immutable property as well and document that when data is changed always a new array should be created instead of changing an existing array when array is used for value.
When wanting to delete a Object I need to create a new Array and add slices of the old one? like:
removePageFromListing(selectedPage: Page) {
const index = this.pages.indexOf(selectedPage);
if (index > -1 ) {
this.pages = [ ...this.pages.slice(0, index), ...this.pages.slice(index + 1, this.pages.length ) ];
}
}
Or is there a more elegant way?
I just want to say that this change alone has caused us to abandon PrimeNG and cancel our plans for PrimeNG premium services (we're a mid sized software company in the states).
You can't make a framework for business/enterprise and then change things like this with no warning, proper documentation, and debate in your community.
We built a huge chunk of our app in the 2.* versions of PrimeNG and have a huge amount of code that relies on the previous method of change detection. Then this change is made in an RC release with a tiny side note and our entire application breaks when we upgrade.
We can't have people deciding to make major BREAKING changes frequently based off their own personal preferences. We'll likely fork the repo for now until we can fully replace this suite with something more appropriate.
I totally understand but we still think the change is necessary and vital for performance so that is why we applied it between major versions 2->4.
As of PrimeNG 4.0 there are no breaking changes planned ahead as the library api is stable.
I understand the change but it has a big impact on small tables (a few lines) where the previous behaviour was more than adequate performance wise...
There are several cases where I cannot reassign the array the table is iterating over. For example, we use reactive forms with datatables, and I cannot modify angular's FormGroup controls. This means I have to write a large workaround involving manually caching the FormGroup's control array and I have to keep it in sync. Very annoying change, wish there was an alternative.
I agree with @leetharris, a change like this should have been debated by the community, or offered as an alternative module (using the same component selector), allowing the user to import the preferred implementation (.. at least until an agreed upon solution was in place).
```javascript
import {DataTableModule,SharedModule} from 'primeng/primeng';
````
or
```javascript
import {DataTableModuleImmutable,SharedModule} from 'primeng/primeng';
````
I lost several hours of work trying to understand why my table was not updating automatically.
The change discouraged me a lot, since I use the Angular because it is also the result of leaving everything dynamic ...
At least create a function to update the table would be a contour ...
@cagataycivici Any reason why this wasn't a separated component? ImmutableDataTable for lots of data without lazy loading and DataTable for the rest.
We currently have an hack in place before we change all occurrences of splice, push, etc... In our custom generic primeNg module, we added:
export class PrimengModule { // Generic PrimeNg Module in-which we import/export all PrimeNG modules.
constructor() {
Object.defineProperty(DataTable.prototype, 'value', {
set: function (v) {
this._value = v;
this.handleDataChange();
}
});
}
}
That way we kept the same reference to our array; not sure if this breaks other stuff. At least our app is in a workable state...
@cagataycivici I did not get it right, did you change it directly in the original component?
I appreciate your answer ..
Instead of a separate component, what we can try is add an attribute like immutable (default true), if not we need to reintroduce ngDoCheck although this makes the codebase complex. Problem is Angular does not call setter if reference does not change and ngDoCheck is slow, we don't need to know what has changed in array, need to know if data has changed.
Update: ngDoCheck is back but you need to set [immutable]="false". From the new docs of 4.1.RC3;
DataTable either uses setter based checking or ngDoCheck to realize if the underlying data has changed to update the UI. This is configured using the immutable
property, when enabled (default) setter based detection is utilized so your data changes such as adding or removing a record
should always create a new array reference instead of manipulating an existing array as Angular does not trigger setters if the reference does not change.
For example, use slice instead of splice when removing an item or use spread operator instead of push method when adding an item. On the other hand, setting immutable property to false removes
this restriction by using ngDoCheck with IterableDiffers to listen changes without the need to create a new reference of data. Setter based method is faster however
both methods can be used depending on your preference. Note that immutable property also defines how DataTable treats the data, for example
when immutable is enabled sorting does not mutate the original data but creates a new array of sorted data.
@cagataycivici Thank you! This is a perfect compromise.
Awesome support @cagataycivici ! Thanks for this !
I'm in primeng version 4.3.0 and nothing is working for me to have DataTable and DataGrid automatically refresh when modifying a value in the array. Did anything change again? I have tried both adding in and leaving out [immutable]="false". The data is being updated because I do see the change but only when I do a refresh of the page via browser refresh. Say my table and grid are bound to an array called data
, and for now, all I care about is seeing the first entry change. I've tried:
this.data[0].status = newStatus;
this.data.slice();
and
let item = _.cloneDeep(this.data[0]);
item.status = newStatus;
let tempData = this.data;
tempData[0] = item;
this.data = [...tempData];
and
let item = this.cloneItem(this.data[0]);
item.status = newStatus;
let tempData = this.data;
tempData[0] = item;
this.data = [...tempData];
cloneItem: (item: Item) => Item = (item: Item) => {
const newItem = new Item(0, '', 0);
for (const prop in item) {
if (item.hasOwnProperty){
newItem[prop] = item[prop];
}
}
return newItem;
}
among many others
Most helpful comment
I just want to say that this change alone has caused us to abandon PrimeNG and cancel our plans for PrimeNG premium services (we're a mid sized software company in the states).
You can't make a framework for business/enterprise and then change things like this with no warning, proper documentation, and debate in your community.
We built a huge chunk of our app in the 2.* versions of PrimeNG and have a huge amount of code that relies on the previous method of change detection. Then this change is made in an RC release with a tiny side note and our entire application breaks when we upgrade.
We can't have people deciding to make major BREAKING changes frequently based off their own personal preferences. We'll likely fork the repo for now until we can fully replace this suite with something more appropriate.