Différentes façons de transmettre des données aux composants angulaires

Bonjour, Habr! Je vous présente la traduction de l'article «Différentes façons de passer des entrées à un composant en angulaire» par Netanel Basal.

image

Dans cet article, nous analyserons trois façons différentes de transférer des données vers un composant. Dans l'exemple suivant, nous utiliserons select comme composant principal, mais les méthodes qui y sont utilisées sont pertinentes pour d'autres composants.

Créez un composant sélectionné qui reçoit l'entrée suivante - taille et placement .

Utilisation d'entrées


La première méthode que nous connaissons tous consiste à utiliser le décorateur d' entrée .

@Component({
  selector: 'app-select',
  template: `
    <p><b>Size</b> {{ size }}</p>
    <p><b>Placement:</b> {{ placement }}</p>    
    `
})
export class SelectComponent {
  @Input() size: 'sm' | 'md' | 'lg' = 'md';
  @Input() placement: 'top' | 'bottom' | 'right' | 'left'  = 'bottom'
}

Et ce code fonctionne très bien, sauf qu'il n'est pas si flexible. Par exemple, nous devons définir la variable de taille sur grand pour tout sélectionner dans notre application. Par conséquent, nous devons permettre au client de réécrire n'importe quelle entrée globalement.

Utilisation de la dépendance à l'injection


Pour ce faire, nous pouvons utiliser la fonction d'injection de dépendance angulaire.

import { InjectionToken, Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class SelectConfig {
  size: 'sm' | 'md' | 'lg' = 'md'
  placement: 'top' | 'bottom' | 'right' | 'left' = 'bottom';
}

export function setSelectConfig(config: Partial<SelectConfig>) {
  return {
    ...new SelectConfig(),
    ...config
  }
}

Nous devons d'abord créer une configuration de fournisseur. Ce fournisseur peut être utilisé comme jeton , type et également définir des valeurs par défaut pour chaque entrée . Nous l'utilisons dans notre composant sélectionné :

@Component({
  selector: 'app-select',
  template: `
    <p><b>Size</b> {{ size }}</p>
    <p><b>Placement:</b> {{ placement }}</p>    
    `
})
export class SelectComponent {
  @Input() size: SelectConfig['size'];
  @Input() placement: SelectConfig['placement'];

  constructor(private config: SelectConfig) {
    this.size = config.size;
    this.placement = config.placement;
  }
}

Nous pouvons maintenant réécrire les entrées sélectionnées au niveau de notre application:

@NgModule({
  providers: [
    {
      provide: SelectConfig,
      useValue: setSelectConfig({
        size: 'lg'
      })
    }
  ]
  bootstrap: [AppComponent]
})
export class AppModule { }

Mais ce n'est pas tout. Nous pouvons également l'utiliser pour transmettre diverses entrées au niveau du composant. Par exemple, nous avons un composant que nous utilisons plusieurs fois dans l'application. Dans chaque cas, nous devons utiliser la petite valeur :

@Component({
  selector: 'app-todos-page',
  template: `<app-select></app-select>`,
  providers: [
    {
      provide: SelectConfig,
      useValue: setSelectConfig({
        size: 'sm'
      })
    }
  ]
})
export class TodosPageComponent {}

Nous pouvons l'ajouter au composant provider et cette valeur sera utilisée pour tous les composants déclarés et enfants dans les modèles. Mais nous pouvons toujours réécrire cette variable directement comme suit:

@Component({
  selector: 'app-todos-page',
  template: `
   <app-select></app-select>
   <app-select size="lg"></app-select>
`,
  providers: [
    {
      provide: SelectConfig,
      useValue: setSelectConfig({
        size: 'sm'
      })
    }
  ]
})
export class TodosPageComponent {}

La même stratégie est utilisée pour les modules paresseux car elle crée une nouvelle injection.

Utilisation de directives


Supposons que nous ayons des composants avec beaucoup d'entrée. Nous fixons les mêmes valeurs pour la plupart d'entre eux. Dans l'exemple, cela ressemblera à ceci:

<!-- It can be in the same template or in different places in the app -->
<app-select size="lg" position="right" inputThree="someValue"></app-select>
<app-select size="lg" position="right" inputThree="someValue"></app-select>
<app-select size="lg" position="right  inputThree="someValue"></app-select>
<app-select size="lg" position="right" inputThree="someValue"></app-select>
<app-select size="lg" position="right" inputThree="someValue"></app-select>

Nous pouvons répéter ces valeurs, mais nous pouvons créer une directive qui transmettra les valeurs nécessaires de toutes les variables:

@Directive({
  selector: '[selectConfigOne]',
  providers: [{
    provide: SelectConfig,
    useValue: setSelectConfig({
      size: 'lg',
      placement: 'right',
      inputThree: 'someValue'
    })
  }]
})
export class SelectConfigOneDirective {}

Et nous pouvons utiliser cette directive là où nous en avons besoin:

<h1>Using Inputs</h1>
<app-select size="lg"></app-select>
<app-select placement="top"></app-select>

<h1>Using a Directive</h1>
<app-select selectConfigOne></app-select>

<app-todos-page></app-todos-page>

All Articles