2 votes

Comment créer une carte à partir d'une classe afin d'extraire ses propriétés en tant que valeurs ?

J'aimerais créer un lien plus solide entre un modèle Angular et un FormGroup. J'ai pensé à ce qui suit, mais je ne sais pas comment l'exprimer correctement en TypeScript.

Je veux utiliser un objet pour définir les clés de la controls d'un Groupe de formulaires (le premier paramètre de la FormControl constructeur), ainsi que la liaison de l formControlName dans le modèle, en partant d'une classe modèle.

Mon raisonnement est que cela éliminera le "filandreux" ou le soi-disant corde magique découlant de l'utilisation de chaînes de caractères pour les formControlName attribut. De cette façon, la source unique de vérité serait la classe modèle. Cela me permettrait également de remanier facilement cette classe et de mettre à jour toutes les autres références.

Par exemple, j'aurais aimé pouvoir écrire quelque chose comme ceci :

// model class:
class Partner {
  id: string;
  name: string;
}

// some static type SomeType = { id: "id", name: "name" } extends Partner's public properties
// but the values of those properties must equal the property name.

// component:
@Component({
  template: `
    <form [formGroup]="form" (ngSubmit)="onSubmit()" novalidate>
      <!-- notice I'm not using a stringy API like formControlName="id" -->
      <input type="text" [formControlName]="SomeType.id">
      <input type="text" [formControlName]="SomeType.name">
    </form>
`})
class CreatePartnerComponent {
  form = new FormGroup({
    SomeType.id: new FormControl(''),
    SomeType.name: new FormControl('')
  });
}

Merci !

2voto

Il semble que j'aie trouvé un (seul) moyen.

class ModelClass {
  id: string;
  name: string;
}

// for the template I need a literal object that I can access by key
// and provide form control names as strings to bind the formControlName
// directive to, so I declare this inside the component class:

readonly fcName: { [key in keyof ModelClass]: key } = {
  // the problem with this is you need to explicitly declare the properties here and
  // keep this property up to date when you refactor ModelClass, but you still
  // get an error if you forget to, so that's great.
  // Also some IDEs can auto-fill these properties along with the values as well.
  id: 'id',
  name: 'name'
}

// and bind form controls like [formControlName]="fcName.id" and so on,
// in the template, this should be pretty obvious by now.

// and the form group you now declare like this, which
// enforces correct key names based on the model:

form = new FormGroup({
  id: new FormControl(''),
  name: new FormControl('')
} as { [key in keyof ModelClass]: FormControl });

Il n'y a pas d'autre moyen plus élégant de le faire, qui ne nécessite peut-être pas la création d'un fichier de type fcNames (noms des contrôles de formulaire), juste pour lier les noms corrects des contrôles de formulaire dans le modèle ? C'est du code en double que j'aimerais éliminer si possible.

-1voto

IAfanasov Points 121

C'est une très bonne pratique à éviter. magic string . Une solution pourrait être envisagée :

class ModelClass {
    id: string;
    age: number;
}
class MyFormGroup extends FormGroup {
    controls: {
        [key in keyof ModelClass]: AbstractControl;
    };
}
@Component({
    template: `
        <form [formGroup]="form"
              (ngSubmit)="onSubmit()"
              novalidate>
            <input type="text"
                   [formControl]="form.controls.id" />
            <input type="text"
                   [formControlName]="form.controls.age" />
        </form>
    `,
})
class CreatePartnerComponent {
    someEnum = MyFormGroup; // trick to use enum inside the template
    formConfig: { [key in keyof ModelClass]: FormControl } = {
        id: new FormControl(),
        age: new FormControl(),
    };
    form = new FormGroup(this.formConfig) as MyFormGroup;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X