skip to Main Content

I have currently this piece of HTML that is too much duplicated.

<!-- Carte de la Métropole -->
<div>
  <app-carte [nom] = "(( environment.metropole_nom ))"
     [url_couche] = "(( environment.metropole_couche_url ))"
     [layer_couche] = "(( environment.metropole_couche_layer ))"
     [longitude] = "(( environment.metropole_longitude_initale ))"
     [latitude] = "(( environment.metropole_latitude_initale ))"
     [zoom] = "(( environment.metropole_zoom ))"
     [projection] = "(( environment.metropole_projection ))"></app-carte>
</div>

<!-- Régions d'Outremer -->
<div>
  <!-- Carte de la Guadeloupe -->
  <div>
    <app-carte [nom] = "(( environment.guadeloupe_nom ))"
       [url_couche] = "(( environment.guadeloupe_couche_url ))"
       [layer_couche] = "(( environment.guadeloupe_couche_layer ))"
       [longitude] = "(( environment.guadeloupe_longitude_initale ))"
       [latitude] = "(( environment.guadeloupe_latitude_initale ))"
       [zoom] = "(( environment.guadeloupe_zoom ))"
       [projection] = "(( environment.guadeloupe_projection ))"></app-carte>
  </div>

  <!-- Carte de la Martinique -->
  <div>
    <app-carte [nom] = "(( environment.martinique_nom ))"
       [url_couche]="(( environment.martinique_couche_url ))"
       [layer_couche]="(( environment.martinique_couche_layer ))"
       [longitude] = "(( environment.martinique_longitude_initale ))"
       [latitude] = "(( environment.martinique_latitude_initale ))"
       [zoom] = "(( environment.martinique_zoom ))"
       [projection]= "(( environment.martinique_projection ))"></app-carte>
  </div>

  <!-- Carte de la Guyane -->
  <div>
    <app-carte [nom] = "(( environment.guyane_nom ))"
       [url_couche]="(( environment.guyane_couche_url ))"
       [layer_couche]="(( environment.guyane_couche_layer ))"
       [longitude] = "(( environment.guyane_longitude_initale ))"
       [latitude] = "(( environment.guyane_latitude_initale ))"
       [zoom] = "(( environment.guyane_zoom ))"
       [projection]= "(( environment.guyane_projection ))"></app-carte>
  </div>

  <!-- Carte de La Réunion -->
  <div>
    <app-carte [nom] = "(( environment.la_reunion_nom ))"
       [url_couche]="(( environment.la_reunion_couche_url ))"
       [layer_couche]="(( environment.la_reunion_couche_layer ))"
       [longitude] = "(( environment.la_reunion_longitude_initale ))"
       [latitude] = "(( environment.la_reunion_latitude_initale ))"
       [zoom] = "(( environment.la_reunion_zoom ))"
       [projection]= "(( environment.la_reunion_projection ))"></app-carte>
  </div>

  <!-- Carte de Mayotte -->
  <div>
    <app-carte [nom] = "(( environment.mayotte_nom ))"
       [url_couche] = "(( environment.mayotte_couche_url ))"
       [layer_couche] = "(( environment.mayotte_couche_layer ))"
       [longitude] = "(( environment.mayotte_longitude_initale ))"
       [latitude] = "(( environment.mayotte_latitude_initale ))"
       [zoom] = "(( environment.mayotte_zoom ))"
       [projection] = "(( environment.mayotte_projection ))"></app-carte>
  </div>
</div>

After having added a list of the ultramarine regions in its component,

export class CarteFranceComponent {
  protected readonly environment= environment;
  protected regions_outremer: string[] = ['guadeloupe', 'martinique', 'guyane', 'la_reunion', 'mayotte']
}

I’ve attempted something like that:

