Answers.Body: <p>Okay, please don't be afraid and give it a try. I'm using the angular way, it seems a little bit difficult but it's actually really easy once you get used to it and works perfectly as soon as you understand it a little bit. If you need changes I'll provide whatever you need.<br>
  <strong>Edit</strong>: here you can see a live example for it <a href="https://plnkr.co/edit/uqIupfOslx7qWMedoiBE?p=preview" rel="nofollow noreferrer">plunker</a> or course without css but it is your html</p>
  
  <p>Let's get into it.
  For testing purposes I created this category structure in my backend and called the group <code>filter</code>.
  <a href="https://i.sstatic.net/QAVVY.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/QAVVY.png" alt="enter image description here"></a></p>
  
  <p>First you need to include this library you can of course use the <code>{% includeJsRessource %}</code> as well</p>
  
  <pre><code>&lt;script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"&gt;&lt;/script&gt;
  </code></pre>
  
  <p>Then you create 2 javascript arrays one for the Culture, Democracy... I call them parents and one for their children that belong to them</p>
  
  <pre><code>// get all filters of the first level
  {% set filters = craft.categories.group('filter').level(1).find() %}
  &lt;script type="text/javascript"&gt;
      var children = [];
      var parents = [];
      {% for filter in filters %}
          parents.push({
              title: "{{ filter.title }}",
              id: "{{ filter.id }}"
          });
          // now fetch all children for them
          {% set children = craft.categories.group('filter').descendantOf(filter).level(2).find() %}
          {% for child in children %}
              children.push({
                  title: "{{ child.title }}",
                  id: "{{ child.id }}",
                  parent: "{{ filter.id }}"
              });
          {% endfor %}
      {% endfor %}
  &lt;/script&gt;
  </code></pre>
  
  <p>In the end you'll have 2 array that could look like<a href="https://i.sstatic.net/5qnGf.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/5qnGf.png" alt="enter image description here"></a></p>
  
  <p>Now the funny part starts
  include this javascript file. You can ask whatever you want I'll explain it. Even if the syntax and everything what's going on seems a little bit strange, but make sure this is loaded <strong>after</strong> the library from above</p>
  
  <pre><code>var  myApp = angular.module('myApp',[]).config(function($interpolateProvider) {
      $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
  });
  
  myApp.controller('filterController', ['$scope', function ($scope) {
      // all parents
      $scope.parents = parents;
      // all children
      $scope.children = children;
  
      // return if the parent is selected or not
      $scope.filterBySelectedParent = function (item) {
          return $scope.selectedParents.indexOf(item.parent) !== -1;
      };
  
      // an array with all selected parent ids
      $scope.selectedParents = [];
  
      // include an item to the array or slice it when the input it clicked
      $scope.addFilter = function(id){
          var index = $scope.selectedParents.indexOf(id);
          if(index === -1){
              $scope.selectedParents.push(id);
          }else{
              $scope.selectedParents.splice(index, 1);
          }
      }
  }]);
  </code></pre>
  
  <p>And finally your new html</p>
  
  <pre><code>&lt;!-- this is your menu or your filter bar or whatever you want to call it --&gt;
  &lt;!-- I inspected your html and tried to use that but you must include ng-app and ng-controller somewhere --&gt;
  &lt;div ng-app="myApp" ng-controller="filterController"&gt;
      &lt;!-- your first ul... all your parents, the first filter in your page --&gt;
      &lt;ul&gt;
          &lt;li ng-repeat="filter in parents"&gt;
              &lt;label class=""&gt;
                  &lt;input type="checkbox" ng-click="addFilter(filter.id);" value="{[{filter.id}]}"&gt;&lt;span&gt;{[{ filter.title }]}&lt;/span&gt;
              &lt;/label&gt;
          &lt;/li&gt;
      &lt;/ul&gt;
  
      &lt;!-- all your children, the second filter in your page --&gt;
      &lt;ul&gt;
          &lt;li class="" ng-repeat="child in children | filter: filterBySelectedParent"&gt;
              &lt;label class="" &gt;
                  &lt;input type="checkbox" data-name="selectItemfocusArea" value="{[{ child.id }]}"&gt;&lt;span&gt;{[{ child.title }]}&lt;/span&gt;
              &lt;/label&gt;
          &lt;/li&gt;
      &lt;/ul&gt;
  
      &lt;!-- include the rest here --&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>Explanation: so what actually happens is the following </p>
  
  <ol>
  <li>you create 2 arrays in javascript based on your backend inputs</li>
  <li>angular renders your menu based on those two arrays but the second one has a filter. Only clicked items of the first array are shown</li>
  <li>as soon as someone clicks on an filter it is included in an array <code>$scope.selectedParents</code> </li>
  <li>any change in this array is recognized automatically which results, that the html renders again => your other filters are shown.</li>
  </ol>
  
  <p>Please tell me if I missunderstood you somehow.. based on my current state I can change nearly everything really easily in just a few clicks. For example if you would like to automatically select your children you would include <code>ng-checked="filterBySelectedParent(child)"</code> on your input and remove the <code>| filter: filterBySelectedParent</code>.. that's it</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-09T02:08:10.720Z
