We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Angular 2: ngFor not working correctly with Tab

Hi Keerthana,

In an Angular2 application, this way of using a dynamic number of tabs should work:

@Component(...)
export class TabComponent {
    tabs = ["tab1", "tab2"]
    ...
}

<ej-tab>
    <ul>
        <li *ngFor="let t of tablist"><a rel='nofollow' href="#{{t}}">Tab {{t}}</a></li>
    </ul>
    <div *ngFor="let t of tablist" id="{{t}}" [style.width]="'100%'">
        Hello tab {{t}}
    </div>
</ej-tab>

And indeed, it does produce what I expect. However, when I try to make it dynamic by changing the list of tabs as a result of an event:

<button (click)="onNewTab()">Add Tab</button> 

onNewTab() {
   this.tablist.push("tab" + this.tablist.length)
}

The result is not right ... I am not getting an additional tab, but a funny mixture of elements:

Tabs, having added two more
In this thread, there is a similar question, and the recommendation is to use the Javascript API. However, this does not integrate well with Angular 2 applications, which use data binding as template syntax. So this is not really an alternative. Anything I am doing wrong here?


3 Replies

KR Keerthana Rajendran Syncfusion Team July 22, 2016 12:55 PM UTC

Hi Alexander, 
Sorry for the inconvenience caused. We have prepared sample based on our understanding of your requirement. Please refer the below  
given link 
 
 
In component.html: 
We have bounded the function onNewTab(tabObj) with button click whose action is defined in ts file 
<code> 
<ej-tab [showCloseButton]="true" #tabObj> 
<ul> 
        <li *ngFor="let t of tabs"><a rel='nofollow' href="#{{t}}">Tab {{t}}</a></li> 
    </ul> 
    <div *ngFor="let t of tabs" id="{{t}}" [style.width]="'100%'"> 
        Hello tab {{t}} 
    </div> 
</ej-tab> 
<br> 
<button (click)="onNewTab(tabObj)">Add Item</button> 
</code> 
In component.ts: 
We have added tab item by using a public method addItem and set its content using innerHTML based on its count  
<code> 
export class AppComponent { 
    public tabs=["tab1","tab2"] 
    public count = 2 ; 
    onNewTab(tabObj) {   
        this.count ++ 
        var a = "tab" + this.count; 
        tabObj["widget"]["addItem"]('#'+a,'Tab' + this.count); 
        document.getElementById(a).innerHTML =   "Hello tab " + a; 
    } 
</code> 
If  we have misunderstood your requirement please get back to us with some more  details on your query 
 
Please let us know if any concern 
Regards, 
Keerthana.


AH Alexander Heim July 22, 2016 01:13 PM UTC

Hi Keerthana,

Thanks for your reply. Indeed, the code you provided works.

However, that's not Angular 2 data binding. It's a mixture of a) using Angular 2 to create the UI component and then b) using old-school style Javascript programming to work dynamically with it.  

My real case is, that the application is managing a list of tabs, that are dynamically created and closed. That list is conveniently held in an array property of the component. 

The problem is, that your tab component in my example, on construction, starts out with the content in the list property. But right after the initial creation, it gets completely disconnected from the property, and changes to it are not reflected by the tab. So instead of featuring Angular 2 two-way binding, the grid component forces me to hand-code all the interaction, just like if it would not be an Angular application. 

Wouldn't it make a lot more sense for an Angular 2 UI component, if your grid had a binding property for the tabs, and would lay itself out accordingly? Something like:

<ej-tab [(tabs)]>="myTabs">[...]</ej-tab>



KR Keerthana Rajendran Syncfusion Team July 26, 2016 01:08 PM UTC

Hi Alexander, 
Sorry for the inconvenience caused. 
Currently we don’t have support for two-way binding as you mentioned in Grid because tab component rendered via elements rather than data source property like in grid.  
The reason for the issue is when you push an element into array our component doesn’t notify the changes to tab component.  So we suggest you to refresh the tab items manually on each array item push.   
To do this, we need to call this refresh method ngAfterViewChecked event which will trigger on every model change.  
In component.html 
<code> 
<button (click)="onNewTab(tabtest1)">Add Item</button> 
</code> 
In component.ts 
<code> 
export class AppComponent { 
    public tabs:any =["tab0","tab1"]; 
    public count:number = 2; 
    public tabObject :any; 
    public triggered:boolean = false; 
    
    onNewTab(tabtest1) {   
       this.tabs.push("tab"+this.tabs.length);   
       this.count = jQuery(".e-tab").find("li").length; 
       this.tabObject = tabtest1; 
       this.triggered = false; 
    } 
     
    ngAfterViewChecked(){         
        if(jQuery(".e-tab").find("li").length > this.count && !this.triggered){ 
             this.tabObject["widget"]["_refresh"](); 
             this.triggered = true; 
        }        
    }   
 
</code> 
We have prepared a sample for your reference. Please refer the below given link: 
 
Please let us know if any concern 
Regards, 
Keerthana.

Loader.
Up arrow icon