Как принудительно обновить пользовательский интерфейс в нативном скрипте (машинописи) с помощью Observables через http-запросы?

Я использую компонент TabView с синтаксисом шаблона, чтобы перебирать его и добавлять элементы внутрь (используя наблюдаемую коллекцию и асинхронный канал). Мои элементы приходят из http-запроса.

Мой home.component.tns.html выглядит следующим образом:

<ActionBar title="Angular 2 Seed Advanced (nativescript)">
</ActionBar>
<StackLayout>
  <TabView selectedIndex="0" selectedColor="#FF0000">
    <template ngFor let-tab [ngForOf]="tabs | async">
      <StackLayout *tabItem="tab">
          <Label text="tab item"></Label>
      </StackLayout>
    </template>
  </TabView>

  <Button text="call something" (tap)="emptymethod()"></Button>

</StackLayout>

... и мой home.component.ts:

...
    export class HomeComponent{

        public tabs: Observable<any[]>;

        constructor(private _menuService: MenuService) {

            this._menuService.getMenu()
                .map((menus) => {
                    let result: Array<any> = [];

                    if (menus) {
                        menus.forEach(menu => {
                            result.push({ 'title': menu.title });
                        });
                    }
                    return result;
                })
                .subscribe(
                data => {
                    this.tabs = Observable.of<any[]>(data);
                },
                error => error => this._log.debug(error));
        }

        emptymethod() {
            this._log.debug('HomeComponent - nada invoked');
        }

        ngOnInit() {

        }
    ...

Когда интерфейс визуализируется, меню TabView не появляется, но когда я нажимаю кнопку вызвать что-то и вызывается emptymethod, элементы внутри TabView появляются, другими словами, после "обновления" появляется этот компонент...

Это не должно происходить автоматически?


person Richard Lee    schedule 19.05.2016    source источник


Ответы (3)


У меня было несколько ситуаций с нативным скриптом, когда пользовательский интерфейс не обновлялся (зона не запускала обновление пользовательского интерфейса или что-то в этом роде), и самый простой способ сделать это — заставить код запускаться в зону. Вот небольшой пример

export class TestClass {
   constructor(private _ngZone: NgZone) {
   }
   someOperation(){
     this._ngZone.run(() => {
       //Do whatever you want here
     })
   }
}

Я знаю, что это не лучшее решение, но я думаю, что это самый чистый обходной путь.

Вот еще один вопрос, который я задал несколько месяцев назад, связанный с этим: external-angular">Angular 2 Как заставить Angular обнаруживать изменения, сделанные вне Angular?

person Denko Mancheski    schedule 22.08.2016

Кажется, есть проблема с тем, как асинхронные операции и обнаружение изменений обрабатываются в nativescript-angular, когда задействованы сторонние плагины.

Текущее предложение состоит в том, чтобы обернуть все вызовы асинхронных уведомлений в зонированную функцию обратного вызова.

В следующем видео объясняется проблема и решение. Надеюсь это поможет. http://www.nativescriptsnacks.com/videos/2016/06/13/zoned-callbacks.html

Более подробная информация о соответствующем запросе функции в Nativescript представлена ​​здесь. https://github.com/NativeScript/NativeScript/issues/2229

person abz    schedule 21.08.2016

Я предполагаю, что обнаружение изменений не запускается, когда вызывается блок next в подписке, поэтому изменение на this.tabs не обнаруживается до тех пор, пока обнаружение изменений не будет запущено нажатием кнопки.

Вы должны быть в состоянии упростить свой Observable и просто сделать:

        this.tabs = this._menuService.getMenu()
            //Convert the Array into a flattened Observable
            .flatMap((menus) => menus ? menus.map(({title}) => {title}) : []);

Что неявно сгладит массив в Observable для вашего блока ngFor.

person paulpdaniels    schedule 19.05.2016
comment
Является ли flatMap функцией из Observables? Я получаю сообщение flatMap in not a function ...или мне следует вернуть массив из getMenu, а не Observable? - person Richard Lee; 20.05.2016
comment
Да, flatMap — это функция для Observable, это псевдоним для mergeMap. Возможно, вам придется импортировать его, см. здесь - person paulpdaniels; 20.05.2016