0

I have a component called JobList which currently gets a JSON object from a file (will later be a web server) and displays a list of jobs on the page. I want the list to be sorted by a property in each job called Status.Order.

To do this I am using a Pipe which I have setup as in the below code.

Problem: If I don't use the pipe, the jobs get display in the file order but if I use the pipe then no content is shown at all. Am I doing something wrong in the Pipe code?

If I add a console.log in the tranform function within the Pipe code then i can see that an empty array is being passed in. I would expect to see a second call when the data is added but get nothing.

export class JoblistComponent implements OnInit {

  private openJobs = new Array();
  private activeJobs = new Array();

  constructor() { }

  ngOnInit() {

    const openJobs = this.openJobs;
    const activeJobs = this.openJobs;

    $.getJSON('assets/data/jobs.json', function (json: Array<any>) {

      for (const job of json) {
        if (job.Status.Section === 'Active') {
          activeJobs.push(job);
        } else {
          openJobs.push(job);
        }
      }
    });
  }
}

To render the content I am using this HTML.

 <div class="job" *ngFor="let job of openJobs | orderByStatus" [ngStyle]="{ 'border-left-color': job.Group.Colour }">
        <span class="title">12 Example Street, {{job.Location.Name}}</span>
        <span>{{ job.Name }}</span>
        <span>{{ job.Type.Name }}</span>
      </div>

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'orderByStatus'
})
export class OrderByStatusPipe implements PipeTransform {

  transform(array: Array<any>, args?: any): any {

    array.sort((a: any, b: any) => {
      if (a.Status.Order < b.Status.Order) {
        return -1;
      } else if (a.Status.Order > b.Status.Order) {
        return 1;
      } else {
        return 0;
      }
    });

    return array;
  }

}

Example Job

{
        "_id": "597b5a700c1d413f20c4d67a",
        "Name": "JOB-20170628-029",
        "Created": "2017-07-28T15:38:24.619Z",
        "Group": {
            "_id": "5919e2f96b1822dc0daf94d5",
            "Name": "Priority 3",
            "Colour": "#1bb934",
            "Order": 3,
            "Class": "priority3"
        },
        "Type": {
            "Name": "Type 2",
            "_id": "597b5a680c1d413f20c4b5fc"
        },
        "Status": {
            "Order": 2,
            "Section": "Active"
        }
        "Description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sed lacus sit amet enim congue molestie. \nAenean pharetra tincidunt ligula a luctus. In vel interdum lacus. Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
        "Location": {
            "Postcode": "RG31 6PL",
            "Name": "RG31 6PL"
        }
    }

1
  • Did you have some kind of error in your web console? I implemented the same thing in my projects it should be working. Though the only difference I could see is I did not use new Array() instead I use the generic one [] Commented Sep 1, 2017 at 10:45

2 Answers 2

1

You try to access async call in your template. If it load to quick it not load the object at all.

In your html you try:

    <span class="title">12 Example Street, {{job.Location.Name}}</span>
    <span>{{ job.Name }}</span>
    <span>{{ job.Type.Name }}</span>

Instead it should be {{job?.Location?.Name}} {{job?.Name}} in Angular2 or {{job.Location.Name | async}} Angular4

Went on a break

Update

Try:

If not work put console.log(a) and console.log(b)

if (a.Status.Order < b.Status.Order) {
        return -1;
      } 
if (a.Status.Order > b.Status.Order) {
        return 1;
      } 
        return 0;
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. That solves the blank issue but the objects are still not being sorted. Thoughts?
1

Docs: Pipes are by default pure...

Angular executes a pure pipe only when it detects a pure change to the input value. A pure change is either a change to a primitive input value (String, Number, Boolean, Symbol) or a changed object reference (Date, Array, Function, Object).

Here we have no change in object reference, you are just pushing values to the array. You can solve this by marking the pipe as impure:

@Pipe({
  name: 'orderByStatus'
  pure: false // here
})

But I really suggest you would want to reconsider that, performancewise, as the docs continue saying...

Angular executes an impure pipe during every component change detection cycle. An impure pipe is called often, as often as every keystroke or mouse-move.

With that concern in mind, implement an impure pipe with great care. An expensive, long-running pipe could destroy the user experience.

This is the main reason for not having an orderBy pipe in Angular, contrary to AngularJS.

I would suggest you implement the sorting and ordering in component after you have received your data :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.