0

I'm trying to display the information I receive from a Web API but I think I'm missing something in my component.

The call in the service work (I receive a code 200 with all the Application) List of the application

But then, I just want to display them in the console and it doesn't fill the table.

ngOnInit(){
        this.getApplications();
        console.log(this.applications);
    }


getApplications() {
        this.applications = [];
        this._UCCXCiscoService.getApplications().subscribe(
            res => {
                this.applications = res;
            },
                    error => this.errorMessage = <any>error
        );
    }

    // Model

export interface Application {
    self: string;
    ScriptApplication: ScriptApplication;
    id: string;
    applicationName: string;
    type: string;
    description: string;
    maxsession: number;
    enabled: string;
}

export interface ScriptApplication {
    script: string;
    scriptParams: ScriptParam[];
}

export interface ScriptParam {
    name: string;
    value: string;
    type: string;
}

export interface RootObject {
    type: string;
    application: Application[];
}

My model is good, I'm pretty sure of that. I Think it's the method getApplications() that's wrong, but can't find why...

Thanks in advance for your help,

Florian

EDIT 1 : Code of getApplications() in my service

@Injectable()
export class UCCXCiscoService {

    public headers:Headers = new Headers({ 'Content-Type': 'application/json' ,'Authorization': 'Basic User + mdp'});

    constructor(private http: Http) {
    }

    getApplications() {
        let options = new RequestOptions({ headers: this.headers });
        return this.http.get('API URL', options)
            .map(data => <Application[]> data.json().application)
            .catch(this.handleError);
    }

Yes this method works and returns me the applications (as shown in the picture List of Applications). I didn't put the api url and the password here for privacy reason ^^'

EDIT 2 : getApplications() of component and the response of the service

EDIT 3 :

<div class="contentPage">
    <div class="pageTitleHeaderContainer">
        <div class="pageTitle">
            <span>Cisco</span>
        </div>
    </div>

    <div class="subContent">
        <message-to-user messageToUser={{messageToUser}} messageLevel={{messageLevel}}></message-to-user>

        <table class="table table-hover table-condensed">
            <th>Id</th>
            <th>Nom</th>

