Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*ngIf not working in Angular application for hide/show layout after upgrade to NS3 #872

Closed
NickIliev opened this issue Jun 30, 2017 · 41 comments · Fixed by #888
Closed

*ngIf not working in Angular application for hide/show layout after upgrade to NS3 #872

NickIliev opened this issue Jun 30, 2017 · 41 comments · Fixed by #888
Assignees
Labels

Comments

@NickIliev
Copy link

From @memphisvl on June 29, 2017 19:56

It used to work on {N} 2.5 and now it seems that the only way to show/hide some elements is using visibility option.

Before

<StackLayout class="page">
  <Label *ngIf="isPresent" text="{{showText}}"></Label>        
</StackLayout>

Now (Workaround)

<StackLayout class="page">
  <Label visibility="{{isPresent ? 'visible' : 'collapse'}}" text="{{showText}}"></Label>        
</StackLayout>

Is this expected and from now on I will have to use visibility for UI logic?

Versions

    "@angular/animations": "~4.1.0",
    "@angular/common": "~4.1.0",
    "@angular/compiler": "~4.1.0",
    "@angular/core": "~4.1.0",
    "@angular/forms": "~4.1.0",
    "@angular/http": "~4.1.0",
    "@angular/platform-browser": "~4.1.0",
    "@angular/platform-browser-dynamic": "~4.1.0",
    "@angular/router": "~4.1.0",
    "moment": "^2.18.1",
    "nativescript-angular": "^3.1.0",
    "nativescript-angular-snapshot": "1.5.2-5.5.372.32",
    "nativescript-carousel-view": "^2.9.0",
    "nativescript-google-maps-sdk": "^2.3.0",
    "nativescript-loading-indicator": "^2.3.2",
    "nativescript-local-notifications": "^1.2.1",
    "nativescript-platform-css": "^1.4.0",
    "nativescript-plugin-firebase": "^4.0.2",
    "nativescript-pulltorefresh": "^2.0.1",
    "nativescript-push-notifications": "^0.1.2",
    "nativescript-sidedrawer": "^1.0.6",
    "nativescript-theme-core": "~1.0.2",
    "reflect-metadata": "~0.1.8",
    "rxjs": "~5.3.0",
    "tns-core-modules": "^3.1.0",
    "zone.js": "~0.8.2"

TNS Paltform
3.1.0

Copied from original issue: NativeScript/NativeScript#4479

@mcrvaz
Copy link

mcrvaz commented Jun 30, 2017

I'm having some similiar issues with *ngIf, sometimes the elements are rendered out of order, sometimes aren't even rendered. Seems to be related with the last version (3.1.0).

@danielgek
Copy link

danielgek commented Jun 30, 2017

Me to, not only with *ngIf but *ngFor too

@NathanWalker
Copy link
Contributor

I have found visibility to be more stable generally. Perhaps a directive should be added here out of the box to make visibility more like ngIf in that sense - maybe even call it ngShow which would use the visibility attribute under the hood?

@berchik
Copy link

berchik commented Jul 2, 2017

Same here.

@u14040426
Copy link

I also have a similar issue, where after a http request and setting a boolean to true to show content, the content doesnt show. But what prompted me top try this, was the http request returns a string which is supposed to change a labels text but it didnt change. That is why I wrapped it in a ngIf but then it doesnt show at all.

@memphisvl
Copy link

After I did the upgrade and had to redo my Angular layout logic I've found these issues with ngIf:

  1. ngIf works as expected if value is available at time of rendering
  2. ngIf break any layout (out of order rendering of ngIf elements) if value was delayed (eg: async call)
  3. visibility seem to be good alternative

Overall it was unpleasant to find out that what used to work with {N}2.5 is not working in {N}3.x.
At least I know, that am not alone) For anyone wondering about workarounds use [visibility] for Angular html layouts.

@EddyVerbruggen
Copy link

A possible workaround for out-of-order rendering could be separating the elements in different <StackLayout>s. My case was this:

<StackLayout>
  <GridLayout id="g1" *ngFor>
  </GridLayout>
  <GridLayout id="g2">
  </GridLayout>
</StackLayout>

Because of the ngFor "g2" was rendered before "g1".

This fixed it:

