Hey, ran into an issue while trying to use observable.contains() method to check if my list contains a specific object. An Observable holding complex types (objects) seems to only trigger a match when I’m looking for the exact object that I previously added to the list. It does not trigger a match when I search for an identical-looking object. An Observable holding simple types (strings, numbers) doesn’t care if the thing you search for is that specific string or number, as long as the value matches.
I do understand that the objects I’m checking for are different, even if they look the same. Is there an alternative way to using .contains() for matching on [copies of] objects?
Consider the following code:
var Observable = require('FuseJS/Observable');
// a simple object constructor
function Obj(id) {
this.id = id;
}
// an observable for holding the objects
var list = Observable();
// a couple objects for testing
var obj1 = new Obj('one');
var obj2 = new Obj('two');
var obj3 = new Obj('three');
// add the objects to the observable
list.add(obj1);
list.add(obj2);
list.add(obj3);
console.log(list.contains(obj2)); // prints True
console.log(list.contains(new Obj('two'))); // prints False
As JavaScript doesn’t have structural equality, you can do this using count which supports a condition, and then implement your own equality operator in the condition. count returns an Observable you can then map to with something like var contains = count(equalityCheck).map(function (c) { return c >= 1; }). This should be roughly equivalent to a contains(condition), but it would probably be nice to have that as part of the library as well.
Something like this works:
<App Theme="Basic">
<JavaScript>
var Observable = require('FuseJS/Observable');
// a simple object constructor
function Obj(id) {
this.id = id;
}
// an observable for holding the objects
var list = Observable();
// a couple objects for testing
var obj1 = new Obj('one');
var obj2 = new Obj('two');
var obj3 = new Obj('three');
// add the objects to the observable
list.add(obj1);
list.add(obj2);
list.add(obj3);
console.log("Object contains: " + list.contains(obj2)); // prints True
console.log("Similar object contains: " + list.contains(new Obj('two'))); // prints False
var countWhere = list.count(function (o) {
return o.id === 'two';
});
var countContains = countWhere.map(function (c)
{
return c >= 1;
});
module.exports = {
countWhere : countWhere,
countContains : countContains
};
</JavaScript>
<StackPanel>
<Text Value="{countWhere}" />
<WhileTrue Value="{countContains}">
<Text>It is contained</Text>
</WhileTrue>
</StackPanel>
</App>
However, you might need to do some ninja magic, similar to the Observable functions we did earlier to be able to parametrize what you are looking for as an id, let me know if you want me to throw that together for you quickly.
<App Theme="Basic">
<JavaScript>
var Observable = require('FuseJS/Observable');
// a simple object constructor
function Obj(id) {
this.id = id;
}
// an observable for holding the objects
var list = Observable();
// a couple objects for testing
var obj1 = new Obj('one');
var obj2 = new Obj('two');
var obj3 = new Obj('three');
var collectionSearchId = Observable('two')
// add the objects to the observable
list.add(obj1);
list.add(obj2);
list.add(obj3);
var contains = collectionSearchId.map(function (s) {
return list.count(function (o) {
return o.id === s;
}).map(function (c) { return c >= 1; });
}).inner();
module.exports = {
contains : contains
};
</JavaScript>
<StackPanel>
<WhileTrue Value="{contains}">
<Text>It is contained</Text>
</WhileTrue>
</StackPanel>
</App>