            <tr *ngFor="#application of applications">
                <td>{{application?.id}}</td>
                <td>{{application?.applicationName}}</td>
            </tr>
        </table>
    </div>
</div>
  • make sure that declaration of ``applications`` is outside the ``getApplications`` function – Sameer K May 05 '17 at 09:13
  • Yes it is. public applications:Application[]; – Florian Guebel May 05 '17 at 09:15
  • possible to share plunker link replicating the issue ?? – Sameer K May 05 '17 at 09:33
  • and are you getting data when console log the ``res`` in subscribe ?? – Sameer K May 05 '17 at 09:34
  • I have never used Plunker (still a student) :S I put the console.long just after this.applications = data; and there is nothing shown (not even an empty array) so looks like my method doesn't fill the array... – Florian Guebel May 05 '17 at 09:42
  • Wanted to know if you are getting data from ``_UCCXCiscoService.getApplications()`` ?? Can you share the code of this function ?? – Sameer K May 05 '17 at 09:53
  • return the data from `.map` in `getApplications()` – Sameer K May 05 '17 at 10:01
  • Is not that what I am already doing? – Florian Guebel May 05 '17 at 10:05
  • `.map` function simply transfer the element of observable which you got from ``http.get`` request but does not return any thing. You need to return the data like `.map(data => return data.json().application)`. – Sameer K May 05 '17 at 10:10
  • Promises / Observables are asyncronous, it makes sense that you are getting an empty value. To be 100% sure that you effectively are getting something, do the console.log inside the `.subscribe` of `getApplications()`. If that solves the issue, just return the observable itself or use a getter instead. As far as I can tell anyway it makes perfectly sense, because you are logging the value before it may even be set. – briosheje May 05 '17 at 10:25
  • .map can't return anything. I assume the problem come from getApplications() in my component that's call getApplications() from my service... – Florian Guebel May 05 '17 at 10:28
  • @briosheje I edited my post with a picture to show you – Florian Guebel May 05 '17 at 10:37
  • Possible duplicate of [How do I return the response from an Observable/http/async call in angular2?](http://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular2) – eko May 05 '17 at 10:40
  • @FlorianGuebel: `.map` is overriding the value of the response, it is returning something in that case. Anyway, the preview doesn't say much to me, please try to console.log the output of the HTTP response (in the .map). Remember that everything is **asyncronous** here, so your console.log doesn't make any sense, you need to wrap it in an observable or simply convert the observable in a promise and use `.then`. You are expecting an asyncronous call to be syncronous, which is impossible. – briosheje May 05 '17 at 10:41
  • Also, remember that **interfaces in javascript don't exists in runtime**, so you are not literally casting the values, you are just assuming that **the http response implements your interface**, but you are just **assuming** this, it doesn't mean that it will be such, you should do a strict check if you want to be 100% sure that the response is valid. – briosheje May 05 '17 at 10:44
  • @briosheje I get what you said, I will try to find a solution. – Florian Guebel May 05 '17 at 10:59
  • @echonax I didn't see that post when I did mine :S Will check it – Florian Guebel May 05 '17 at 11:00
  • @FlorianGuebel Hope it helps :-) – eko May 05 '17 at 11:07
  • @FlorianGuebel: It's as easy as this: simply return the Observable and do what you need to do by subscribing to the observable. Alternatively, convert to Observable to a promise (chain .toPromise()) and use .then in your main ;) – briosheje May 05 '17 at 12:58
  • @echonax I come back to you because it still doesn't work. My call to the api works fine, I receive data in xml (that I convert in json) and then, in my component, the array is undefined. I searched all the week-end but impossible to find something... If you need something, I can edit my post. – Florian Guebel May 08 '17 at 12:49
  • @FlorianGuebel are you still trying to console.log it inside ngOnInit? – eko May 08 '17 at 12:52
  • @echonax No, I made the html page to display it, I put the code in my first post. – Florian Guebel May 08 '17 at 12:54
  • @FlorianGuebel are you sure that you read the link I've posted? You haven't even done what Picci wrote in the answer. – eko May 08 '17 at 12:55
  • @echonax Yes, like 10 times to compare my code to it... – Florian Guebel May 08 '17 at 12:57
  • @FlorianGuebel I don't see the console.log inside the subscribe.. – eko May 08 '17 at 12:58
  • @echonax [getApplications()](http://imgur.com/a/lOpOR) – Florian Guebel May 08 '17 at 13:04
  • 1
    @FlorianGuebel are you trolling :-) ? Read your code carefully, the console.log is not inside the subscribe. You need to write it **after** `this.applications = data;` – eko May 08 '17 at 13:07
  • @echonax I did some ctrl+z before to undo my changes, didn't see it had remove the console.log... Sorry ^^' The array is full now ! I just need to find the error and I will be ablo to display the info :) [List](http://imgur.com/a/xDFz2) – Florian Guebel May 08 '17 at 13:11
  • @FlorianGuebel change ngFor to `*ngFor="let application of applications"` – eko May 08 '17 at 13:17
  • @echonax add me an error.. I need to use #application, let never work :S [error](http://imgur.com/a/dfoMa) – Florian Guebel May 08 '17 at 13:20
  • 1
    @echonax Seems from the console.log (picture) that `applications` is actually an object that contains array `application`? Shouldn't it then be `*ngFor="let application of applications.application?"` I might be wrong tho :D – AT82 May 08 '17 at 13:20
  • @FlorianGuebel try `#application of applications.application` :) – AT82 May 08 '17 at 13:21
  • @AJT_82 good catch! – eko May 08 '17 at 13:22
  • The same ngFor works perfectly for other array. But yeah, looks like I receive xml and not json. – Florian Guebel May 08 '17 at 13:22
  • @AJT_82 My array is not filled anymore if I do what you said [Error 2](http://imgur.com/a/hCDuf). Sorry guys, I'm new in Angular and Typescript, I might miss something stupid... – Florian Guebel May 08 '17 at 13:27
  • @FlorianGuebel Sorry, you need to use safe navigation operator...try `#application of applications?.application` – AT82 May 08 '17 at 13:28
  • @FlorianGuebel Haha. Well it was a joined effort :) Just to explain a little your `applications` is an object, so the safe navigation operator safeguards null values: https://angular.io/docs/ts/latest/guide/template-syntax.html#!#safe-navigation-operator You can prepare yourself to use `?` quite a lot here in the asynchronous world :P – AT82 May 08 '17 at 13:31
  • @AJT_82 Yeah I can't add Echonax but thanks to him too ! I never used "?" cause before, all my call in my other service were to a local database, and looked like I didn't have to use it ^^' Sorry for my english, not my first language :) – Florian Guebel May 08 '17 at 13:34
  • Florian, we could let @echonax write up an answer, which you could then accept, so we get an explanatory answer of what was going on here and how to fix it, so that it can be useful to others. So, hop,hop echonax, my good sir, start scratching down an answer ;) – AT82 May 08 '17 at 13:37
  • @AJT_82 Yup he deserves some reputation – Florian Guebel May 08 '17 at 13:47

2 Answers2

1

Yor are printing on the console in the ngOnInit() method, i.e. before the subscription code is executed and therefore before the applications property is filled. Move console.log() method inside the arrow function of subscribe() just after this.applications = res;

Picci
  • 16,775
  • 13
  • 70
  • 113
0

So thanks to the community, I found my problem. First the console.log() wasn't in the right place. Then I needed to change the ngFor to display the info and now it works fine !

You can read the comment of my post, to find the answer.