0

I am building an Ionic2 app for which i created a WebAPI to fetch the data from db. I am calling the API and fetching data but when i do see in console ,all i see is undefined.
TS

setCountyValues(sState) {
    // this.selectedCounties = this.counties.filter(county => county.state_id == sState.id)
    this.zipcode.getCounties(sState)
      .subscribe(data => {
        this.selectedCounties = data;
        
      })
  }
  
  
  DataFetch() {

    this.sState = this.documentDetails[0].DocumentTypeDetails.State;

    this.stateObj = this.states.find(state => state.StateAbbr == this.sState);
    console.log(this.stateObj); //working fine now
    this.sState = this.stateObj.StateName;

    this.setCountyValues(this.stateObj.StateAbbr);

    this.sCounty = this.documentDetails[0].DocumentTypeDetails.County
    console.log(this.selectedCounties); //giving undefined
    this.countyObj = this.selectedCounties.find(county => county.RecName == this.sCounty)
    this.sCounty = this.countyObj.RecName;
    console.log(this.sCounty);
  }
  
   Autofill() {
    this.zipcode.getDocDetails()
      .subscribe(data => {
        this.documentDetails = data;
        this.DataFetch();
      })
  }
  
  

HTML

ion-item>
    <ion-label>State</ion-label>
    <ion-select (ionChange)="setCountyValues(sState.StateAbbr)" [(ngModel)]="sState" >
      <ion-option [value]="sState" *ngFor="let sState of states" [selected]="sState">{{sState.StateName}}</ion-option>
    </ion-select>
  </ion-item>

  
  <ion-item >
    <ion-label>Counties</ion-label>
    <ion-select (ionChange)="setCityValues(sCounty.PageRec)" [(ngModel)]="sCounty">
      <ion-option [value]="sCounty" *ngFor="let sCounty of selectedCounties" [selected]="sCounty">{{sCounty.RecName}}</ion-option>
    </ion-select>
  </ion-item>
  <ion-item *ngIf="citylength>0">
    <ion-label>Cities</ion-label>
    <ion-select [(ngModel)]="sCity">
      <ion-option [value]="sCity" *ngFor="let sCity of selectedCities" [selected]="sCity">{{sCity.name}}</ion-option>
    </ion-select>
  </ion-item>
  <ion-item *ngIf="selectedCounties">
    <button ion-button round color="primary" (click)="clear()">Clear</button>
    <button ion-button round color="primary" (click)="goToOfficeDetail()">Office Detail Page</button>
  </ion-item>

JSON

"DocumentTypeDetails": {
            "PageRec": "AL005",
            "State": "AL",
            "County": "Autauga County",
            "CityTown": null,
            "Zip": null,
            "ShowRecordingInfo": "true",
            "Deed": {
                "Checked": "True",
                "Pages": "1",
                "ConsiderationAmount": "150000"
            },
            "MortgageDeed": {
                "Checked": "False",
                "Pages": null,
                "NewDebtAmount": null
            },
            "MortgageRefi": {
                "Checked": "False",
                "Pages": null,
                "NewDebtAmount": null,
                "OriginalDebt": null,
                "UnpaidDebt": null
            },
            "Assignment": {
                "Checked": "False",
                "Pages": null,
                "Assignments": null
            },
            "ReleaseSatisfaction": {
                "Checked": "False",
                "Pages": null,
                "ReleasesSatisfactions": null
            },
            "Questions": {
                "Question": {
                    "Number": "Q4",
                    "Category": "Deed",
                    "Type": "bool",
                    "QuestionText": "Are the deed and mortgage being recorded at the same time?",
                    "Answer": "1"
                }
            }
        }

The error what i am getting is "Cannot read property 'find' of undefined" when i a trying to populate countObj. When i am calling the setCountyValues method then selectedCounties should get populated now i know that is async data and all that but how do i populate it?

