Q:

Appending elements to div depending on JSON data

I have a local JSON file that contains "Course Categories" and "Titles". Each Category has many Titles and each Title corresponds with one Category.
I've created three separate divs: "Top Courses", "Newly-Added Courses", and finally "Top Courses", and the divs are populated by Categories. Clicking on a Category opens a modal that shows the Category name a second time and the correct Category description. It's supposed to show all of the Titles that are associated with that Category, e.g. Clicking on the Category "Animals" should show "Chinchilla", "Axolotl", "Flea", etc.
I want to make it so that clicking on a Category only shows the Titles that are associated with that Category. I am seeing Titles in the modal---however I'm only seeing one Title from each Category. Based on the order of the Titles I believe they're coming from the "All Courses" Category. I can't say if it's this way for sure, but when I click on a Category that is not under "All" I see the same thing.
JS Snippet:
var testjson = {
  "d": {
    "results": [{
      "Title": "Aardvark",
      "Category": "Animals",
      "Description": "a-desc",
      "TopTrainingCourse": false,
      "ID": 1,
      "Modified": "2019-03-05T20:13:46Z",
      "Created": "2019-03-05T20:13:36Z"
    }, {
      "Title": "Red Panda",
      "Category": "Animals",
      "Description": "a-desc",
      "TopTrainingCourse": true,
      "ID": 10,
      "Modified": "2019-03-06T21:08:25Z",
      "Created": "2019-03-06T21:08:25Z"
    }, {
      "Title": "Tennis",
      "Category": "Sports",
      "Description": "s-desc",
      "TopTrainingCourse": true,
      "ID": 11,
      "Modified": "2019-03-06T21:08:35Z",
      "Created": "2019-03-06T21:08:35Z"
    }]
  }
}

///// From topCourses.js /////

import testjson from './test.json';

export default class {
    constructor() {
    }

    loadTopCourses() {
        let topCrs = testjson.d.results
            .filter(x => x.TopTrainingCourse === true)
            .filter((el, idx, self) => { // no duplicates
                return (idx === self.map(el => el.Category).indexOf(el.Category))
            })
            .map(x => {
                return {
                    "Category": x.Category,
                    "Description": x.Description,
                    "Title": x.Title
                }
            });

        let curIndex = 0;
        $.each(topCrs, function(idx, val) {
            curIndex++; // this line must be here---if it's moved down the 1st col doesn't show
            let targetDiv = $("div.top-training-div > div[col='" + curIndex + "']");

            let modalTrigger = $('<div />', {
                'class': 'categoryName',
                'data-category': val.Category,
                'data-target': '#modal-id',
                'data-toggle': 'modal',
                'text': val.Category
            });

            targetDiv.append(modalTrigger);

            if(curIndex == 4) {
                curIndex = 0;
            }
        })

        $('.categoryName').click(function(val) {
            let cat = $(this).data('category');
            $('.modal-title').text(cat);

            // console.log($(this).data('category'));

            $(".category-desc").empty();
            var noDupeDescs = topCrs.filter(function(val) {
                return val.Category == this;
            }, cat)
            .map(function(val) {
                return val.Description;
            });

            $.each(noDupeDescs, function(idx, val) {
                $(".category-desc").append(val + "<br />")
            })

            ///

            $(".training-titles").empty();
            let titles = topCrs;

        $.each(titles, function(idx, val) { // ----- thought something like this could help
            for (var i = 0; i = titles.length; i++) {
                if $(titles.contains(val.Title)
                $(".training-titles").append("<li>" + val.Title + "</li>")
            }
        }
      });

    } // ------------------ loadTopCourses

}

Modal:
<div class="modal fade" id="modal-id" role="dialog" >
     <div class="modal-backdrop">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel"></h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">CLOSE</span> <!-- &times; -->
            </button>
          </div>
          <div class="modal-body">
            <div class="category-desc"></div>
            <ul class="training-titles"></ul>
          </div>
        </div>
      </div>
     </div> <!-- modal-backdrop -->
    </div> <!-- modal fade -->

newCourses.js fiddle
allCourses.js fiddle

A:

looks like your mistake is that you iterate to topCrs to show the titles, but the topCrs is a small array that already filtered and holding only one title of each category, there for you will always see only one title from each category.
what you need to do is to iterate again on all the titles again from testjson.d.results, and to filter by the category that was clicked.
var titles = testjson.d.results.filter(x => x.Category === cat);

and then to iterate this title filtered by category like that
$.each(titles, function(idx, val) {
    $(".training-titles").append("<li>" + val.Title + "</li>")
}

