2 votes

Angular 5 la liaison de modèle ne fonctionne pas pour le sélecteur de date ng-bootstrap popup

Je tente de créer mon propre composant à partir du sélecteur de date de ng-bootstrap (je ne veux pas tout ce balisage à chaque fois que j'utilise le sélecteur de date).

Le sélecteur de date fonctionne bien tout seul, mais la valeur ne se lie pas à la page où le composant est utilisé.

Voici mon sélecteur de date - copié de la page d'exemple de ng-bootstrap:

Modèle: {{ selectedDate | json }}

Mon composant:

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

@Component({
  selector: 'reo-datepicker-popup',
  templateUrl: './datepicker-popup.component.html',
})
export class DatepickerPopupComponent implements OnInit {

  selectedDate; any;

  constructor() {}

  ngOnInit() {
  }

}

Le composant est utilisé de cette manière:

Il y a d'autres contrôles sur ma page où [(ngModel)] fonctionne comme prévu. Je peux définir une valeur par défaut pour selectedDatePopup dans la page parent - et cette valeur se propagera au sélecteur de date, mais ne remontera pas au parent lorsqu'elle est modifiée.

J'ai essayé @Input() au lieu de [(ngModel)] avec le même résultat. J'ai également vérifié que NgbModule est importé dans chaque module (ngbModule.forRoot() dans le module de l'application), et FormsModule est toujours importé avant NgbModule.

Version d'Angular 5.2.3
Version de ng-bootstrap 1.02

Toute aide est appréciée.

Plunker

5voto

Joel Richman Points 811

Vous devez implémenter ControlValueAccessor sur votre DatePickerPopupComponent. Cela permettra aux formulaires angulaires (template ou réactif) de se lier à votre composant. Votre plnkr ne fonctionne plus. J'ai créé un exemple ici sur StackBlitz. J'ai dû ajouter un code supplémentaire pour traduire la date pour le ngbDatePicker. Il pourrait y avoir une meilleure façon de le faire. Cela devrait suffire pour vous mettre dans la bonne direction.

Voici à quoi le code du composant devrait ressembler :

import { Component, OnInit, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, } from '@angular/forms';

export const DATEPICKER_VALUE_ACCESSOR =  {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => DatePickerComponent),
  multi: true
};

@Component({
  selector: 'app-date-picker',
  templateUrl: './date-picker.component.html',
  providers: [DATEPICKER_VALUE_ACCESSOR]
})
export class DatePickerComponent implements ControlValueAccessor {

  selectedDate: any;
  disabled = false;

  // Function to call when the date changes.
  onChange = (date?: Date) => {};

  // Function to call when the date picker is touched
  onTouched = () => {};

  writeValue(value: Date) {
    if (!value) return;
    this.selectedDate = {
      year: value.getFullYear(),
      month: value.getMonth(),
      day: value.getDate()
    }
  }

  registerOnChange(fn: (date: Date) => void): void {
    this.onChange = fn;
  }

  // Allows Angular to register a function to call when the input has been touched.
  // Save the function as a property to call later here.
  registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }

  // Allows Angular to disable the input.
  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

  // Write change back to parent
  onDateChange(value: Date) {
    this.onChange(value);
  }

  // Write change back to parent
  onDateSelect(value: any) {
    this.onChange(new Date(value.year, value.month - 1, value.day));
  }

}

Markup:

          [[]]

Modèle sur le sélecteur de date: {{ selectedDate | json }}

Mise en œuvre sur un composant :

import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `Bonjour {{name}}!

    C'est le sélecteur de date : 

    Modèle sur le parent : {{ selectedDate | date:'short' }}

  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input() name: string;
  public selectedDate: Date;
  constructor() {
    this.selectedDate = new Date(2018, 1, 1);
  }
}

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