<StackLayout>
  <StackLayout>
    <GridLayout id="g1" *ngFor>
    </GridLayout>
  </StackLayout>
  <StackLayout>
    <GridLayout id="g2">
    </GridLayout>
  </StackLayout>
</StackLayout>

@pauly815
Copy link

pauly815 commented Jul 4, 2017

@EddyVerbruggen Your workaround resolved my issue with multiple *ngIf items better than the visibility workaround. Thanks!

@sis0k0
Copy link
Contributor

sis0k0 commented Jul 5, 2017

Hey, guys! Can you share some code snippets where items are rendered out of order?

@sis0k0 sis0k0 added this to the 3.2 TBD milestone Jul 5, 2017
@sis0k0 sis0k0 added the bug label Jul 5, 2017
@EddyVerbruggen
Copy link

Hi @sis0k0, here's one I hope you find useful:

<StackLayout>
  <!-- NOK -->
  <StackLayout>
    <Label text="label 1"></Label>
    <Label text="label 2"></Label>
    <Label text="label 3" *ngIf="true"></Label>
    <Label text="label 4"></Label>
  </StackLayout>

  <!-- OK -->
  <StackLayout>
    <Label text="label a"></Label>
    <Label text="label b"></Label>
    <StackLayout>
      <Label text="label c" *ngIf="true"></Label>
    </StackLayout>
    <Label text="label d"></Label>
  </StackLayout>
</StackLayout>

screen shot 2017-07-05 at 09 42 57

@sis0k0 sis0k0 self-assigned this Jul 11, 2017
sis0k0 added a commit that referenced this issue Jul 11, 2017
sis0k0 added a commit that referenced this issue Jul 11, 2017
@sis0k0 sis0k0 changed the title [iOS] *ngIf not working in Angular application for hide/show layout after upgrade to NS3 *ngIf not working in Angular application for hide/show layout after upgrade to NS3 Jul 11, 2017
@sis0k0 sis0k0 removed this from the 3.2 milestone Aug 2, 2017
@cgebe
Copy link

cgebe commented Oct 26, 2017

This issue was initially not about out-of-order rendering. It is about elements, where *ngIf is changed dynamically after the first render of the page, not getting rendered at all. This problem does and still only occur on iOS.

Code examples on Version 3.2.0:

<GridLayout rows="*">
    <RadListView row="0" [items]="accounts" pullToRefresh="true" (pullToRefreshInitiated)="refresh($event)" separatorColor="transparent">
        <ng-template let-item="item" let-i="index">
            <StackLayout>
                <GridLayout (tap)="selectAccount(item)"
                    <Label *ngIf="item.selected" col="0" row="0" class="fa text-center select-indicator" text="&#xf111;"></Label>
                    <Label *ngIf="!item.selected" col="1" row="0" class="fa text-center select-indicator" text="&#xf10c;"></Label>
                </GridLayout>
            </StackLayout>
        </ng-template>
    </RadListView>
</GridLayout>

selectAccount(item) toggles the selected boolean attribute. When changed, both directives arent rendered again. When toggling back they arent also not rendered again. Replacing it with [visibility]:

<GridLayout rows="*">
    <RadListView row="0" [items]="accounts" pullToRefresh="true" (pullToRefreshInitiated)="refresh($event)" separatorColor="transparent">
        <ng-template let-item="item" let-i="index">
            <StackLayout>
                <GridLayout (tap)="selectAccount(item)"
                    <Label [visibility]="item.selected ? 'visible' : 'collapse'" col="0" row="0" class="fa text-center select-indicator" text="&#xf111;"></Label>
                    <Label [visibility]="!item.selected ? 'visible' : 'collapse'" col="1" row="0" class="fa text-center select-indicator" text="&#xf10c;"></Label>
                </GridLayout>
            </StackLayout>
        </ng-template>
    </RadListView>
</GridLayout>

Leads to not rendering when toggling for the first time, but toggling back renders the elements again!

All in all this issue should not have been closed, because the problem persists, elements with *ngIf are not rerendered when their values are changed dynamically. [visibility] as workaround is not working fully either!

@jevenson
Copy link

jevenson commented Oct 26, 2017

@cgebe Same here, but I'm experiencing on Android.

@cgebe
Copy link

cgebe commented Oct 27, 2017

