4

I'm using a TabView component with template syntax to iterate over it and add items inside (using an observable collection and async pipe). My items come from a http request.

My home.component.tns.html as follows:

<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>

...and my 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() {

        }
    ...

When the interface is renderized, the TabView menu does not appears, but when i click over call something button and emptymethod is called the items inside the TabView appears, in other words, after the "refresh" that component appears...

This should not happens automatically?

3 Answers 3

14

I had couple of situations with nativescript where the UI wont refresh (the zone will not trigger a UI refresh or something) and the easiest way to do it is to force the code to run into the zone. Here is small example

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

I know this is not the best solution but thats the cleanest workaround currently I think

Here is another question that I asked months ago related to this: Angular 2 How to get Angular to detect changes made outside Angular?

Sign up to request clarification or add additional context in comments.

1 Comment

thanks dude, it worked perfect for me, it may not be the optimal solution, but it works fine!
1

There seems to be a problem with how async operations and change detection is being handled in nativescript-angular when third party plugins are involved.

The current suggestion is to wrap all async notify calls within a zoned callback function.

The following video explains the issue and solution. Hope this helps. http://www.nativescriptsnacks.com/videos/2016/06/13/zoned-callbacks.html

More details on a corresponding feature request in Nativescript is present here. https://github.com/NativeScript/NativeScript/issues/2229

Comments

0

I would guess because the change detection is not being triggered when the next block in the subscribe is called so the change to this.tabs is not detected until changed detection triggered by the button press.

You should be able to simplify your Observable and just do:

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

Which will flatten the array into an Observable implicitly for your ngFor block.

2 Comments

Is flatMap a function from Observables? I'm receiving a message flatMap in not a function ...or should i return a array from getMenu and not a Observable?
Yes flatMap is a function on Observable, it is an alias for mergeMap. You may need to import it see here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.