2

I'm building an app with Meteor using the react-komposer package. It is very simple: There's a top-level component (App) containing a search form and a list of results. The list gets its entries through the props, provided by the komposer container (AppContainer). It works perfectly well, until I try to implement the search, to narrow down the results displayed in the list.

This is the code I've started with (AppContainer.jsx):

import { Meteor } from 'meteor/meteor';
import { composeWithTracker } from 'react-komposer';
import React, { Component } from 'react';
import Entries from '../api/entries.js';
import App from '../ui/App.jsx';

function composer(props, onData) {
  if (Meteor.subscribe('entries').ready()) {
    const entries = Entries.find({}).fetch();
    onData(null, {entries});
  };
};

export default composeWithTracker(composer)(App);

App simply renders out the whole list of entries. What I'd like to achieve, is to pass query parameters to Entries.find({}).fetch(); with data coming from the App component (captured via a text input e.g.). In other words: How can I feed a parameter into the AppContainer from the App (child) component, in order to search for specific entries and ultimately re-render the corresponding results?

To further clarify, here is the code for App.jsx:

import React, { Component } from 'react';

export default class App extends Component {
  render() {
    return (
      <div>
        <form>
          <input type="text" placeholder="Search" />
        </form>
        <ul>
          {this.props.entries.map((entry) => (
            <li key={entry._id}>{entry.name}</li>
          ))}
        </ul>
      </div>
    );
  }
}

Thanks in advance!

2 Answers2

2

I was going to write a comment for this to clarify on nupac's answer, but the amount of characters was too restrictive.

The sample code you're looking for is in the search tutorial link provided by nupac. Here is the composer function with the corresponding changes:

function composer(props, onData) {
  if (Meteor.subscribe('entries', Session.get("searchValues")).ready()) {
    const entries = Entries.find({}).fetch();
    onData(null, {entries});
  };
};

The solution is the session package. You may need to add it to your packages file and it should be available without having to import it. Otherwise try with import { Session } from 'meteor/session'; You just need to set the session when submitting the search form. Like this for instance:

Session.set("searchValues", {
      key: value
});

The subscription will fetch the data automatically every time the specific session value changes.

Finally, you'll be able to access the values in the publish method on the server side:

Meteor.publish('entries', (query) => {
  if (query) {
    return Entries.find(query);
  } else {
    return Entries.find();
  }
});

Hope this helps. If that's not the case, just let me know.

0

There are 2 approaches that you can take.

  1. The Subscription way,
  2. The Meteor.call way,

The Subscription way

It involves you setting a property that you fetch from the url. So you setup your routes to send a query property to you Component.Your component uses that property as a param to send to your publication and only subscribe to stuff that fits the search criteria. Then you put your query in your fetch statement and render the result.

The Meteor.call way

Forget subscription and do it the old way. Send your query to an endpoint, in this case a Meteor method, and render the results. I prefer this method for one reason, $text. Minimongo does not support $text so you cannot use $text to search for stuff on the client. Instead you can set up your server's mongo with text indexes and meteor method to handle the search and render the results.

See what suits your priorities. The meteor.call way requires you to do a bit more work to make a "Search result" shareable through url but you get richer search results. The subscription way is easier to implement.

Here is a link to a search tutorial for meteor and read about $text if you are interested

SolarBear
  • 4,534
  • 4
  • 37
  • 53
nupac
  • 2,459
  • 7
  • 31
  • 56
  • Thanks for your answer. This gives me a rough idea of how to proceed, but I haven't been able to translate those approaches into actual code. Could you please provide an example based on the code excerpts? – Wolfgang Becker May 19 '16 at 22:07
  • @WolfgangBecker any update regarding this? i have the same problem basically i just want to filter the list in my component. Do you have a sample code? – reggieboyYEAH Jul 07 '16 at 07:14
  • @reggieboyYEAH I just submitted an alternative answer based on one of the solutions proposed by nupac. – Wolfgang Becker Jul 13 '16 at 04:29