I found out, this issue only happens in conjuction with RadListView due to not using ObservableArray as underlying data structure.

@spmamidi
Copy link

+1

@marcusjrc
Copy link

marcusjrc commented Dec 13, 2017

+1 Still having this issue, both *ngFor and *ngIf don't re-render for iOS correctly when data changes after the initial render

@vultix
Copy link
Contributor

vultix commented Dec 31, 2017

Also seeing this issue on IOS for *ngIf

@souly1
Copy link

souly1 commented Jan 21, 2018

+1

@giorgiopiatti
Copy link

giorgiopiatti commented Jan 29, 2018

Any update on this issue, it still persists....
When you have a boolean input as an async variable on the first render it works but if the input changes the UI would not update according to the status.

By the way, I'm using the last version of nativescript and nativescript-angular.

@cgebe
Copy link

cgebe commented Jan 29, 2018

Issue should be reopened.

@sis0k0
Copy link
Contributor

sis0k0 commented Jan 29, 2018

Heya, could you please share a playground link or some code snippet that demonstrates the broken behavior?

@behrangs
Copy link

behrangs commented Feb 11, 2018

It seems to me that:

  1. the 'visibility' option is more reliable than the '*ngIf' counterpart
  2. even that only works well only if what you are toggling is visible at the start.
<StackLayout orientation="horizontal" [visibility]="menuStatus ? 'visible' : 'collapsed'">
    <Button text="Delete" (tap)="delete(item)"></Button>
</StackLayout>

So in this example, I have a menu which I would like to toggle and if menuStatus is true at the beginning it works, however, if it's false then some sort of UI refresh is needed to make the visibility work. But obviously when you have such menu you'd most likely want it to be hidden at first so I'm struggling with this a little. I should probably mention that this snippet is in a RadListView as well. Is there an update on this?

@Raf197
Copy link

Raf197 commented Mar 1, 2018

So there is no quick fix for this? Like some fix on config files or something like that?

@svzi
Copy link

svzi commented Apr 12, 2018

@behrangs Did you resolve that issue somehow? I'm exactly facing the same. :(

@netowp
Copy link

netowp commented Apr 26, 2018

Same issue here. I hope they re-open this issue.

@NickIliev
Copy link
Author

@netowp @yasserN @svzi @Raf197 @behrangs the issue seems to be related to this one. The fix for the linked issue is already in master branch and it will be included in the next official release. meanwhile, you can test the fix on your side with

npm i tns-core-modules@next --save

Keep in mind that the next version (master branch) is not meant for production but just for testing purposes.

@bettsjj
Copy link

bettsjj commented Apr 29, 2018

NickIliev got it right. I had the problem with the following html on android only and broken on IOS. however after upgrading it works.

Thanks for your assistance
<StackLayout class="text-left" *tabItem="{title: 'Details'}">
<div *ngIf="!isLoadingImages">
<GridLayout height="250" [carousel]="gallery" carouselLabelOverlay="true" carouselSpeed="2000">


<div *ngIf="isLoadingImages">




@divyachandana
Copy link

hey @NickIliev that was really helpful im really struggling with this issue for days.
after updating tns-core-modules ng-if working perfectly in ios. Thanks a lot for help.
npm i tns-core-modules@next --save

@parliament718
Copy link

parliament718 commented Jul 23, 2018

I feel like this needs to be re-opened again, how it possible that I'm still seeing this issue in {N} 4.1.1 with tns-core-modules@next (^4.2.0-2018-07-21-02). Same with ngSwitch and [visibility] also does not work as expected. I have yet to find a workaround

<GridLayout class="thumb-icon" [ngSwitch]="location.progress">                    
    <Label *ngSwitchCase="null" text="&#xf1f8;" class="fas fa-trash"></Label>
    <Label *ngSwitchCase="100" text="&#xf058;" class="fas fa-check-circle"></Label>
    <Progress *ngSwitchDefault [value]="location.progress" maxValue="100"></Progress>
</GridLayout>

<GridLayout class="thumb-icon">                    
                    
   <Label *ngIf="location.progress == null" text="&#xf1f8;" class="fas fa-trash"></Label>
   <Label *ngIf="location.progress == 100" text="&#xf058;" class="fas fa-check-circle"></Label>
   <Progress *ngIf="location.progress > 0" [value]="location.progress" maxValue="100"></Progress>
