The Blaze components provide you with an input, the results view, logic to add loading spinners and more. Those are also customizable
and should be sufficient for most use cases. The components can be used in the easy:search
package which wraps the core and
easysearch:components
into one. This article assumes you have read the Getting started page beforehand.
All the components require you to add an index parameter which is the index instance that it should act on. Certain components allow you to specify an array of indexes to pass in. You can also specify a name when you want to have multiple components of an index on the same page.
Renders an <input>
tag that searches the specified index(es). It searches through all the configured fields
on your index.
Allows to use multiple indexes.
{{> EasySearch.Input index=myIndex}}
{ placeholder: "Search..." }
)enter
, if it only should search on enterIs the same as EasySearch.Input
, but lets you search in a specified field. Allows to use multiple indexes.
{{> EasySearch.FieldInput field="name" index=myIndex}}
{ placeholder: "Search for this" }
)enter
, if it only should search on enterLoops through the found documents if any are found.
{{#EasySearch.Each index=myIndex}}
<div class="result">{{someField}}</div>
{{/EasySearch.Each}}
Renders the content when the input that’s associated with the index is empty. Allows multiple indexes.
{{#EasySearch.IfInputEmpty index=myIndex}}
<div>Start searching!</div>
{{/EasySearch.IfInputEmpty}}
Renders the content when there are no results found. Allows multiple indexes.
{{#EasySearch.IfNoResults index=myIndex}}
<div>No results found!</div>
{{/EasySearch.IfNoResults}}
Renders the content when the associated input is being searched. Allows multiple indexes.
{{#EasySearch.IfSearching index=myIndex}}
<div>Searching...</div>
{{/EasySearch.IfSearching}}
Renders a <button>
tag that loads more documents if there are more than currently displayed.
{{> EasySearch.LoadMore index=myIndex content="Load more content"}}
{ class: "load-more-button" }
)Renders an unordered list that displays pages to navigate through if there are more documents than current displayed.
{{> EasySearch.Pagination index=myIndex maxPages=10}}
You can retrieve component values, such as the current search string by using the index method getComponentDict
.
// Assuming you either use EasySearch.Input or EasySearch.FieldInput inside your app
Template.searchBox.helpers({
searchCount: () => {
// index instanceof EasySearch.index
let dict = index.getComponentDict(/* optional name */)
// get the total count of search results, useful when displaying additional information
return dict.get('count')
}
})
The components use the dictionary themselves to store reactive state. You can retrieve following values through the dictionary.
search
If you want to work with multiple indexes on your components, you can simply specify indexes
instead of index
on the component.
This is where the logic
parameter that each if component has becomes helpful.
import { Index } from 'meteor/easy:search'
const indexOne = new Index({
...
})
const indexTwo = new Index({
...
})
Template.searchBox.helpers({
searchIndexes: () => [indexOne, indexTwo],
indexOne: () => indexOne,
indexTwo: () => indexTwo,
})
<template name="searchBox">
{{> EasySearch.Input indexes=searchIndexes }}
{{#EasySearch.IfNoResults indexes=searchIndexes logic="AND" }}
<div>No search results found</div>
{{/EasySearch.IfNoResults}}
{{#EasySearch.IfSearching indexes=searchIndexes logic="OR" }}
<div>Indexes are searching...</div>
{{/EasySearch.IfSearching}}
{{#EasySearch.Each index=indexOne }}
...
{{/EasySearch.Each}}
{{#EasySearch.Each index=indexTwo }}
...
{{/EasySearch.Each}}
</template>
This is a basic example using multiple indexes. Note how all components except EasySearch.Each
use indexes
as it’s parameter. This is
because EasySearch.Each
does only associate documents of one index, because otherwise there would be some merging logic between different
document structure which would be quite nasty. The logic
parameter decides how to apply the logic across the given indexes. For example
when searching it displays the Indexes are searching… content when one of the indexes searches, whereas the No search results found
is only showed when all of the indexes have no results.
Components use component methods that contain the core logic, such as searching with an input and so on. The index method
getComponentMethods
exposes them as a public Javascript API and makes it possible to add custom logic to your app.
Template.filterBox.events({
'change select': (e) => {
// index instanceof EasySearch.index
index.getComponentMethods(/* optional name */)
.addProps('countryFilter', $(e.target).val())
},
})
This code adds a custom property that is called countryFilter
and the value of a country code. Everytime somebody executes a search
(by either searching through an EasySearch.Input
or calling the search
method itself with the component methods) this countryFilter prop
can be used to filter the searchable documents. See the docs for more information.
The components are written with Blaze Components which offer a great way to re-use functionality by using ES2015 classes and its power of reusability while still keeping the simplicity of Blaze.
Let’s say you want to create a <select>
component that sets custom properties when you change an option. With pure blaze you would
use the getComponentMethods
method that’s on the index.
<template name="MySelectFilter">
<select>
<option value="awesome">Awesome</option>
<option value="not-so-awesome">Not so awesome</option>
</select>
</template>
Template.MySelectFilter.events({
'change select': function () {
// myIndex instanceof EasySearch.Index
myIndex.getComponentMethods()
.addProps('awesomeFilter', $(e.target).val().trim())
},
})
The above example would be useable by just calling {{> MySelectFilter}}
in your code. With Blaze Components you could create a component
that is useable for every index that supports the awesomeFilter.
class MySelectFilterComponent extends EasySearch.BaseComponent {
events() {
return [{
'change select' : function (e) {
const selectedValue = $(e.target).val().trim()
this.eachIndex((index, name) => {
index.getComponentMethods(name)
.addProps('awesomeFilter', selectedValue)
})
},
}]
}
}
MySelectFilterComponent.register('MySelectFilter')
This could be used by calling {{> MySelectFilter index=index}}
or with multiple indexes.