web-dev-qa-db-fra.com

Comment puis-je accéder à la méthode 'select' de NgbTabSet dans le composant dans Angular2 et ng-bootstrap?

Utilisation de Angular 2.3.1 et ng-bootstrap 1.0.0-alpha.18. J'essaie de sélectionner par programme un onglet basé sur l'ID dans le composant plutôt que dans le modèle. Le but est pour extraire le paramètre de l'url et l'utiliser pour sélectionner l'onglet dans ngOnInit

le gabarit

<section id="policy-terms">
<ngb-tabset>
  <ngb-tab title="Terms and Privacy" id="terms">
    <template ngbTabContent>
      <div class="container page-content">

      </div>
    </template>
  </ngb-tab>
  <ngb-tab title="Company Policy" id="policy">
    <template ngbTabContent>
      <div class="container page-content">

      </div>
    </template>
  </ngb-tab>

</ngb-tabset>
</section>

Et le code composant:

import { Component, OnInit } from '@angular/core';
import { NgbTabset } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'app-policy-terms',
  templateUrl: './policy-terms.component.html',
  styleUrls: ['./policy-terms.component.scss'],
  providers: [
       NgbTabset
   ]
 })
 export class PolicyTermsComponent implements OnInit {

 constructor(
    public tabset: NgbTabset
  ) { }

  ngOnInit() {
    this.tabset.select('policy');
   }
}

Cela produit juste une erreur:

Erreurs du journal de la console

Comment puis-je accéder à cette méthode?

14
bikeguy

Routage avec Ngb-TabSet

Dans AngularJs 1.x, utiliser ui-router pour configurer des routes de noms était simple. Dans Angular 2 avec Ng-Bootstrap, ce n'est pas aussi évident. Du côté positif, ce dont vous avez besoin est disponible dans les bibliothèques natives Angular 2).

Configuration de la configuration de l'itinéraire

export const appRoutes: Routes =
    [
        { path: 'prospect/:prospectid/details', component: ProspectTabsView, data:{name:'details'} },
        { path: 'prospect/:prospectid/appointments', component: ProspectTabsView, data:{name:'appointments'} },
        { path: 'prospect/:prospectid/followups', component: ProspectTabsView, data:{name:'followups'} },
        { path: 'prospect/:prospectid/contacts', component: ProspectTabsView, data:{name:'contacts'} },
        { path: '', component: DashboardView },
        { path: '**', redirectTo: '', pathMatch: 'full'}
    ];

La configuration est simple à une exception près: l'attribut [data]. Vous remarquerez qu'il a une clé appelée name. C'est le nom de l'itinéraire. Considérez-le comme un attribut de données comme un sac de données. Vous pouvez ajouter plus que le nom de l'itinéraire.

Configuration du balisage TabSet

<ngb-tabset #tabs>
    <ngb-tab id="details">
        <ng-template ngbTabTitle>
            <a [routerLink]="['/prospect', prospectId, 'details']">Details</a>
        </ng-template>
        <ng-template ngbTabContent>
        </ng-template>
    </ngb-tab>
    <ngb-tab id="contacts">
        <ng-template ngbTabTitle>
            <a [routerLink]="['/prospect',prospectId,'contacts']">Contacts</a>
        </ng-template>
        <ng-template ngbTabContent>
        </ng-template>
    </ngb-tab>
    <ngb-tab id="appointments">
        <ng-template ngbTabTitle>
            <a [routerLink]="['/prospect', prospectId, 'appointments']">Appointments</a>
        </ng-template>
        <ng-template ngbTabContent>
        </ng-template>
    </ngb-tab>
    <ngb-tab id="followups">
        <ng-template ngbTabTitle>
            <a [routerLink]="['/prospect', prospectId, 'followups']">Follow Ups</a>
        </ng-template>
        <ng-template ngbTabContent>
        </ng-template>
    </ngb-tab>
</ngb-tabset>