</GridLayout>

Neither version works to show the progress bar when location.progress is updated. I can see location.progress updating in the UI via a simple <Label>

@parliament718
Copy link

parliament718 commented Jul 24, 2018

Here's a playground to demonstrate the issue which is still present in {N} 4.1

https://play.nativescript.org/?template=play-ng&id=xRtLDX&v=4

The top section does now show the progress bar when u start the "upload", meanwhile the bottom section does.

The only difference between these 2 ListViews is that in the top case I pass the countries reference via [items]="countries" whereas on the bottom I pass a copy of the array each time via [items]="countries.slice()". The latter fixes the issue but this is not a solution for me because in my case the items are actually images and passing a new reference on every read causes the images to reload and jitter every digest cycle.

I have tried the same implementation with a GridView (instead of ListView) so it seems evident that the problem really arises when using *ngIf or *ngSwitch inside an *ngFor that is iterating over an array reference.

Can somebody please take a look into fixing this. Since passing an array reference is actually the correct way to use ngFor, it seems that this is a very common and rudimentary use case and it's a real bummer to have this present after 1 year of this issue being open. I currently have no workaround for this, as I would just be trading one bug for another (I have to choose between a progress bar and image jitter/constant reloads).

@racknoris
Copy link

racknoris commented Aug 27, 2018

Still in NS 4+, I found that using this.ngZone.run(() => { this.foo = false; }) works well in re-rendering the view content in case it doesn't work

@kamok
Copy link

kamok commented Sep 5, 2018

When I bind a function to the *ngIf instead of binding an attribute, it works fine, except for the "Expression has changed after last checked" error.

@boldham31
Copy link

When I bind a function to the *ngIf instead of binding an attribute, it works fine, except for the "Expression has changed after last checked" error.

Thanks @kamok this solution worked for me. This seems to be the simplest temporary workaround that I have seen in the thread. The update to the tns core modules didn't work for me as well.

@WouterVanVegchel
Copy link

I face the same issue, but found another work around (works for me, but no guarantees...).
I place a Label above the element with the *ngIf :
<Label [visibility]="mLoaded && !hasM ? 'hidden' : 'hidden'" text=""></Label> and now it works. Why?!, I don't know. I cannot explain it.

@Morgs007
Copy link

Morgs007 commented Jan 5, 2019

I was very excited to learn Ionic, sadly landed on Ionic 4 which seems overly unstable right now! For me, [(ngModel)] two-way binding, *ngIf, and *ngFor all not working when I do and Android release of my app... ! I can only imagine I would face the same issues on iOS... I could perhaps resolve the ngIf with that visibility workaround but how do I fix the ngFor and [(ngModel)]? I posted my model binding issues here and here if anyone could kindly offer me some help?

@jimb77
Copy link

jimb77 commented Dec 2, 2019

Any updates on this issue?

@csimpi
Copy link

csimpi commented Mar 21, 2020

For me, this is still an issue. Can't really use *ngIf properly in NS+Angular

@Nurtylek
Copy link

Nurtylek commented Jun 5, 2020

also having trouble with *ngIf, its rendering my element outside of parent element

@gbro3n
Copy link

gbro3n commented Mar 8, 2021

For me this wasn't working because I'd missed the inclusion of some declarations under @NgModule in app.module.ts:

@NgModule({
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent,
    ProductDetailsComponent,
    CartComponent,
    ShippingComponent
  ],

@stan1025
Copy link

I have also problem with ngIf inside a p-splitter template. If I move the splitter, the ngIf seams to be ignored and all the code will be placed in the dom.

@qualcentric-web-solutions

yes i have same issue in ios app only so i added ngZone this one solved my problem for ios app.

<StackLayout class="page">
  <Label *ngIf="isPresent" text="{{showText}}"></Label>        
</StackLayout>
import { Component, OnInit, NgZone } from '@angular/core';

constructor(private service: ApiService, private zone: NgZone) {
    this.getDataFromApi();
 }

getDataFromApi(): void {
    this.service.getDataFromApi().subscribe(score => {
      this.zone.run(() => {
        this.isPresent= isPresent;
      });
      
    })
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.