Svelte: $m reactive not working

All,
I’m trying to build a simple search on text list.
The filtered resultset gives write number of rows but incorrect data rows.
Any help is greatly appreciated. Thanks

Sample code:

import Program from './Program.svelte';
import { ProgramsCollection } from '../api/ProgramsCollection';
	let programs = [];
	let filter = {};
	let search = '';
	$m: programs = ProgramsCollection.find(filter).fetch();

	const handleSubmit = () => {
		if (search != '') {
			filter = { title: new RegExp(search, 'i') };
		} else {
			filter = {};
		}
};
<div class="panel">
		<input class="program-title" type="text" name="search" placeholder="Type to search programs" bind:value={search} />
		<button on:click={() => handleSubmit()}>Filter Now </button>
</div>

{#each programs as program, i}
	<Program {program} />
{/each}

I think you need to subscribe to programs before you set up $m: programs =

$m: Meteor.subscribe(/* name of your programs publication */)

Also, as an aside, you shouldn’t need let programs = []

As Jam said you need to subscribe first.
To do a text search you need a text index in your programs collection.

As for usability. You could make the “Search Now” button inactive until the Search input has any value.

Can you give us an example of your output? By “right amount but incorrect” you mean that there are eg. 4 programs but the search string is not applied correctly?

Of course you need to subscribe, but I assume you either have a global subscription or the autopublish package installed. If the collection is big, you should reimplement the current solution in a more efficient way, but that does not answer your question now.

You don’t need a text index as the filtering is happening locally at the moment. And as for the database, the regex search works fine, but is generally slow (again, it depends on the collection size).

You can try to display the filter value on the page. I remember having issues that the regex had been considered the same although the string inside has changed. I don’t know what was the exact situation though. You can also doublecheck that the programs var does get recalculated:

$m: {
   programs = ProgramsCollection.find(filter).fetch();
   console.log(programs, filter)
}

Please see my code below.
When I run the programs and search for ‘Show’. it returns Program1 and Program2.
Any help is much appreciated.

Programs.svelte

<script>
	import Program from './Program.svelte';
	import { ProgramsCollection } from '../api/ProgramsCollection';

	let text = '';
	let filter = {};
	let isLoading = true;

	$m: {
		const handler = Meteor.subscribe('programs', filter);
		isLoading = !handler.ready();
	}

	let programs;
	$m: programs = ProgramsCollection.find(filter).fetch();

	const handleSubmit = (e) => {
		console.log('text:' + text);
		if (!text) {
			filter = {};
		} else {
			filter = { title: new RegExp(text, 'i') };
		}
	};
</script>

<div class="container">
	<form class="task-form" on:submit|preventDefault={handleSubmit}>
		<input type="text" name="text" placeholder="Type to search" bind:value={text} />
		<button type="submit">Search</button>
	</form>
	{#if isLoading}
		<div class="loading">loading...</div>
	{/if}
	{#each programs as program}
		<Program {program} />
	{/each}
</div>

<style>
	.panel {
		display: flex;
		padding: 10px;
		/* margin: 5px; */
	}
</style>

ProgramsCollections.js

import { Mongo } from 'meteor/mongo';
export const ProgramsCollection = new Mongo.Collection('programs');

ProgramsPublications.js

import { Meteor } from 'meteor/meteor';
import { ProgramsCollection } from '../api/ProgramsCollection';

Meteor.publish('programs', function publishPrograms(searchValue) {
	console.log('searchValue:' + searchValue);
	if (searchValue === '') {
		return ProgramsCollection.find({});
	} else {
		return ProgramsCollection.find({ title: new RegExp(searchValue, 'i') });
	}
});

Program.svelte

<script>
	export let program;

	const { title, _id } = program;
</script>

<div class="program">
	<div class="program-title">{title}</div>
</div>

server/main.js

import { Meteor } from 'meteor/meteor';
import { ProgramsCollection } from '/imports/api/ProgramsCollection';
import '/imports/api/ProgramsPublications';

const insertProgram = (program) =>
	ProgramsCollection.insert({
		title: program.title,
		createdAt: new Date(),
	});

Meteor.startup(() => {
	if (ProgramsCollection.find().count() == 0) {
		[
			{
				title: 'Program 1',
			},
			{
				title: 'Program 2',	
			},
			{
				title: 'Program 3',	
			},
			{
				title: 'Show 1',
			},
			{
				title: 'Show 2',
			},
		].forEach(insertProgram);
	}
	ProgramsCollection.createIndex({ title: 1 });
});