Typescript bind http response to xml


#1

My app is not an angular application. I’m using just typescript. It usually binds the values to the xml view if I set them outside methods and functions.

How can I bind the http response to the xml Labels when I get data from server? It’s not working inside .then() method.

home-page.xml:

<Label text="{{ name }}"></Label>

home-view-model.ts:

import { Observable } from "data/observable";

var http = require("http");

export class HomeViewModel extends Observable {

private serverUrl = "http://www.website.com/clientes/users/select-myinfos.php";
user_id:string = "1";

name: string;

 private getUserInfos() {

    console.log("get user infos executed");

    http.request({
        url: this.serverUrl,
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        content: JSON.stringify({ id: this.user_id })

    }).then(function (response) {

        this.name = response.content.toJSON()[0].NAME; // this is not working. It doesn't display in xml view


    }, function (e) {
        console.log("Error occurred " + e);

        alert("Error");
    });

 }
}

Note: Server data request is working fine.


Simple Post Request to my URL gives me "Unable to resolve host"
#2

Did you setup your page’s bindingContext to use this class/variable?
(I don’t speak typescript, but you need to assign this class/variable to the page’s bindingContext.)

https://docs.nativescript.org/core-concepts/data-binding#binding-to-a-property


#3

How could I do that? Would you help me? I’m new to NS.


#4

Here’s a simple example. Since I don’t know typescript, I created this example in javascript, but you can translate this to typescript. Also, I’m using fetch instead of the http module, but that makes no difference.

It pulls data from an API. Once the data arrives, it takes a property out of it (email) and displays it. That piece of data (email) is what gets assigned to the page’s bindingContext as an observable.


#5

Here’s the typescript example:


#6

Hi. I cannot see the code


#7

You need to click on the link.


#8

Ok. I tried only on a mobile browser. I’ll check it again.


#9

Nothing changed. “name” should be highlighted inside then(function…) when I click on “name” from name: string; This is an indicative that it would work both would be the same. But it doesn’t happen.

It looks like “name” is not available inside then(function(response)…)


#10

I believe your original question was that your “name” property is not binding in the XML, so when you receive the data, the property is not showing up. When you run the code that’s on the playground, you will see the “name” property will bind in the XML file, and the data (which is an email address) will be displayed on the screen once it is received from the server.


#11

I understood your code but I tried it in my code and nothing has changed. It’s not binding to xml.


#12

You can’t do a simple assignment, such as “name = value”. When you do that, the property “name” will not raise an event when it has changed. As such, it will not propagate any changes to the target element in your XML file.

You have to make sure that you bind your source (name) to your target (the text attribute of the Label in your XML file).

Since your view model class (HomeViewModel) is extending the Observable object, you can use set method to register changes in your property. Eg

this.set("name-of-your-property", "new value")

And that is how I changed your code which is reflected in the playground example.

https://docs.nativescript.org/cookbook/data/observable


#13

I don’t understand why this is not working in my app. I set

this.set("name", "");

inside the constructor just like you did and changed the code like below:


http.request({
        url: this.serverUrl,
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        content: JSON.stringify({ id: this.user_id })

    }).then(function (response) {

        this.set("name",  response.content.toJSON()[0].NAME);
        
    }, function (e) {
        console.log("Error occurred " + e);

        alert("Error");
    });

And I can do “name = value” outside that function. It works fine.


#14

You could create a sample on playground and post it.


#15

I just did it in playground but nothing is binded to xml view yet


<Page loaded="pageLoaded" class="page" xmlns="http://www.nativescript.org/tns.xsd">

	<ActionBar title="Home" class="action-bar">
	</ActionBar>

	<ScrollView>
		<StackLayout class="home-panel">
			<!--Add your page content here-->
			<Label textWrap="true" text="Play with NativeScript!" class="h2 description-label" />
			<Label textWrap="true" text="Write code in the editor or drag and drop components to build a NativeScript mobile application."
			 class="h2 description-label" />
			<Label textWrap="true" text="{{name}}" />
		</StackLayout>
	</ScrollView>
</Page>
import { Observable } from 'data/observable';

var http = require("http");

export class HomeViewModel extends Observable {

    private serverUrl = "http://www.website.com/clientes/users/select-myinfos.php";
    user_id: string = "1";

    constructor() {
        super();
        this.set("name", "");

        this.getUserInfos();
    }

    private getUserInfos() {

        console.log("get user infos executed");

        http.request({
            url: this.serverUrl,
            method: "POST",
            headers: { "Content-Type": "application/x-www-form-urlencoded" },
            content: JSON.stringify({ id: this.user_id })

        }).then(function (response) {

            var resposta = response.content.toJSON();
            console.log("resposta: " + response.content);

            this.set("name", response.content.toJSON()[0].NAME);

        }, function (e) {
            console.log("Error occurred " + e);
            //loader.hide();
            alert("Erro ao baixar informações. Verifique sua conexão.");
        });

    }
}

#16

Ok, I think I found the problem.

Http is not working properly. I used fetch() based on your code and it worked on Playground. I’ll test it in my code asap.


#17

Here’s a working demo. There are/were two issues.

  1. I’m not sure what content type are you expecting. I have used a test http service (https://httpbin.org/post) which returns JSON. So the content type had to be changed from application/x-www-form-urlencoded to application/json.
  2. The other issue was with the context of this, when the http returns. When you change it to an ES6 call, the context of this will be properly set to your data.

This way you can use http.response as opposed to fetch.


Http not sending token in GET request. CORS issue?
#18

I followed your steps but it really works with fetch() instead of http(). If I use http no value is displayed in xml view. Very weird. Is there any problem using fetch?


#19

I have posted multiple live code samples that it works with fetch and with http as well. Since I don’t have access to your server, I don’t know what your server returns and how you handle the data you get back. I can only show how it works using publicly available APIs. I suggest take a look at the code samples using the APIs I have posted, then try to backtrack from there why your code doesn’t work.


#20

My server response is a simple json response like

data: [{“ID”: “1”, “NAME”:"Brian ",}]

So, both

this.set("name", data[0].NAME);

and

this.name = data[0].NAME;

work with fetch() binding the values to xml view and does not work with http().