Parsing User JSON - ldco2016/microurb_web_framework GitHub Wiki
import { User } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
  models: User[] = [];
  events: Eventing = new Eventing();
  get on() {
    return this.events.on;
  }
  get trigger() {
    return this.events.trigger;
  }
}
I am going to ensure that my class Collection has a fetch() method that will make a request to /users and retrieve all the different users that I have:
I first implemented this with Axios just so I could see what information I was going to get back from JSON Server. I needed to parse this stuff and turn each object that I get back into an instance of a user. To do so, inside the index.ts file I completed the following:
import axios from "axios";
axios.get("http://localhost:3000/users");
I then chained on a .then() statement that got called with some response object that is of type AxiosResponse like so:
import axios, { AxiosResponse } from "axios";
axios.get("http://localhost:3000/users").then((response: AxiosResponse) => {
  console.log(response.data);
});

So you can see that when I make a network request over to that endpoint, I get back an array of objects and each object is going to have an id a name and an age.
So the object i get back essentially conforms to my UserProps interface. So I want to take objects that conform to that interface and use them to create different instances of users. So I just need to loop over the response, take each one of these objects and throw them into buildUser.
Back in my Collection.ts file, I now need to use Axios and probably make reference to the UserProps interface inside of here:
import axios from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
  models: User[] = [];
  events: Eventing = new Eventing();
  get on() {
    return this.events.on;
  }
  get trigger() {
    return this.events.trigger;
  }
  fetch(): void {
    axios.get();
  }
}
The argument to get() is going to be the url that I want to make my request to. I could hardcode it in, but I will eventually have to dynamically specify that root url on the fly. So whenever we create an instance of class Collection I should have to pass in the root url that I want to make this request to and then I can reuse it for other types of records as well. So I will add in a constructor() and use the shortened syntax to receive a public variable called rootUrl with type of string like so:
import axios from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
  models: User[] = [];
  events: Eventing = new Eventing();
  constructor(public rootUrl: string) {}
  get on() {
    return this.events.on;
  }
  get trigger() {
    return this.events.trigger;
  }
  fetch(): void {
    axios.get(this.rootUrl);
  }
}
And then I was able to reference that rootUrl inside the fetch() method axios request with this.rootUrl.
So now I can chain on a .then() statement, receive all that JSON data and turn each of those objects into an instance of a user like so:
import axios, { AxiosResponse } from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
  models: User[] = [];
  events: Eventing = new Eventing();
  constructor(public rootUrl: string) {}
  get on() {
    return this.events.on;
  }
  get trigger() {
    return this.events.trigger;
  }
  fetch(): void {
    axios.get(this.rootUrl).then((response: AxiosResponse) => {});
  }
}
Then I have a response.data property inside that .then() statement and I want to run a loop over response.data because that is going to be the array of records that we get back from the JSON Server. I will do a forEach() on this thing and for every object inside there I will turn it into an instance of a user and add it to the models array like so:
import axios, { AxiosResponse } from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
  models: User[] = [];
  events: Eventing = new Eventing();
  constructor(public rootUrl: string) {}
  get on() {
    return this.events.on;
  }
  get trigger() {
    return this.events.trigger;
  }
  fetch(): void {
    axios.get(this.rootUrl).then((response: AxiosResponse) => {
      response.data.forEach((value: UserProps) => {});
    });
  }
}
So I will take the value and stick into User.buildUser() which will create a user and then push it into the models array as mentioned above like so:
import axios, { AxiosResponse } from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
  models: User[] = [];
  events: Eventing = new Eventing();
  constructor(public rootUrl: string) {}
  get on() {
    return this.events.on;
  }
  get trigger() {
    return this.events.trigger;
  }
  fetch(): void {
    axios.get(this.rootUrl).then((response: AxiosResponse) => {
      response.data.forEach((value: UserProps) => {
        const user = User.buildUser(value);
        this.models.push(user);
      });
    });
  }
}
Now I can test this out easily inside of index.ts like so:
import { Collection } from "./models/Collection";
I will create a new instance of a Collection like so:
import { Collection } from "./models/Collection";
const collection = new Collection("http://localhost:3000/users");
collection.fetch();
IMPORTANT NOTE:
Right now I am not returning a Promise from collection.fetch(). I am going to rely upon the Eventing system to know whether or not an event has changed.
So after running the entire forEach() I will trigger a change event like so:
import axios, { AxiosResponse } from "axios";
import { User, UserProps } from "./User";
import { Eventing } from "./Eventing";
export class Collection {
  models: User[] = [];
  events: Eventing = new Eventing();
  constructor(public rootUrl: string) {}
  get on() {
    return this.events.on;
  }
  get trigger() {
    return this.events.trigger;
  }
  fetch(): void {
    axios.get(this.rootUrl).then((response: AxiosResponse) => {
      response.data.forEach((value: UserProps) => {
        const user = User.buildUser(value);
        this.models.push(user);
      });
      this.trigger("change");
    });
  }
}
Then back inside of index.ts, to get a notification of when this has been completed, I can add on an event handler like so:
import { Collection } from "./models/Collection";
const collection = new Collection("http://localhost:3000/users");
collection.on("change", () => {
  console.log(collection);
});
collection.fetch();
I console logged the entire collection and headed to the browser.

I should be able to expand it, open up models and see all those different users:

The users that I see in here are all the users reflected in my users.db file. The only problem now is that my users collection only works with users:
export class Collection {
  models: User[] = [];
  events: Eventing = new Eventing();
...
So I am going to have to turn this into a generic class to make it reusable.