Answers.Text: Thanks for this solution!  As for the HTML, it's actually possible to just add the options to the select box and it gets generated into that ul/li list with labels with a plugin I'm using to create the multi-checkbox functionality.  I will try out your method though and let you know how it goes!
Answers.UserDisplayName: user5824
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-09T02:17:47.830Z
Answers.Text: Ah okay sry I thought it was your work. My solution has definitely disadvantages, for example you have to get used to the new methods but from my experience (and everyone else will say the same who uses angular) for searching/filtering and filter that depends other filters and all these kind of things this method is perfect because you don't have to care about the html since angular does everything for you and of course it boosts your performance compared to php or jquery. Anyway I wish you good luck
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-13T02:37:41.270Z
Answers.Text: Hi Robin, thanks for much for the help.  I've made a test page to test your solution and it's not quite working: http://www.joycefdn.org/grantsDB
  I tried to convert the HTML to the select boxes that I need and it doesn't work when I apply the multiple select option plugin to the selects, in that case, the secondary select box does not fill in at all.  Also, I need the values of the select boxes to still be the titles of the categories because that's how the filtering works.  Any help would be greatly appreciated!!
Answers.UserDisplayName: user5824
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-13T02:41:18.763Z
Answers.Text: This is how I tried to edit it:
  <div ng-app="myApp" ng-controller="filterController">
  <select id="program" name="program" multiple="multiple">
  <option value="" selected>Program</option>
  <option ng-repeat="filter in parents" ng-click="addFilter(filter.id);" value="{[{filter.id}]}">{[{ filter.title }]}</option>
  </select>
  <select id="focusArea" name="focusArea" multiple="multiple">
  <option class="" ng-repeat="child in children | filter: filterBySelectedParent"><span data-name="selectItemfocusArea" value="{[{ child.id }]}">{[{ child.title }]}</span>
  </option>
  </select>
  </div>