<div *ngFor="let outremer of regions_outremer;">
  <app-carte [nom] = "(( environment.{{outremer}}_nom ))"
     [url_couche] = "(( environment.{{outremer}}_couche_url ))"
     [layer_couche] = "(( environment.{{outremer}}_couche_layer ))"
     [longitude] = "(( environment.{{outremer}}_longitude_initale ))"
     [latitude] = "(( environment.{{outremer}}_latitude_initale ))"
     [zoom] = "(( environment.{{outremer}}_zoom ))"
     [projection] = "(( environment.{{outremer}}_projection ))"></app-carte>
</div>

but those aren’t recognized statements.

How should I write my *ngFor directive?

2

Answers


  1. You can access the key of an object like environment.guyane_nom as well as environment['guyane_nom']

    So you can tweak the your selector a bit using the template literals with the second way of accessing the property of an object.

    So your ngFor template can be modified as below and it should work.

    <div *ngFor="let outremer of regions_outremer;">
      <app-carte
        [nom]="environment[`${outremer}_nom`]"
        [url_couche]="environment[`${outremer}_couche_url`]"
        [layer_couche]="environment[`${outremer}_couche_layer`]"
        [longitude]="environment[`${outremer}_longitude_initale`]"
        [latitude]="environment[`${outremer}_latitude_initale`]"
        [zoom]="environment[`${outremer}_zoom`]"
        [projection]="environment[`${outremer}_projection`]"
      >
      </app-carte>
    </div>
    

    Edit from Marc Le Bihan:

        <app-carte [nom]="(( environment[outremer + '_nom'] ))"
           [url_couche] = "(( environment[outremer + '_couche_url'] ))"
           [layer_couche] = "(( environment[outremer + '_couche_layer'] ))"
           [longitude] = "(( environment[outremer + '_longitude_initale'] ))"
           [latitude] = "(( environment[outremer + '_latitude_initale'] ))"
           [zoom] = "(( environment[outremer + '_zoom'] ))"
           [projection] = "(( environment[outremer + '_projection'] ))">
        </app-carte>
    

    is the form that eventually works.
    I write it in your reply because you were at a centimeter of the solution. Thanks a lot!

    Login or Signup to reply.
  2. Would say your current environment structure makes it complex.

    You should work with the structure below to avoid complexity:

    {
      guadeloupe: {
        nom: 'guadeloupe_nom',
      },
      martinique: {
        nom: 'martinique_nom',
      },
      guyane: {
        nom: 'guyane_nom',
      },
      la_reunion: {
        nom: 'la_reunion_nom',
      },
      mayotte: {
        nom: 'mayotte_nom',
      },
    }
    

    Transform the existing environment to the new structure with:

    1. Iterate each value from regions_outcomer.

    2. Create an object with the outremer as key.

    3. Get the entry (key-value pair) in the environment that should fall under the same group (require the key to start with outremer key) and make it a sub-object.

    4. This will result in an array of objects. Combine all objects into single object.

    protected readonly environment: { [key: string]: { [key: string]: any } } =
      Object.assign(
        {},
        ...this.regions_outremer.map((outremer) => {
          let keys = Object.keys(environment).filter((y) =>
            y.startsWith(outremer)
          );
    
          let newObj: any = {};
          newObj[outremer] = Object.entries(environment)
            .filter((kvp) => keys.indexOf(kvp[0]) > -1)
            .reduce((acc: any, cur: [string, any]) => {
              acc[cur[0].split(`${outremer}_`)[1]] = cur[1];
    
              return acc;
            }, {} as { [key: string]: any });
    
          return newObj;
        })
      );
    

    For the view, you need to iterate the environment properties via KeyValuePipe.

    <div *ngFor="let outremer of environment | keyvalue;">
      <app-carte [nom]="outremer.value.nom"
        [url_couche]="outremer.value.couche_url"
        [layer_couche] ="outremer.value.couche_layer"
        [longitude]="outremer.value.longitude_initale"
        [latitude]="outremer.value.latitude_initale"
        [zoom]="outremer.value.zoom "
        [projection] = "outremer.value.projection"
          
      ></app-carte>
    </div>
    

    Demo @ StackBlitz

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search