Односторонняя привязка данных NativeScript не обновляет представление

Мне это кажется довольно простым случаем, но я явно что-то упускаю. У меня есть модель для привязки к представлению. Затем я загружаю модель с помощью Http-вызова. Почему не обновляется View? Я думал, что в этом весь смысл односторонней привязки.

Я подтвердил, что получаю данные, которые ожидаю от HTTP-вызова.

Обновить. Я добавил кнопку на экран, и привязка данных фактически обновит экран с помощью данных, загруженных по протоколу http, для обоих полей при нажатии кнопки, даже если метод кнопки устанавливает только одно из значений. Так что либо в NativeScript есть ошибка, либо я что-то не делаю неправильно.

Обновление 2. Привязка срабатывает при нажатии кнопки. Я изменил код, чтобы иметь пустой обработчик касаний, и просто нажатие кнопки приводит к привязке.

машинопись

import { Component, ChangeDetectionStrategy, OnInit } from "@angular/core";
import { Job } from "../../shared/customer/job";
import { Http, Headers, Response } from "@angular/http";
import { Observable } from "rxjs/Rx";

@Component({
    selector: "my-app",
    templateUrl: "pages/job-details/job-details.html",
    changeDetection: ChangeDetectionStrategy.OnPush
})

export class JobDetailsComponent implements OnInit {
    job: Job;
    salesAssociateName: string = "x";

    constructor(private http: Http) {
        this.job = new Job();
    }

    ngOnInit() {
        this.getJob(1234);
    }

    getJob(leadId: number) {
        var url = "https://url-not-for-you/job?franchiseeid=48&leadid=" + leadId;
        var headers = this.createRequestHeader();

        this.http.get(url, { headers: headers }).map(response => response.json())
            .do(data => this.setData(data[0]))
            .subscribe(
                () => this.success(),
                (error) => this.error()
            );
    }

    private createRequestHeader() {
        let headers = new Headers();
        headers.append("AuthKey","blah");
        headers.append("AuthToken", "blee");

        return headers;
    }

    setData(job) {
        this.job.FullName = job["FullName"];
        this.job.SalesAssociateName = job["SalesAssociateName"];
        this.salesAssociateName = this.job.SalesAssociateName;

        console.log("Found job for customer: " + job["FullName"]);
    }

    success() {
        // nothing useful
    }

    error() {
        alert("There was a problem retrieving your customer job.");
    }

    changeSA() {
    }
}

html

<StackLayout>
    <Label [text]="job.FullName"></Label>
    <Label [text]="salesAssociateName"></Label>
    <Button text="Push" (tap)="changeSA()"></Button>
</StackLayout>

person Danno    schedule 09.12.2016    source источник


Ответы (1)


Ваш код будет работать должным образом со значением по умолчанию ChangeDetectionStrategy. однако вы изменили стратегию на onPush

Чтобы привязка работала должным образом, в параметре changeStrategy по умолчанию удалить следующую строку

changeDetection: ChangeDetectionStrategy.OnPush

или измените его на

changeDetection: ChangeDetectionStrategy.Default

Подробнее об Angular-2 ChangeDetectionStrategy здесь и здесь

Если вы по-прежнему хотите использовать onPush вместо стратегии по умолчанию, ваши свойства должны быть объявлены как @input () и после внесения изменения (в вашем случае в setData) помечены как markForCheck ()

Причина, по которой ваша привязка работает при нажатии кнопки, заключается в том, что изменение состояния приложения может быть вызвано:

  • События - коснитесь, проведите пальцем,
  • XHR - Получение данных с удаленного сервера
  • Таймеры - например, setTimeout ()

В целях тестирования и если кому-то интересно, как реализовать сценарий с помощью onPush, вот пример кода:

import { Component, ChangeDetectionStrategy, ChangeDetectorRef, OnInit, NgZone, Input } from "@angular/core";
import { Http, Headers, Response } from "@angular/http";
import { Observable as RxObservable } from "rxjs/Rx";
import "rxjs/add/operator/map";
import "rxjs/add/operator/do";

@Component({
    selector: "my-app",
    templateUrl: "app.component.html",
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements OnInit {
    @Input() public job: any = { salesAssociateName: "default job" };
    @Input() public salesAssociateName: string = "default name";


    constructor(private http: Http, private change:ChangeDetectorRef) { }

    ngOnInit() {
        this.getJob();
    }

    getJob() {
        var url = "http://httpbin.org/get";
        var headers = this.createRequestHeader();

        this.http.get(url, { headers: headers })
            .map(response => response.json())
            .do(data => {
                this.setData();
            }).subscribe(
                () => this.success(),
                (error) => this.error()
            );
    }

    private createRequestHeader() {
        let headers = new Headers();
        return headers;
    }

    setData() {

        this.job.salesAssociateName = "NEW job SalesAssociateName";
        this.salesAssociateName = "NEW job FullName";
        this.change.markForCheck();
    }

    success() {
        alert("success");
    }

    error() {
        alert("There was a problem retrieving your customer job.");
    }
}
person Nick Iliev    schedule 12.12.2016
comment
На самом деле наблюдаемые входные данные не работают или время от времени работают с onPush в nativescript. Не знаю почему. - person Lyubimov Roman; 17.10.2017
comment
Будет ли этот метод работать в NativeScript 5.1 с angular 7? - person bks; 24.12.2018