Answers.UserDisplayName: user5824
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-13T03:08:25.490Z
Answers.Text: I'm so sorry, I'm really new to Stack Exchange, I think I forgot to tag you... @robin-schambach
Answers.UserDisplayName: user5824
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-13T05:11:18.953Z
Answers.Text: It actually works but you hide the real select with all functionality and show the useless jquery select with no functionality instead. By the way: best practice would be to create all your filters that way, so you have multiple Arrays with all filters, in order to display the entries by your arrays. If you want I could do it for you. It makes everything much easier and smoother. I tried to accomplish such a thing with jquery in the past too. But it becomes a pain sooner or later
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-13T05:34:10.340Z
Answers.Text: I think that is the same reason why your previous code did not work either. Your code may have been correct but you did not activate your functions for the jquery filter, only for you own but you hide it and never use it
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-13T18:23:11.603Z
Answers.Text: I'm not sure what you mean, do you mean I could use Angular to make the multi-select options in the select boxes instead of the jQuery plugin? The other filters don't really need to cascade on each other like the Program and Focus Area ones so I'm only using jQuery to make them multi-selects, also for your code, is there a way to make them cascade on each other without using "value" since that's how the filters display the entries?  Thanks!!
Answers.UserDisplayName: user5824
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-13T18:28:35.130Z
Answers.Text: It's not that you could to it, you should use only angular or another jquery plugin, since the one you use is not able to sync properly. The value attribute does not matter, you can leave it if you don't want to use the real strength of the script and of course if you don't want to avoid trouble sooner or later because of jquery. As soon as you have more entries and reach a certain limit or if you want to include more filters it is going to be mess
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-13T19:05:23.427Z
Answers.Text: ohhh, I see what you mean.  I see it working in my test page now, I just have to reconcile how it filters the entries now and style it.  Does it seem right to you??  Thanks!
Answers.UserDisplayName: user5824
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-13T19:08:46.580Z
Answers.Text: That's one way you could do it
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-09T01:05:37.030Z
Answers.LastActivityDate: 2017-12-09T01:30:49.183Z
Answers.LastEditDate: 2017-12-09T01:30:49.183Z
Answers.UserDisplayName: Robin Schambach
Body: <p>I have a question about combining Twig and jQuery in Craft. I have a couple of filters on a page that outputs some entries:
  <a href="http://www.joycefdn.org/grants" rel="nofollow noreferrer">http://www.joycefdn.org/grants</a></p>
  
  <p>My categories are organized like this:
  Education and Economic Mobility
   - Educator Quality 
   - Innovation<br>
   - Pathways 
  Environment 
   - Climate Solutions<br>
   - Great Lakes<br>
  Culture 
   - Arts Access and Participation<br>
   - Arts Leadership and Workforce<br>
   - Creativity and Cultural Production<br>
   - Joyce Awards 
  Democracy<br>
   - Fair Elections<br>
   - Media<br>
  Gun Violence Prevention and Justice Reform<br>
   - Gun Violence Prevention<br>
   - 21st Century Policing<br>
   - Reducing Mass Incarceration<br>
  Special Opportunities<br>
   - Communications<br>
   - Cross-Programmatic Innovations<br>
   - Digital Tools</p>
  
  <p>with the top level being Programs and the second level being focus areas.  I would like to have it so that when a Program is selected then the Focus Area select menu gets populated with the categories that are children of that program.  I currently have this jQuery left over from another method I tried which does get the current Programs that are selected:</p>
  
  <pre><code>$(".grants-data form[name='grantSearch'] select[name='program']").change(function(){
      var selectedPrograms = $("form[name='grantSearch'] input[data-name='selectItemprogram'][value!='']:checked").map(function() {
      return this.value;
                  }).get().join('|');
  });
  </code></pre>
  
  <p>and I have this which appends all of the descendants of all categories to the focus area menu:</p>
  
  <pre><code>{% set catSlug = craft.categories.title('focusArea').first() %}
              {% set childFAs = craft.categories.descendantOf(catSlug) %} 
              $("select#focusArea").html('&lt;option value=""&gt;Focus Area&lt;/option&gt;');
              {% for fa in childFAs %}
              $("select#focusArea").append('&lt;option value="{{fa.title}}"&gt;{{fa.title}}&lt;/option&gt;');
              {% endfor %}
              {% if faSlug|length %}
                  $("select#focusArea option[value='{{faSlugOrig}}']").attr('selected',true);
              {% endif %}
              &lt;/script&gt;
  </code></pre>
  
  <p>but I can't seem to connect these two so that only the descendants of the program that is clicked get populated.  I think I may be overthinking this or trying to combine two methods that just won't combine.  Any help would be greatly appreciated!</p>
  
  <p>Thanks!!</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-12-08T23:59:49.037Z
