2

I'm trying to get AngularJS to do the following by reading in a JSON file and printing out the data into a table (you can ignore the CSS, it's just there so that the result is formatted correctly):

#page {
  width: 1200px;
  margin: 30px auto;
}
.job-applicants {
  width: 100%;
}
.job-name {
  text-align: center;
}
.applicant-name {
  width: 150px;
}

html{color:#000;background:#FFF}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit}input,textarea,select{*font-size:100%}legend{color:#000}#yui3-css-stamp.cssreset{display:none}

h1{font-size:138.5%}h2{font-size:123.1%}h3{font-size:108%}h1,h2,h3{margin:1em 0}h1,h2,h3,h4,h5,h6,strong{font-weight:bold}abbr,acronym{border-bottom:1px dotted #000;cursor:help}em{font-style:italic}blockquote,ul,ol,dl{margin:1em}ol,ul,dl{margin-left:2em}ol{list-style:decimal outside}ul{list-style:disc outside}dl dd{margin-left:1em}th,td{border:1px solid #000;padding:.5em}th{font-weight:bold;text-align:center}caption{margin-bottom:.5em;text-align:center}p,fieldset,table,pre{margin-bottom:1em}input[type=text],input[type=password],textarea{width:12.25em;*width:11.9em}#yui3-css-stamp.cssbase{display:none}
<table class="job-applicants">
  <thead>
    <tr>
      <th>Job</th>
      <th>Applicant Name</th>
      <th>Email Address</th>
      <th>Website</th>
      <th>Skills</th>
      <th>Cover Letter Paragraph</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td rowspan="10" class="job-name">Job 1</td>
      <td rowspan="3" class="applicant-name">Person's Name</td>
      <td rowspan="3"><a href="mailto:person@email.com">person@email.com</a></td>
      <td rowspan="3"><a href="http://website.com">website.com</a></td>
      <td>Skill</td>
      <td rowspan="3">Some trivial text</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td rowspan="2" class="applicant-name">Person's Name</td>
      <td rowspan="2"><a href="mailto:person@email.com">person@email.com</a></td>
      <td rowspan="2">---</td>
      <td>Skill</td>
      <td rowspan="2">Some trivial text</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td rowspan="2" class="applicant-name">Person's Name</td>
      <td rowspan="2"><a href="mailto:person@email.com">person@email.com</a></td>
      <td rowspan="2"><a href="http://website.com">website.com</a></td>
      <td>Skill</td>
      <td rowspan="2">Some trivial text</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td rowspan="3" class="applicant-name">Person's Name</td>
      <td rowspan="3"><a href="mailto:person@email.com">person@email.com</a></td>
      <td rowspan="3"><a href="http://website.com">website.com</a></td>
      <td>Skill</td>
      <td rowspan="3">Some trivial text</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>


    <tr>
      <td rowspan="12" class="job-name">Job 2</td>
      <td rowspan="3" class="applicant-name">Person's Name</td>
      <td rowspan="3"><a href="mailto:person@email.com">person@email.com</a></td>
      <td rowspan="3"><a href="http://website.com">website.com</a></td>
      <td>Skill</td>
      <td rowspan="3">Some trivial text</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td rowspan="3" class="applicant-name">Person's Name</td>
      <td rowspan="3"><a href="mailto:person@email.com">person@email.com</a></td>
      <td rowspan="3"><a href="http://website.com">website.com</a></td>
      <td>Skill</td>
      <td rowspan="3">Some trivial text</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td rowspan="3" class="applicant-name">Person's Name</td>
      <td rowspan="3"><a href="mailto:person@email.com">person@email.com</a></td>
      <td rowspan="3"><a href="http://website.com">website.com</a></td>
      <td>Skill</td>
      <td rowspan="3">Some trivial text</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td rowspan="3" class="applicant-name">Person's Name</td>
      <td rowspan="3"><a href="mailto:person@email.com">person@email.com</a></td>
      <td rowspan="3"><a href="http://website.com">website.com</a></td>
      <td>Skill</td>
      <td rowspan="3">Some trivial text</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>
    <tr>
      <td>Skill</td>
    </tr>

  </tbody>

  <tfoot>
    <tr>
      <td colspan="6">8 Applicants, 11 Unique Skills</td>
    </tr>
  </tfoot>
</table>

The JSON file I'm reading in looks like this:

{
    "applicants": [
        {
            "id": 1,
            "name": "Person's Name",
            "email": "person@email.com",
            "website": "website.com",
            "cover_letter": "Some trivial text",
            "job_id": 1,
            "skills": ["Skill", "Skill", "Skill"]
        },
        ...
    ],
    "jobs": [
        {
            "id": 1,
            "name": "Job 1"
        },
        {
            "id": 2,
            "name": "Job 2"
        }
        ...
    ]
}

I am suuuper close, there's just one problem. I can only get the first skill to show up. I understand that I have to make the rows that are not skills span by the amount of skills that applicant has. But the problem is, I have to reference any additional skill AFTER the applicant <tr> ng-repeat.

In other words, I have to create a new row for each skill placed AFTER the row containing the applicant's other information, in order to get it to show up inline with that row. But since this would be out of the scope of the ng-repeat="app in applicants", I can't think of a way to do this.

I've tried a lot of different things, but the closest I've managed to get is the following:

<table class="job-applicants">
  <thead>
    <tr>
      <th ng-repeat="heading in headings">{{ heading }}</th>
    </tr>
  </thead>

  <tbody ng-repeat="job in jobs">
    <tr>
      <td rowspan="{{ filtered.length+1 }}" class="job-name">{{ job.name }}</td>
    </tr>
    <tr id="applicant-{{ app.id }}" class="applicant" ng-repeat="app in applicants | filter : {job_id: job.id} as filtered">
      <td class="applicant-name">{{ app.name }}</td>
      <td rowspan="app.skills.length+1"><a href="mailto:{{ app.email }}">{{ app.email }}</a></td>
      <td rowspan="app.skills.length+1"><a href="{{ app.website }}">{{ app.website }}</a></td>
      <td></td>
      <td>{{ app.skills[0] }}</td>
      <td rowspan="app.skills.length+1">{{ app.cover_letter }}</td>
    </tr>
  </tbody>

  <tfoot>
    <tr>
      <td colspan="{{ headings.length }}">{{ applicants.length }} Applicants, {{ unique_skills.length }} Unique Skills</td>
    </tr>
  </tfoot>
</table>

Table Screenshot

I know this is possible with jQuery, but I need to use AngularJS, and as per this post, we should not mix the two.

MattR
  • 127
  • 2
  • 11
  • To boil this down, is the problem that you need to be able to access `filtered.length + 1`, but in the `` that is above the `ng-repeat` where `filtered` is created? Sorry if that's an obvious question...Monday afternoon brain here. – Lex Aug 27 '18 at 22:26
  • No, not quite. `filtered` works as intended. What I need to do is add a new row for each skill that a person has (found in the JSON file in `applicants[0].skills`, for instance). Each of these skill rows needs to be placed in the HTML after the ` – MattR Aug 27 '18 at 22:42
  • Gotcha. One sort of hacky way to do this is to nest a table in the `` and throw an `ng-repeat` on the `app.skills` collection. – Lex Aug 27 '18 at 22:58
  • Yeah, I thought of that, but that won't work for me unfortunately :/ – MattR Aug 27 '18 at 23:37

0 Answers0