Skip to content

Instantly share code, notes, and snippets.

@daftspunk
Last active September 21, 2019 05:26
Show Gist options
  • Save daftspunk/f82dca0d410efe640ebebdd102af7f92 to your computer and use it in GitHub Desktop.
Save daftspunk/f82dca0d410efe640ebebdd102af7f92 to your computer and use it in GitHub Desktop.
Example filter engine in October
// ...
class Movie extends Model
{
// ...
/**
* The attributes on which the post list can be ordered
* @var array
*/
public static $allowedSortingOptions = array(
'created_at desc' => 'Posted date (descending)',
'created_at asc' => 'Posted date (ascending)',
'updated_at desc' => 'Last updated (descending)',
'updated_at asc' => 'Last updated (ascending)',
'name desc' => 'Name (descending)',
'name asc' => 'Name (ascending)',
);
/**
* Lists movies for the front end
* @param array $options Display options
* @return self
*/
public function scopeListFrontEnd($query, $options = [])
{
/*
* Default options
*/
extract(array_merge([
'page' => 1,
'perPage' => 30,
'sort' => 'created_at desc',
'users' => null,
'types' => null,
'categories' => null,
'search' => ''
], $options));
$searchableFields = ['name', 'slug', 'description'];
/*
* Sorting
*/
if (!is_array($sort)) $sort = [$sort];
foreach ($sort as $_sort) {
if (in_array($_sort, array_keys(self::$allowedSortingOptions))) {
$parts = explode(' ', $_sort);
if (count($parts) < 2) array_push($parts, 'desc');
list($sortField, $sortDirection) = $parts;
$query->orderBy($sortField, $sortDirection);
}
}
/*
* Type
*/
if ($types) {
$query->whereIn('movie_type', (array) $types);
}
/*
* Search
*/
$search = trim($search);
if (strlen($search)) {
$query->searchWhere($search, $searchableFields);
}
/*
* Skills categories
*/
if ($categories !== null) {
if (!is_array($categories)) $categories = [$categories];
$query->whereHas('skill_categories', function($q) use ($categories) {
$q->whereIn('id', $categories);
});
}
return $query->paginate($perPage, $page);
}
// ...
}
url = "/movies"
==
function onStart()
{
$this->prepareVars();
}
function onFilterMovies()
{
$this->prepareVars();
}
function prepareVars()
{
$options = post('Filter', []);
$this['movies'] = MovieModel::listFrontEnd($options);
$this['sortOptions'] = MovieModel::$allowedSortingOptions;
$this['movieCategories'] = CategoryModel::all();
$this['movieTypes'] = [
'movie' => 'Movie',
'series' => 'TV Series'
];
}
==
<script>
$('#partialMoviesFilter').on('change', 'input,select', function(){
var $form = $(this).closest('form')
if (filterTimer !== undefined)
window.clearTimeout(filterTimer)
filterTimer = window.setTimeout(function(){
$form.request()
}, 500)
})
</script>
{{ form_ajax('onFilterMovies', {
id: 'moviesBrowseForm',
update: { 'movies/movies': '#partialMoviesMovies' }
}) }}
<div id="partialMoviesFilter" class="movies-filter">
{% partial 'movies/filter' %}
</div>
{{ form_close() }}
<div id="partialMoviesMovies">
{% partial 'movies/movies' movies=movies %}
</div>
<h5>Movie type</h5>
{% for code, label in movieTypes %}
<input
type="checkbox"
name="Filter[types][]"
value="{{ code }}" />
<label>{{ label }}</label>
{% endfor %}
<h5>Search</h5>
<input
type="text"
name="search"
value="" />
<h5>Categories</h5>
{% for category in movieCategories %}
<input type="checkbox" name="Filter[categories][]" value="{{ category.id }}" />
<label>{{ category.name }}</label>
{% endfor %}
<h5>Sort by</h5>
<select name="Filter[sort]">
{% for code, option in sortOptions %}
<option value="{{ code }}">{{ option }}</option>
{% endfor %}
</select>
{% if movies|length %}
{% for movie in movies %}
<div class="item">
Movie item
</div>
{% endfor %}
{% else %}
<div class="ui message text-center">
<p>
There are no movies that match the criteria.
</p>
</div>
{% endif %}
@Krank3n
Copy link

Krank3n commented Sep 21, 2019

Hey Samuel, Thank you so much for this! I think the search input name needs to be like:

**name="Filter[search]"**

Love your work mate!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment