NgbDatepicker в реактивных формах: установить начальное значение - PullRequest
0 голосов
/ 04 августа 2020

Это может быть одна из самых неприятных проблем, с которыми я справился за последнее время. Даты и, в частности, NgbDatepicker, в целом, немного неудобны для Angular.

Я использую NgbDatepicker против реактивных форм в Angular 8, и суть Моя проблема в том, что я могу установить начальное значение элемента управления датой, но это начальное значение не отображается (визуально) в форме. Я могу зарегистрировать свою форму на консоли и увидеть, что значение устанавливается, но само поле формы не обновляется. Если я выберу дату из самого средства выбора, мой выбор отобразится в поле формы. Я думал, что это будет так же просто, как установить свойство [startDate] ввода ngbDatepicker, но, видимо, нет. Я пробовал много разных вариантов этого; вот где все стоит по коду:

My HTML:

<input #licenseExpiration="ngbDatepicker"
    class="form-control"
    fromControlName="licenseExpiration"
    [startDate]="startDate"
    ngbDatepicker />
<button class="btn btn-info zero-spacing pt-1 pr-1 pl-1"
    (click)="licenseExpiration.toggle()"
    type="button">

Соответствующие биты моего компонента:

@Component({
  selector: 'app-cert',
  templateUrl: './cert.component.html',
  providers: [
    { provide: NgbDateParserFormatter, useClass: CustomDateParserFormatter }
  ]
})
export class CertComponent implements OnInit {
  certForm: CertForm = new CertForm();

  constructor(
    public readonly formatter: CustomDateParserFormatter) { }

  ngOnInit() {
    this.certForm.setModel(...modelObjectFromOtherService...);
  }

  get startDate() {
    return { year: 2020, month: 6, day: 13 };
  }
}

Выше HTML находится в группе formGroup, которая является spe c 'd этим типом CertForm. Эта форма содержит элемент управления для даты и выглядит (частично) следующим образом:

export class CertForm extends FormGroup {
  public dateParser: CustomDateParserFormatter;

  constructor(
    cert: ICertModel = new CertModel()) {
    super({
      ..
      licenseExpiration: new FormControl("", Validators.required),
      ..
    });
  }

  setModel(cert: ICertModel) {
    this.patchValue({
      licenseExpiration
    });
  }

  getModel(): ICertModel {
    const cert = new CertModel();
    ...
    cert.licenseExpiration = this.get("licenseExpiration").value;
    ...
    return cert;
  }
}

Оттуда у меня есть настраиваемый парсер / форматировщик, и он выглядит так же, как тот, который является spe c 'd на страницах примеров NGB:

@Injectable({
  providedIn: "root"
})
export class CustomDateParserFormatter extends NgbDateParserFormatter {

  readonly DELIMITER = '/';

  parse(value: string): NgbDateStruct | null {
    if (value) {
      let date = value.split(this.DELIMITER);
      return {
        day: parseInt(date[0], 10),
        month: parseInt(date[1], 10),
        year: parseInt(date[2], 10)
      };
    }
    return null;
  }

  format(date: NgbDateStruct | null): string {
    return date ? date.month + this.DELIMITER + date.day + this.DELIMITER + date.year : '';
  }
}

И, опять же, похоже, это просто не позволяет мне инициировать это поле даты с видимым начальным значением. Как видите, сейчас я просто жестко кодирую возвращаемое значение для этой даты начала. И эта дата действительно устанавливается правильно - когда вы открываете средство выбора, это дата, на которую он приземляется, но на самом деле он не отображается в поле отображения, когда вы попадаете на страницу. Это просто пусто, пока вы не выберете значение.

Я пробовал так много различных комбинаций идей, но ничего не работает. Это невероятно расстраивает. Я вижу, что варианты / фрагменты этого вопроса уже существуют, но я не могу найти примеров вопроса, который задается именно с этой комбинацией технологий. При использовании NgbDatepicker большинство людей полагаются на шаблонные, а не на реактивные формы.

1 Ответ

1 голос
/ 04 августа 2020
Свойство

startDatae в средстве выбора даты не устанавливает начальное значение. Вы должны установить для вашего formControl желаемое значение.

Это пример без синтаксического анализатора. Я использую собственный синтаксический анализатор / форматировщик на работе, и он действительно работает (не могу опубликовать этот код здесь).

Рабочий stackblitz (обратите внимание, что это последний Angular и Ng Bootstrap) https://stackblitz.com/edit/angular-zpeul4

Компонент приложения

  formGroup = new FormGroup({});

  ngOnInit() {
    console.log('on init');
    this.formGroup.addControl("test", new FormControl({day: 20, month:4, year:1969})) //nice
    this.formGroup.valueChanges.subscribe(val => {
      console.log(val);
    })
    console.log(this.formGroup.value);
  }

Шаблон

 <div class="container" [formGroup]="formGroup">
    
  <input #licenseExpiration="ngbDatepicker"
    class="form-control"
    [formControlName]="'test'"
    ngbDatepicker />

  <button class=""
  (click)="licenseExpiration.toggle()"
  type="button">open</button>

</div>  

Если у вас все еще возникают проблемы с анализатором, убедитесь, что у вас есть оба NgbDateParserFormatter и NgbDateAdapter и что ваше начальное значение, которое вы устанавливаете, может быть правильно преобразовано адаптером (если это не объект даты Ngb)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...