Live filtering a list when using togglecontrol.

What would be the best way to create a live filter?

Im currently using a ToggleControl bound to an observable value ( ‘selected’ ), and when the ToggleControl is toggled I want the list to be filtered, but nothing happens. What am I doing wrong? I’m still in the process of learning fuse, so bear with me. It seems like whatever combination I try using Any, Where, Flatmap, Map, the filtered list is not updated when the ‘selected’ is toggled.

var categories = new Observable(
{
    id : 1,
    title : "my title",
    selected : new Observable(true)},
{    id : 2,
        title : "my other title",
        selected : new Observable(true)}, 
{
        id : 3,
        title : "my third title",
        selected : new Observable(false)}
);

var subscribed_categories = categories.flatMap(function(e) {
    return categories.where(function() {
        return e.selected.value;
    });
});

module.exports = {
     subscribed_categories: subscribed_categories,
}

...
<Each Items="{subscribed_categories }">
<ToggleControl HitTestMode="LocalBounds" Height="80" Value="{selected}">
    <Clicked>
        <Toggle Target="this"/>
    </Clicked>
</ToggleControl>
</Each>
...

Hi Palton,

the reactive operators on multi-value Observables are only recalculated when there are any changes to the list itself - when an item is added or removed. In your case, you want to filter an Observable list by an Observable property that belongs to its list items - and making changes to that property does not affect the list itself in no way.

I played around with the idea and came up with the following hack’ish solution. Note that it does not (and can not) use Observables for storing the selected state, because every time I replace the items they will be completely new items and old data-bindings to those list-item-selected-properties would die.

Also, if you’re expecting to have a very large list, then this is definitely NOT the way to do it.

<App>
	<JavaScript>
	var Observable = require("FuseJS/Observable");

	var categories = Observable(
		new Category(1, "cat one", true),
		new Category(2, "cat two", true),
		new Category(3, "cat three", false),
		new Category(4, "cat four", false),
		new Category(5, "cat five", true),
		new Category(6, "cat six", false)
	);

	function refresh() {
		categories.replaceAll(categories.toArray());
	}

	function Category(id, title, selected) {
		this.id = id;
		this.title = title;
		this.selected = selected;
		var self = this;
		this.toggleSelect = function() {
			self.selected = ! self.selected;
			refresh();
		}
	}

	var selectedCategories = categories.where({selected: true});
	var notSelectedCategories = categories.where({selected: false});

	module.exports = {
		selectedCategories: selectedCategories,
		notSelectedCategories: notSelectedCategories
	};
	</JavaScript>
	<ClientPanel>
		<Grid RowCount="2" Margin="2">
			<StackPanel Color="#f003" ItemSpacing="2">
				<Each Items="{notSelectedCategories}">
					<Panel Height="56" HitTestMode="LocalBounds">
						<Clicked>
							<Callback Handler="{toggleSelect}" />
						</Clicked>
						<Text Value="{title}" Alignment="Center" Color="#000a" />
						<Rectangle Color="#0003" CornerRadius="2" />
					</Panel>
				</Each>
			</StackPanel>
			<StackPanel Color="#00f3" ItemSpacing="2">
				<Each Items="{selectedCategories}">
					<Panel Height="56" HitTestMode="LocalBounds">
						<Clicked>
							<Callback Handler="{toggleSelect}" />
						</Clicked>
						<Text Value="{title}" Alignment="Center" Color="#000a" />
						<Rectangle Color="#0003" CornerRadius="2" />
					</Panel>
				</Each>
			</StackPanel>
		</Grid>
	</ClientPanel>
</App>

Thank you Uldis for a nice solution!
The list is not going to be very large so this works great! :slight_smile:

By the way, I updated fusetools today and the new environment looks great!