priyank bhardwaj
  • 119
  • 2
  • 15
  • 2
    Move the console log and `this.DataFill()` (if you need it to be executed after `documentDetails` has been populated) inside the callback (`subscribe`) and read (especially) the accepted answer in the duplicate. And welcome to the asynchronous world :) – AT82 Jun 28 '17 at 10:20
  • Ya tried that too but a lot of issues are coming after that...i will probably put up a more detailed one after a while – priyank bhardwaj Jun 28 '17 at 10:25
  • @AJT_82..i Have edited the post ..And i am really confused as i can't find a bypass to it. – priyank bhardwaj Jun 28 '17 at 12:27
  • The same problem persists, did you read the question and answer of the duplicate? You **still** have the same problem: Take a look at this line:`this.setCountyValues(this.stateObj.StateAbbr)`; and the console log:`console.log(this.selectedCounties); //giving undefined` and read the accepted answer again in the duplicate. – AT82 Jun 28 '17 at 12:45
  • @AJT_82 i did read the solution of the post and i do understand the nature of the call but my problem is i do need to populate selectedCounties value at a certain point of time..Now what do i do in order to achieve it...because then countyObj will give an error. – priyank bhardwaj Jun 28 '17 at 12:52
  • Well tell my why the console log is undefined? :) If you really understood this, you'd know what to do based on the duplicate question :) I'm not trying to be an asshole here, but I'd like you to realize yourself what is going on in the code and the asynchronous execution! :) – AT82 Jun 28 '17 at 12:57
  • @AJT_82..hehe i do know that buddy and i highly appreciate that..i am not blaming you...i do get that javascript is executing the console.log before even its getting the response...so what do i do now? should i make it wait....i dont care about priting the data....focus is on populating selected counties ...when should i call all of it....I would be using the setCountyValues method at several places so cannot just do all the stuff for this scenerio – priyank bhardwaj Jun 28 '17 at 13:42
  • Yes, that is correct, console log is executed first (and rest of the code under it). So what did you do in the original issue, you moved the console log and `this.dataFill()` inside the callback, so what do you think you should do now? :P Well this seems to become a chaining hell, so perhaps consider using `flatMap` or something so you get rid of the nested subscriptions, this might help: https://stackoverflow.com/questions/42626536/angular-2-chaining-http-requests – AT82 Jun 28 '17 at 13:48
  • @AJT_82 ok..but its kind of interdependency of a bunch of requests....here i do have only one request to take care of now – priyank bhardwaj Jun 28 '17 at 14:05
  • @AJT_82..tried flatMap but seems like my service call method isnt dependent on other – priyank bhardwaj Jun 29 '17 at 08:01
  • Well as said in your original problem, you need to move everything inside the callback so that it won't be undefined, so just do the same now. – AT82 Jun 29 '17 at 08:03
  • But the same thing what i have to move now isn't applicable for the other scenarios...There i do not need that code to be executed – priyank bhardwaj Jun 29 '17 at 08:05
  • Then I suggest you flip it around and do something like this instead: https://stackoverflow.com/a/37867462/6294072 :) – AT82 Jun 29 '17 at 08:09
  • hmm...seems interesting..i will give it a try – priyank bhardwaj Jun 29 '17 at 08:15
  • Yes, please do. Now when understanding the big picture and what's going on in your code I think that something like that is the smartest solution. Good luck and happy coding! :) – AT82 Jun 29 '17 at 08:18

1 Answers1

0

It's because you are getting the data asynchronously, which means that your code: console.log(this.documentDetails) gets executed first before actually getting the data. If you really want to print it to the console, put it inside the callback function:

Autofill() {
  this.zipcode.getDocDetails()
    .subscribe(data => {
      this.documentDetails = data;       
      console.log(this.documentDetails);
    });
  this.DataFill();
}
Rax Weber
  • 3,730
  • 19
  • 30
  • 1
    IMHO, there's no need to add an answer to this question, since a very good answer can be found in the [post mentioned in the comments](https://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular2). Instead of adding a new answer, you should vote to close this one since it's a duplicate. – sebaferreras Jun 28 '17 at 10:22
  • Yeah I know. It's just that some people like OP seem to not get a good grasp of the detailed answers, that's why I just put it in a simple manner. Also, I don't think his problem isn't really Angular-specific, it shows that he still doesn't understand how JS works. – Rax Weber Jun 28 '17 at 10:24
  • 1
    Agree, but we're not here to do things for someone else, we're here to help people learning why and how to do things :) – sebaferreras Jun 28 '17 at 10:26
  • 1
    I see your point. Anyway, I'm just answering only a few questions that shouldn't necessarily be answered, because the answer is simple, and I like to also keep myself sharp by sharing my knowledge. :) – Rax Weber Jun 28 '17 at 10:30
  • 2
    @RaxWeber, yes, duplicate questions shouldn't be answered, unless you feel it's **not** a duplicate ;) https://meta.stackexchange.com/a/10844 – AT82 Jun 28 '17 at 10:30
  • @RaxWeber here i have edited one more portion – priyank bhardwaj Jun 28 '17 at 12:31