Comments.Text: Would an answer without jquery be ok for you too? I don't like jquery for this task but I could help you
Comments.UserDisplayName: Robin Schambach
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-12-09T00:07:08.363Z
Comments.Text: Sure!  Any answer would be okay with me :-)
Comments.UserDisplayName: user5824
Tags: <categories>
Title: Selecting descendants of a category when ancestor is clicked
ThreadText: # Selecting descendants of a category when ancestor is clicked
  
  (Asked by: username_0 on 2017-12-08)
  
  I have a question about combining Twig and jQuery in Craft. I have a couple of filters on a page that outputs some entries:
  <http://www.joycefdn.org/grants>
  
  My categories are organized like this:
  Education and Economic Mobility
  - Educator Quality
  - Innovation  
  - Pathways
  Environment
  - Climate Solutions  
  - Great Lakes  
  Culture
  - Arts Access and Participation  
  - Arts Leadership and Workforce  
  - Creativity and Cultural Production  
  - Joyce Awards
  Democracy  
  - Fair Elections  
  - Media  
  Gun Violence Prevention and Justice Reform  
  - Gun Violence Prevention  
  - 21st Century Policing  
  - Reducing Mass Incarceration  
  Special Opportunities  
  - Communications  
  - Cross-Programmatic Innovations  
  - Digital Tools
  
  with the top level being Programs and the second level being focus areas. I would like to have it so that when a Program is selected then the Focus Area select menu gets populated with the categories that are children of that program. I currently have this jQuery left over from another method I tried which does get the current Programs that are selected:
  
  ```
  $(".grants-data form[name='grantSearch'] select[name='program']").change(function(){
      var selectedPrograms = $("form[name='grantSearch'] input[data-name='selectItemprogram'][value!='']:checked").map(function() {
      return this.value;
                  }).get().join('|');
  });
  
  ```
  
  and I have this which appends all of the descendants of all categories to the focus area menu:
  
  ```
  {% set catSlug = craft.categories.title('focusArea').first() %}
              {% set childFAs = craft.categories.descendantOf(catSlug) %} 
              $("select#focusArea").html('<option value="">Focus Area</option>');
              {% for fa in childFAs %}
              $("select#focusArea").append('<option value="{{fa.title}}">{{fa.title}}</option>');
              {% endfor %}
              {% if faSlug|length %}
                  $("select#focusArea option[value='{{faSlugOrig}}']").attr('selected',true);
              {% endif %}
              </script>
  
  ```
  
  but I can't seem to connect these two so that only the descendants of the program that is clicked get populated. I think I may be overthinking this or trying to combine two methods that just won't combine. Any help would be greatly appreciated!
  
  Thanks!!
  
  **Tags:** categories
  
  > **Comments:**
  > **username_1**: Would an answer without jquery be ok for you too? I don't like jquery for this task but I could help you  
  > **username_0**: Sure!  Any answer would be okay with me :-)  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2017-12-09. Score: 0 | Accepted answer
  
  Okay, please don't be afraid and give it a try. I'm using the angular way, it seems a little bit difficult but it's actually really easy once you get used to it and works perfectly as soon as you understand it a little bit. If you need changes I'll provide whatever you need.  
  **Edit**: here you can see a live example for it [plunker](https://plnkr.co/edit/uqIupfOslx7qWMedoiBE?p=preview) or course without css but it is your html
  
  Let's get into it.
  For testing purposes I created this category structure in my backend and called the group `filter`.
  [![enter image description here](https://i.sstatic.net/QAVVY.png)](https://i.sstatic.net/QAVVY.png)
  
  First you need to include this library you can of course use the `{% includeJsRessource %}` as well
  
  ```
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
  
  ```
  
  Then you create 2 javascript arrays one for the Culture, Democracy... I call them parents and one for their children that belong to them
  
  ```
  // get all filters of the first level
  {% set filters = craft.categories.group('filter').level(1).find() %}
  <script type="text/javascript">
      var children = [];
      var parents = [];
      {% for filter in filters %}
          parents.push({
              title: "{{ filter.title }}",
              id: "{{ filter.id }}"
          });
          // now fetch all children for them
          {% set children = craft.categories.group('filter').descendantOf(filter).level(2).find() %}
          {% for child in children %}
              children.push({
                  title: "{{ child.title }}",
                  id: "{{ child.id }}",
                  parent: "{{ filter.id }}"
              });
          {% endfor %}
      {% endfor %}
  </script>
  
  ```
  
  In the end you'll have 2 array that could look like[![enter image description here](https://i.sstatic.net/5qnGf.png)](https://i.sstatic.net/5qnGf.png)
  
  Now the funny part starts
  include this javascript file. You can ask whatever you want I'll explain it. Even if the syntax and everything what's going on seems a little bit strange, but make sure this is loaded **after** the library from above
  
  ```
  var  myApp = angular.module('myApp',[]).config(function($interpolateProvider) {
      $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
  });
  
  myApp.controller('filterController', ['$scope', function ($scope) {
      // all parents
      $scope.parents = parents;
      // all children
      $scope.children = children;
  
      // return if the parent is selected or not
      $scope.filterBySelectedParent = function (item) {
          return $scope.selectedParents.indexOf(item.parent) !== -1;
      };
  
      // an array with all selected parent ids
      $scope.selectedParents = [];
  
      // include an item to the array or slice it when the input it clicked
      $scope.addFilter = function(id){
          var index = $scope.selectedParents.indexOf(id);
          if(index === -1){
              $scope.selectedParents.push(id);
          }else{
              $scope.selectedParents.splice(index, 1);
          }
      }
  }]);
  
  ```
  
  And finally your new html
  
  ```
  <!-- this is your menu or your filter bar or whatever you want to call it -->
  <!-- I inspected your html and tried to use that but you must include ng-app and ng-controller somewhere -->
  <div ng-app="myApp" ng-controller="filterController">
      <!-- your first ul... all your parents, the first filter in your page -->
      <ul>
          <li ng-repeat="filter in parents">
              <label class="">
                  <input type="checkbox" ng-click="addFilter(filter.id);" value="{[{filter.id}]}"><span>{[{ filter.title }]}</span>
              </label>
          </li>
      </ul>
  
      <!-- all your children, the second filter in your page -->
      <ul>
          <li class="" ng-repeat="child in children | filter: filterBySelectedParent">
              <label class="" >
                  <input type="checkbox" data-name="selectItemfocusArea" value="{[{ child.id }]}"><span>{[{ child.title }]}</span>
              </label>
          </li>
      </ul>
  
      <!-- include the rest here -->
  </div>
  
  ```
  
  Explanation: so what actually happens is the following
  
  1. you create 2 arrays in javascript based on your backend inputs
  2. angular renders your menu based on those two arrays but the second one has a filter. Only clicked items of the first array are shown
  3. as soon as someone clicks on an filter it is included in an array `$scope.selectedParents`
  4. any change in this array is recognized automatically which results, that the html renders again => your other filters are shown.
  
  Please tell me if I missunderstood you somehow.. based on my current state I can change nearly everything really easily in just a few clicks. For example if you would like to automatically select your children you would include `ng-checked="filterBySelectedParent(child)"` on your input and remove the `| filter: filterBySelectedParent`.. that's it
  
  > **Comments:**
  > **username_0**: Thanks for this solution!  As for the HTML, it's actually possible to just add the options to the select box and it gets generated into that ul/li list with labels with a plugin I'm using to create the multi-checkbox functionality.  I will try out your method though and let you know how it goes!  
  > **username_1**: Ah okay sry I thought it was your work. My solution has definitely disadvantages, for example you have to get used to the new methods but from my experience (and everyone else will say the same who uses angular) for searching/filtering and filter that depends other filters and all these kind of things this method is perfect because you don't have to care about the html since angular does everything for you and of course it boosts your performance compared to php or jquery. Anyway I wish you good luck  
  > **username_0**: Hi username_1, thanks for much for the help.  I've made a test page to test your solution and it's not quite working: http://www.joycefdn.org/grantsDB I tried to convert the HTML to the select boxes that I need and it doesn't work when I apply the multiple select option plugin to the selects, in that case, the secondary select box does not fill in at all.  Also, I need the values of the select boxes to still be the titles of the categories because that's how the filtering works.  Any help would be greatly appreciated!!  
  > **username_0**: This is how I tried to edit it: <div ng-app="myApp" ng-controller="filterController"> <select id="program" name="program" multiple="multiple"> <option value="" selected>Program</option> <option ng-repeat="filter in parents" ng-click="addFilter(filter.id);" value="{[{filter.id}]}">{[{ filter.title }]}</option> </select> <select id="focusArea" name="focusArea" multiple="multiple"> <option class="" ng-repeat="child in children | filter: filterBySelectedParent"><span data-name="selectItemfocusArea" value="{[{ child.id }]}">{[{ child.title }]}</span> </option> </select> </div>  
  > **username_0**: I'm so sorry, I'm really new to Stack Exchange, I think I forgot to tag you... @username_1-username_1  
  > **username_1**: It actually works but you hide the real select with all functionality and show the useless jquery select with no functionality instead. By the way: best practice would be to create all your filters that way, so you have multiple Arrays with all filters, in order to display the entries by your arrays. If you want I could do it for you. It makes everything much easier and smoother. I tried to accomplish such a thing with jquery in the past too. But it becomes a pain sooner or later  
  > **username_1**: I think that is the same reason why your previous code did not work either. Your code may have been correct but you did not activate your functions for the jquery filter, only for you own but you hide it and never use it  
  > **username_0**: I'm not sure what you mean, do you mean I could use Angular to make the multi-select options in the select boxes instead of the jQuery plugin? The other filters don't really need to cascade on each other like the Program and Focus Area ones so I'm only using jQuery to make them multi-selects, also for your code, is there a way to make them cascade on each other without using "value" since that's how the filters display the entries?  Thanks!!  
  > **username_1**: It's not that you could to it, you should use only angular or another jquery plugin, since the one you use is not able to sync properly. The value attribute does not matter, you can leave it if you don't want to use the real strength of the script and of course if you don't want to avoid trouble sooner or later because of jquery. As soon as you have more entries and reach a certain limit or if you want to include more filters it is going to be mess  
  > **username_0**: ohhh, I see what you mean.  I see it working in my test page now, I just have to reconcile how it filters the entries now and style it.  Does it seem right to you??  Thanks!  
  > **username_1**: That's one way you could do it  
  
  ---
  
  