Search code examples
javascriptmeteormeteor-helper

Loading fields from collection into select field and filtering it based on selected value


Basically i have two questions which are related but i'll separate them with numbers 1) I am trying to load a single field into a select dropdown box from collection but its populating with all repetitive values it collected from the list below it instead of its own helper.

<template name="carsList">

{{> categoryFilter}}

<ul class="collection" id="listings">
{{#each cars}}
<li>
  {{> carItem}}
</li>
{{/each}}
 </ul>
</template>

category template is

<template name="categoryFilter">
 <div class="input-field">
 <select>
   <option value="" disabled selected>Choose your option</option>
    {{#each companyCategories}}
     {{> companyCategory}}
    {{/each}}
 </select>
 <label>Select Category</label>
</div>
</template>

<template name="companyCategory">
  <option>{{ccategory}}</option>
</template>

categoryFilter is holding the dropdown template for which iam using the below helper

Template.categoryFilter.helpers({
companyCategories: function(){
return Cars.find();
}
});

instead of populating from its own helper its loading the data that is coming from "listings" below it and repeating data.

Image of the result in selectbox

2) I also want to filter the listings based on the value selected in the select dropdown box (Ofcourse reactive)

Please help

EDIT

This is how my template looks now

<template name="categoryFilter">
 <div class="input-field">
  <select>
   <option value="" disabled selected>Choose your option</option>
    {{#each companyCategories}}
      {{> companyCategory}}
    {{/each}}
   </select>
 <label>Select Category</label>
 </div>
</template>

<template name="companyCategory">
 <option>{{justCategory}}</option>
</template>

Solution

  • Here is how I would proceed. First, the dropdown: you should use a cursor instead of an array of documents. So your helper should be:

    Template.categoryFilter.helpers({
        companyCategories: function(){
           return Jobs.find();
        }
    });
    

    and your categoryFilter template HTML could be something like this

    <template name="categoryFilter">
    <div class="dropdown">
      <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
        {{selectedCategory}} <!-- refer to an helper which returns the reactive variable--> 
        <span class="caret"></span>
      </button>
      <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
      {{#each companyCategories}}
        <li role="presentation"><a role="menuitem" class="categoryItem" tabindex="-1" href="#">{{yourCatergoryNameField}}</a></li>
      {{/each}}
      </ul>
    </div>
    </template>
    

    You can then create an event to record the current category selected in the dropdown when it is clicked

        "click .categoryItem": function(e, t) {
            var text = $(e.target).text()
            Session.set("selectedCategory", text)
        },
    

    Now, you can filter your cars using the selectedCategory reactive variable. For this, you need another helper. It could be for instance:

    Template.carList.helpers({
        carListingByCategory: function(){
           var filter = Session.get ("selectedCategory");
           return Car.find(category:filter)
        }
    });
    

    That should do the trick. I never use Session, so it might not work as I suppose it does. If it does not work, use ReactiveDict instead. Basically, you add var pageSession = new ReactiveDict(); at the beginning of your doc and you can replace Session with pageSession in my code.

    EDIT

    Ok, let's have a try with underscore. Based on this answer, here is what you can do to return all the distinct categories for every item of allJobs:

    Template.categoryFilter.helpers({
        companyCategories: _.uniq(Collection.find({}, {
            sort: {myField: 1}, fields: {myField: true}
        }).fetch().map(function(x) {
            return x.myField;
        }), true);
        }
    });
    

    where myfield is your categories array field.

    EDIT 2

    Try to change your html and replace {{justCategory}} with {{this}}:

    <template name="categoryFilter">
     <div class="input-field">
      <select>
       <option value="" disabled selected>Choose your option</option>
        {{#each companyCategories}}
          {{> companyCategory}}
        {{/each}}
       </select>
     <label>Select Category</label>
     </div>
    </template>
    
    <template name="companyCategory">
     <option>{{this}}</option>
    </template>