Making an object iterable?


#1

What is required to make a custom collection object ie

https://github.com/trevnorris/cbuffer

iterable in a repeat.for ?

Looping on the internal array of that object does not seem to work and if I add a property to get the data as an array getRecentData constantly gets called. toArray must causing the function to constantly recurse.

get getRecentData() {
    return this.recent_data.toArray();
}

#2

You have to create a value converter for that:


#3

I originally tried that.

I have a simple converter

export class MeterTypeSelectorValueConverter {
    toView(obj) {
        return obj.toArray();
    }
}

The template is

<ul>
            <li repeat.for="item of recent_data | meterTypeSelector">
                ${item}
            </li>
</ul>

However, when I update recent_data in a timer. Ie
this.recent_data.push(“HELLO”);
nothing updates


#4

I guess you’d have to update your definition in the converter:

export class MeterTypeSelectorValueConverter {
toView(obj) {
return Object.values(obj);
}
}


#5

Even doing that no changes are propagated. Its like Aurelia does not see the changes to the internal variables / array inside that CBuffer object and I don’t know how to force the change “event”


#6

I believe the problem was due to

The CBuffer maintains an internal array that has a set size allocated like a vector.
Call push is really just setting elements so change events do not occur.

I added this hack

CBuffer.prototype.setDirty = function () {
    let val = this.data[0];
    this.data.splice(0, 1, val);
}

And will call it from push I guess.


#7

another way to make the repeater to aknoledge changes after a value converter is to make it dependent of the length.
I’m just sending the length as a parameter to the value converter (even if the value converter is even not receiving it)

<ul>
    <li repeat.for="item of recent_data | meterTypeSelector:recent_data.length">
    ${item}
     </li>
</ul>