Get item by id IONIC

I have two tables
CAUSES
id, name

OCCURRENCES
id, name, cause_id

in my causes.ts I have:

  getData() {
    this.service.getCauses()
      .subscribe(
        data => this.causes = data.causas,
        err => console.log(err)
      );
  }

  navigateTo(cause_id) {
    this.navCtrl.push(OccurrencesComponent, {
      cause_id: cause_id
    });
  }

In my Occurrences.ts I have

  constructor(public navParams: NavParams, public navCtrl: NavController, public service: ServiceProvider) {
    this.cause_id = navParams.get('cause_id');
    this.initializeOccurrences();
  }

  initializeOccurrences() {
    this.service.getOccurrences()
        .subscribe(
          data => this.occurrences = data,
          e => console.log(e)
        );
        // this.teste();
  }

I would Like to create another method test and get the occurrences where occurrences.cause_id = causas.id

  teste() {
    this.occurrenceList = [];
      console.log(this.cause_id);
      for(let o of this.occurrences) {
        console.log('passou');
      }
  }

any idea ?

Is there something missing from the code you posted? You say you have two tables - I assume you are talking about some relational database? - that I don’t see anything about in the code. Also, what is this.service?

So, in my service-provider I have

  getHeaders(): any {
    let headers = new Headers({ 'Authorization': 'Bearer ' + window.localStorage.getItem('token') });
    let options = new RequestOptions({ headers: headers });
    return options;
  }

  getCauses() {
    return this.http.get(this.api+'causes' , this.getHeaders()).map( res => res.json());
  }

  getOccurrences() {
    return this.http.get(this.api+'occurrences', this.getHeaders()).map( res => res.json());
  }

the causes data come from there

Ok, so you get the data from a remote webservice / API.

You either have to develop a endpoint that returns what you want to show, or see how you can transform the data you already get into the format you require.

What’s stopping you from doing that? What have you tried and what’s the problem you are facing?

Given their is a relation between the two tables (cause_id in OCCURENCES being an FK) and you are sending in a value through the argument cause_id in the navigateTo method that matches an actual causas.id value, it should be as simple as populating the occurencesList with the filtered objects by using a condition like this if(o.cause_id == this.cause_id)

By the way as @Sujan12 mentioned, it might be better to get the filtered list from the back end webservice itself.

1 Like

when I use the method test() {} to show the following error

  test() {
    this.occurrenceList = [];
      console.log(this.cause_id);
      for(let o of this.occurrences) {
        console.log('passou');
      }
  }

ERROR Error: Uncaught (in promise): TypeError: Cannot read property ‘length’ of undefined
TypeError: Cannot read property ‘length’ of undefined

I want push occurrences to inside this.occurrenceList

That code snippet doesn’t make any sense. Show where it lives and tell us in plain English what you think it should do. Also, the error message is without any context. What is triggering it?
Please also include you ionic info output for good measure.

I’ll go change the example, image this example to be a country states and cities, I want to show cities based in states ID

export class CitiesComponent {

   state_id: any[]; 
   cities: any[];

   constructor(public navParams: NavParams, public navCtrl: NavController, public service: ServiceProvider) {
    this.state_id = navParams.get('state_id');
    this.initializeCities();
  }

  initializeCities() {
    this.service.getCities()
        .subscribe(
          data => this.cities = data,
          e => console.log(e)
        );
  }
}

cities.html

<ion-searchbar (ionInput)="getCities($event)" [debounce]="500" placeholder="Search Cities"></ion-searchbar>
  <ion-list>
    <a *ngFor="let citie of cities" (click)="navigateTo(city)" style="text-decoration: none;">
      <ion-item >
        <h2 style="font-weight: 900"><strong>{{ city.id }}</strong></h2>
        {{ city.name }}
        <ion-icon name="arrow-forward" item-end></ion-icon>
      </ion-item>
    </a>
  </ion-list>

this code show me all cities im my html ok, but I want to show cities based in state_id,
Excuse me if i did not know how to explain

state_id = washington
cities
Seattle
Olympia
Spokane
Tacoma
Bellevue
Redmond
Aberdeen

You could write a filterCities method that is executed behind a button. It takes this.cities, loops trough it and deletes all the cities that are not in the correct state. Then it writes the result in this.cities again which will update the list with the filtered city list.

(This is very dirty and probably not what you wnat, but implement it, get it to work and then go on to e.g. remove the button, create this list directly in initializeCities etc)

But in my constructor I have um parameter this.state_id = navParams.get(‘state_id’);
This already brings the other component’s state, I get state_id

My StatesComponent.ts

export class StateComponent {
  states: any;

    constructor(public navCtrl: NavController, public navParams: NavParams, public service: ServiceProvider, public alertCtrl: AlertController) {
    this.getStates();
  }

  getStates() {
    this.service.getStates()
      .subscribe(
        data => this.states = data, 
        err => console.log(err)
      );
  }
  
    navigateTo(state_id) {
    this.navCtrl.push(CitiesComponent, {
      state_id: state_id
    });
  }
}

my States.html

<ion-col col-6 col-sm-9 col-md-6 col-lg-4 col-xl-3 id="causes" *ngFor="let state of states">
   <a (click)="navigateTo(state.id)">
     <h5><strong>States</strong></h5>
     <h4><strong>{{ state.name }}</strong></h4>
   </a>
 </ion-col>

Always get in the habit of initializing all array and object properties, even if it is just to [] and {}. This will help you avoid bugs like this. Also, please give everything proper types instead of abusing any.

I did it, I pass how to object in parameters

  causes: any[];
  occurrences: any[];

    constructor(public navCtrl: NavController, public navParams: NavParams, public service: ServiceProvider, public alertCtrl: AlertController) {
    this.getData();
    this.initializeCities();
  }

    getStates() {
    this.service.getStates()
      .subscribe(
        data => this.states = data,
        err => console.log(err)
      );
  }

getCities() {
    this.service.getCities()
                .subscribe(
                  data => this.cities = data,
                  e => console.log(e)
        );
  }


  navigateTo(state_id) {
    this.navCtrl.push(CitiesComponent, {
      state_id: state_id,
      cities: this.cities
    });
  }

in my citiescomponents.ts

  constructor(public navParams: NavParams, public navCtrl: NavController, public service: ServiceProvider) {
    this.state_id = navParams.get('state_id');
    this.cities = navParams.get('cities');
    this.getCitiesByIdState();
  }


  getCitiesByIdState() {
    this.cityList = [];
    for(let city of this.cities) {
      if(this.state_id == city.state_id) {
        this.cityList.push(city);
      }else{
        console.log('Geral');
      }
    }
  }

so, I did it to show cities based state_id in my html, thanks!

1 Like

I don’t think the sort of filtering being done in getCitiesByIdState() belongs in a page controller, and I also think slinging the entire list of all cities around via NavParams is rather inefficient.

I would move all of that logic into the service provider, and pass only the state id in NavParams. It can also be written IMHO much more cleanly than the above loop like so:

citiesByState(state: string): string[] {
  return this.allCities.filter(city => city.state_id === state);
}

If this becomes a performance bottleneck, it would also be feasible to presort all cities into a map indexed by state, which would eliminate the need to loop through all cities more than once at startup (assuming they don’t change while the app is running).

I’ll go trying implement your method and tomorrow a feedback friend