4
votes

Pas à pas de matériau angulaire avant le changement de sélection et empêcher le changement d'étape pour certaines conditions

J'utilise un tapis pas à pas linéaire.

Cela fonctionne bien avec next. Je fais un appel à l'API et si c'est un succès, j'appelle l'événement stepper-next au lieu d'utiliser la directive matStepperNext.

Désormais, lorsque l'utilisateur remplit toutes les données à l'étape 1 et clique directement sur une autre étape dans l'en-tête r de la suivante (ou sur toute autre en mode d'édition d'enregistrement), il rediriger vers l'étape suivante car le formulaire est valide.

Je souhaite effectuer un appel de service avant cela et empêcher le changement d'étape jusqu'à ce que l'appel de service soit réussi , il devrait alors être redirigé vers l'étape suivante, sinon il ne devrait pas.

/ p>

Je ne trouve aucune méthode pour implémenter cette fonctionnalité dans doc.

Quelqu'un peut-il me suggérer quoi faire. Je ne veux pas désactiver le clic d'en-tête.


4 commentaires

L'avez-vous résolu?


Nan. Je n'ai toujours pas trouvé de solution


Une résolution encore, j'ai actuellement le même problème?


Non. Actuellement, le stepper n'a pas cette fonctionnalité


4 Réponses :


0
votes

Vous pouvez essayer d'utiliser les attributs editable et completed sur mat-step .

Voir https://material.angular.io/components/stepper/ présentation # editable-step

Sans voir d'exemple, une solution consiste à:

  1. définissez l'attribut editable sur false pour toutes les autres étapes pendant que l'appel de service est en cours
  2. suivez les clics jusqu'à mat-step et conservez cette valeur pour que vous sachiez où l'utilisateur a l'intention d'aller
  3. définissez l'attribut editable sur true lorsque l'appel de service réussit ou échoue (selon la manière dont vous souhaitez traiter les erreurs)
  4. Passer par programme à l'étape suivie au n ° 2

2 commentaires

À partir de quel événement je peux le faire. Lorsque je clique sur l'en-tête de l'étape, il sera redirigé vers cette étape.


Bien, j'ai mal compris votre question. À ce stade, vous pouvez soit essayer de faire quelque chose en désactivant pointer-events (voir stackoverflow.com/questions/46933953/... ) dont je ne suis pas amoureux ou faire une étiquette d'étape personnalisée via ng-template et en le faisant couvrir tout l'espace d'en-tête (c'est aussi un hack), voir stackblitz.com/angular / jbbpbonlbpe



1
votes

Je ne suis pas sûr que ce soit le meilleur mode, mais cela fonctionne pour moi. Les suggestions sont les bienvenues.

1) Rendre le mat-stepper linéaire

reset(stepper?: MatStepper) {
  this.desiredServiceFormGroup.addControl('x', new FormControl('', [Validators.required]));
  stepper.reset();
}

2) Rendre les étapes non modifiables, non facultatives et associer un stepControl à un FormGroup

XXX

3) ajoutez des contrôles à votre FormGroup pour vos éléments de formulaire décrits en HTML et ajoutez un contrôle supplémentaire, pour un contrôle de formulaire inexistant sur votre code html (dans cet exemple, j'ai ajouté le contrôle appelé ' x ', inexistant dans mon code html)

async createVerification(targetId: number, stepper?: MatStepper) {

  this.verification = await this.dataService.createVerification(targetId);

  if (stepper !== undefined) {
    this.desiredServiceFormGroup.removeControl('x');
    stepper.next();
  }

}

Avec ce validateur supplémentaire, votre stepControl sera toujours faux. Lorsque stepControl est false, step n'est pas optionnel, non modifiable et stepper est linéaire, les clics directs sur les en-têtes de pas ne modifient pas l'étape actuelle.

5) le bouton ne sera pas associé à formControl (dans ce cas, il sera toujours désactivé). Dans mon cas, je vérifie chaque élément de formulaire manuellement

<button [disabled]="desiredTarget == null || !paymentAgreed" (click)="createVerification(desiredTarget.targetId, stepper)">NEXT</button>

6) effectuez les opérations nécessaires et lorsque cela est fait, supprimez le contrôle supplémentaire qui rend toujours invalide votre contrôle de formulaire, eto passez par programme à l'étape suivante.

ngOnInit() {

  this.desiredServiceFormGroup = this.formBuilder.group({
    desiredTarget: [ '', Validators.required],
    paymentAgreed: ['', Validators.required],

    ...

    x: ['', Validators.required]
  });

}

7) si vous avez besoin de réinitialiser le stepper, rappelez d'ajouter le contrôle supplémentaire à FormControl

  <mat-step [editable]="false" [optional]="false" [stepControl]="desiredServiceFormGroup">

    <form [formGroup]="desiredServiceFormGroup">

      ...

    </form>

  </mat-step>


0 commentaires

0
votes

Voici une suggestion de travail basée sur la réponse de Sam Tsai qui est la meilleure que j'ai trouvée. J'utilise simplement une valeur "step" est le code et uniquement les boutons normaux pour la navigation.

Vous pouvez revenir en arrière et en avant uniquement si vous avez les bons boutons (je veux dire, il n'est pas possible de changer l'étape en cliquant sur les étapes). Cela signifie que vous effectuez la première étape, puis la deuxième étape et ainsi de suite.

L'exemple de travail est ici: https://stackblitz.com/edit/angular-tznwxe

L'astuce consiste à appeler goStep (x) x est l'étape commençant à 1. Vous pouvez améliorer cela en ajoutant un goNext () et un goPrevious () qui est trivial.

Notez que le "selectedIndex" du stepper doit être changé avec un setTimeout () : il s'agit d'un bug connu discuté ici: https://github.com/angular/components/issues/8479#issuecomment-444063732


0 commentaires

0
votes

Voici comment vous pouvez avoir un contrôle total à ce sujet. Prouvé, fonctionne. pour "@ angular / cdk": "8.2.3" , je ne suis pas sûr d'une version future, peut-être qu'ils ont une fonctionnalité intégrée pour cela.

Réponse courte : Une fois que vous avez rendu le composant stepper sur la page. Vous devez parcourir toutes les étapes du stepper et remplacer la méthode intégrée select () de chaque étape par votre propre version.

Que ferez-vous dans votre propre version?

  • faire quelques calculs
  • faire des appels de service
  • tout ce que vous voulez
  • modifiez currentStepIndex si vous souhaitez que l'utilisateur passe à la nouvelle étape

Réponse longue:

HTML:

// I personally do this in ngAfterViewInit() method
setTimeout(() => {
    this.stepper.steps.forEach((step, idx) => {
        step.select = () => {
            // Your custom code here
            // if you want to change step do execute code below
            this.selectedStepIndex = idx;
        };
    });
});

Dans Controller:

@ViewChild('stepper', { static: false }) stepper: MatStepper;

Une fois que votre stepper est rendu sur la page, vous pouvez remplacer la méthode select comme ceci:

<mat-horizontal-stepper [selectedIndex]="selectedStepIndex" #stepper>


0 commentaires