Il n'y a rien de magique dans le balisage de l'onglet ci-dessus, il y a quelques choses que vous souhaitez noter: d'abord dans le ngb-tabset élément, nous avons déclaré la variable #tab. Nous utiliserons #tab plus loin dans le composant. Deuxièmement, chaque nbg-tab a un ensemble id qui correspond au nom que nous avons défini dans la configuration de l'itinéraire (c'est-à-dire data:{name:'followups'}).

Configuration du composant

import {
     AfterViewChecked, Component, OnInit, 
    ViewChild
} from '@angular/core';
import '../../assets/css/styles.css';
import {ActivatedRoute} from "@angular/router";
import {NgbTabset} from "@ng-bootstrap/ng-bootstrap";

@Component({
    templateUrl: './tabs.view.html'
})
export class ProspectTabsView implements OnInit, AfterViewChecked{
    prospectId: number;
    selectedTab:string; 

    @ViewChild('tabs')
    private tabs:NgbTabset;

    constructor(private route: ActivatedRoute) { 
        this.route.data.subscribe(d=>{
            this.selectedTab = d.name;
        });
    }

    ngOnInit(): void {
        this.route.params.subscribe(
            params => {
                this.prospectId = +params['prospectid'];
            }
        );
    }

    ngAfterViewChecked(): void {
        if(this.tabs) {
            this.tabs.select(this.selectedTab);
        }
    } 
 }

La partie la plus difficile de cet exercice a été d'obtenir l'ordre d'exécution correct. Si ce n'est pas correct, une collection ou une propriété ne sera pas initialisée avant que vous ne l'utilisiez. Nous commencerons par le haut de la classe et descendrons.

Tout d'abord, nous avons les variables. prospectId est la clé primaire des données, selectedTab est le nom de l'onglet actuellement sélectionné, et enfin, nous avons la variable tabs. tabs est une référence à l'attribut (#tab) nous avons ajouté au ngb-tabset élément.

Vient ensuite le constructor. Ce n'est pas évident dans la documentation, mais data est un Observable<data>. Pour capturer la valeur, nous souscrivons à la propriété data de la route.

Le constuctor suit le ngOnInit. Ce n'est pas important pour les onglets, mais cela capture le prospectId que nous utilisons dans le routage de l'onglet. Si vous ne disposez d'aucune donnée dynamique sur vos itinéraires, vous n'en avez pas besoin.

Enfin, nous avons ngAfterViewChecked. Pour router le tabs, c'est le plus important. Ici, nous utilisons la variable tabs que nous avons capturée à partir du balisage et c'est là que nous transmettons le nom de l'onglet sélectionné à tabs pour changer l'onglet sélectionné.

Mise à jour

Pour que cela fonctionne correctement, j'ai dû ajouter pour accrocher dans l'événement tabChange sur le ngb-tabset.

HTML:

<ngb-tabset [activeId]="selectedTab" #tabs (tabChange)="onTabChange($event)">

Manuscrit:

De plus, j'ai dû coder en dur les routes dans la fonction onTabChange.

onTabChange($event: NgbTabChangeEvent) {
    let routes = {
        details: `/prospect/${this.prospectId}/details`,
        appointments: `/prospect/${this.prospectId}/appointments`,
        followups: `/prospect/${this.prospectId}/followups`,
        notes: `/prospect/${this.prospectId}/notes`,
        dials: `/prospect/${this.prospectId}/dials`,
    };

    this.router.navigateByUrl(routes[$event.nextId]);
}
16
Chuck Conway

Cela se produit car vous appelez select on tabs avant même que les onglets aient été initialisés. NgTabset sont initialisés une fois la vue initiée. J'ai utilisé un booléen pour voir s'ils ont été initialisés avant d'appeler select.

    tabsInitialized: boolean = false;
    @ViewChild('tabs') public tabs:NgbTabset;

    ngAfterViewInit() {
     this.tabsInitialized = true;
    }



    ngOnChanges(){
     if(this.tabsInitialized){
      this.tabs.select('dashboard');
    }
   }
...
4
hnameer-GRIT

Si quelqu'un veut le faire à partir du modèle, la meilleure approche est:

<ngb-tabset #tabRef="ngbTabset">
  <ngb-tab title="Tab-1" id="tab1">
     <ng-template ngbTabContent>
       <p> Tab 1 Content</p>
     </ng-template>
  </ngb-tab>
   <ngb-tab title="Tab-2" id="tab2">
     <ng-template ngbTabContent>
       <p> Tab 2 Content</p>
     </ng-template>
  </ngb-tab>
</ngb-tabset>

<div>
  <button class="btn" (click)="tabRef.select('tab2')">Select tab with id tab2</button>
</div>
4
Adrita Sharma

Mettre une référence sur l'élément

<ngb-tabset #tabs>

Utilisez un ViewChild pour contrôler l'onglet

export class PolicyTermsComponent implements OnInit {
  private tabs:NgbTabset;

  @ViewChild('tabs')  public set _tabs(tabs: NgbTabset)
  {
     if(!tabs) return;
     this.tabs = _tabs;
     this.tabs.select('policy');
  }
}

J'ai déplacé l'exécution de la sélection vers un ensemble afin d'être sûr que la page a correctement créé le composant tabs et qu'il peut être référencé et utilisé.

1
misha130

Le problème que vous rencontrez est que vous exécutez le code dans la mauvaise partie de la boucle d'événements. Vous pouvez utiliser le await/async pour pousser le réglage de l'onglet actif à plus tard dans la boucle d'événement avec d'autres micro-tâches

configuration de l'itinéraire .ts

// ... other stuff
{ path: ":id/:tabName", component: ViewTabsComponent },
// ... other stuff

html/balisage

<ngb-tabset #myTabs>
  <ngb-tab title="Terms and Privacy" id="terms">
    <template ngbTabContent>
        <p>content</p>
    </template>
  </ngb-tab>
  <ngb-tab title="Company Policy" id="policy">
    <template ngbTabContent>
      <p>other content<\p>
    </template>
  </ngb-tab>
</ngb-tabset>

contrôleur de composant ts

@ViewChild("myTabs", { static: true, read: NgbTabset }) myTabs: NgbTabset;
async ngOnInit() {
    const params = await this.route.paramMap
        .pipe(
            map((params: ParamMap) => ({ tabName: params.get("tabName") })),
            take(1) // <-- force to complete
        ).toPromise();
    this.myTabs.select(`${params.tabName}`);
}

cela fonctionne avec

  • "@ ng-bootstrap/ng-bootstrap": "^ 5.0.0",
  • "@ angular/common": "^ 8.0.0",
0
Kieran