I am trying to observe an array in typescript 2.3.3, and I am using rxjs. my goal is to run a method every time an array is changed. Let me clarify with some code before I can tell you what I've tried.
rows: any[] = []
rows.push('test1') //fired event now
rows.splice(0,1) //fire event now
rows = [] // fire event now
Rx.Observable.from(this.rows)
Rx.Observable.of(this.rows)
Rx.Observable
I ended up creating an ObservableArray
class that will fire events and has a subscribe method in it. I will post this here just so that people having this issue will be able to use it too.
export class ObservableArray {
onArrayChanges: EventEmitter<any> = new EventEmitter();
onRemovedItem: EventEmitter<any> = new EventEmitter();
onAddedItem: EventEmitter<any> = new EventEmitter();
onComponentChanges: EventEmitter<any> = new EventEmitter();
length(): number {
return this.collection.length;
}
private collectionCount: number = 0;
private isStartup:boolean=true;
constructor(public array: any[]) {
this.onComponentChanges.subscribe(data => {
this.array = data;
this.onChanges();
});
}
private collection: any[] = [];
private subscriptions: any[] = [];
onChanges(): void {
let collectionModel = new CollectionModel();
collectionModel.originalValue = this.collection;
collectionModel.newValue = (this.isStartup)?this.collection:this.array;
collectionModel.isRecordAdded = this.isAddedItem();
collectionModel.isRecordRemoved = this.isRemovedItem();
this.collectionCount = this.collection.length;
if (this.isAddedItem()) {
this.onAddedItem.emit(collectionModel);
}
if (this.isRemovedItem()) {
this.onRemovedItem.emit(collectionModel);
}
if (this.isChanged()) {
this.updateCollection();
this.onArrayChanges.emit(collectionModel);
this.publish(collectionModel);
this.isStartup = false;
}
}
private isChanged(): boolean {
let isChanged = false;
if (this.array) {
isChanged = this.array.length !== this.collectionCount;
}
return isChanged || this.isStartup;
}
private isAddedItem(): boolean {
let isAddedItem = false;
if (this.array) {
isAddedItem =this.array.length > this.collectionCount;
}
return isAddedItem;
}
private isRemovedItem(): boolean {
let isRemoved = false;
if (this.array) {
isRemoved = this.array.length < this.collectionCount;
}
return isRemoved;
}
private updateCollection() {
this.collection = this.array;
}
private publish(payload?: any) {
for (let callback of this.subscriptions) {
callback(payload);
}
}
subscribe(callback: (payload?: any) => void) {
this.subscriptions.push(callback);
}
}
export class CollectionModel {
originalValue: any[] = [];
newValue: any[] = [];
isRecordAdded: boolean = false;
isRecordRemoved: boolean = false;
}
If you really wanted you could make this and ObservableArray<T>
however in my case i didn't think that i needed to do this.
I hope this helps others. :)