StivinKing
@StivinKing

Как правильно забрать значение из директивы Datepicker?

Доброго времени суток,

Такой вопрос заинтересовал. Есть директива для Datepicker [saUidatepicker], которая встраивается в input:
<input type="text" class="form-control datepicker" placeholder="Выберите дату" 
[saUiDatepicker]="{
    dateFormat: 'yy-mm-dd',
    defaultDate: '-7d'
    changesMonth: true,
    minRestrict: '#from'
}" (onChange)="change($event, 'dateFrom')">


Для того, чтобы забрать данные из Datepicker прописываю:
(onChange)="change($event, 'dateFrom')"

Можно как-то сделать, чтобы datepicker сам отдавал значение в input в котором он находится?

Сама директива Datepicker:
import {Directive, ElementRef, OnInit, Input, EventEmitter} from '@angular/core';
import {Output} from "@angular/core/src/metadata/directives";

declare var $: any;

@Directive({
    selector: '[saUiDatepicker]'
})
export class UiDatepickerDirective implements OnInit {

    @Input() saUiDatepicker: any;
    @Output() onChange = new EventEmitter<number>();

    constructor(private el: ElementRef) {
    }

    ngOnInit() {
        let onSelectCallbacks = [];
        let saUiDatepicker = this.saUiDatepicker || {};
        let element = $(this.el.nativeElement);

        if (saUiDatepicker.minRestrict) {
            onSelectCallbacks.push((selectedDate)=> {
                $(saUiDatepicker.minRestrict).datepicker('option', 'minDate', selectedDate);
            });
        }
        if (saUiDatepicker.maxRestrict) {
            onSelectCallbacks.push((selectedDate)=> {
                $(saUiDatepicker.maxRestrict).datepicker('option', 'maxDate', selectedDate);
            });
        }

        //Let others know about changes to the data field
        onSelectCallbacks.push((selectedDate) => {
            element.triggerHandler("change");

            let form = element.closest('form');

            if (typeof form.bootstrapValidator == 'function') {
                try {
                    form.bootstrapValidator('revalidateField', element);
                } catch (e) {
                    console.log(e.message)
                }
            }
        });

        let options = $.extend(saUiDatepicker, {
            prevText: '<i class="fa fa-chevron-left"></i>',
            nextText: '<i class="fa fa-chevron-right"></i>',
            onSelect: (selectedDate) => {
                onSelectCallbacks.forEach((callback) => {
                    callback.call(callback, selectedDate)
                });
                this.onChange.emit(selectedDate);
            }
        });

        System.import('script!jquery-ui-npm/jquery-ui.min.js').then(() => {
            element.datepicker(options);
        });
    }
}
  • Вопрос задан
  • 629 просмотров
Решения вопроса 1
Обычно такие кастомные директивы делают совместимыми с инструментами для работы с формами - делают кастомными контролами формы через реализацию интерфейса ControlValueAccessor
custom-form-controls-in-angular-2

Еще могу увлекательную статью на тему форм посоветовать, где применяется подобная техника
Building Tesla's battery range calculator with Ang...

Вот пример того, как это можно реализовать для datepicker (Plunker)

@Component({
  selector: 'saUiDatepicker',
  template: `<input type="text" #input class="form-control datepicker" placeholder="{{placeholder}}" [(ngModel)]="value" (blur)="onBlur()">`,
  providers: [CUSTOM_UI_DATEPICKER_CONTROL_VALUE_ACCESSOR]
})
export class UiDatepickerComponent implements OnInit, ControlValueAccessor {
  private innerValue: any = '';

  private onTouchedCallback: () => void = () => { };
  private onChangeCallback: (_: any) => void = () => { };

  get value(): any {
    return this.innerValue;
  };

  set value(newValue: any) {
    if (newValue === this.innerValue) return;

    this.innerValue = newValue;
    this.onChangeCallback(newValue);
  }

  @Input() options: any;
  @Input() placeholder: any;

  @ViewChild('input') el: ElementRef;

  onBlur() {
    this.onTouchedCallback();
  }

  writeValue(value: any) {
    if (value !== this.innerValue) {
      this.innerValue = value;
    }
  }

  registerOnChange(fn: any) {
    this.onChangeCallback = fn;
  }

  registerOnTouched(fn: any) {
    this.onTouchedCallback = fn;
  }

  ngOnInit() {
    let options = $.extend(this.options || {}, {
      onSelect: (selectedDate) => {
        this.onChangeCallback(selectedDate);
      }
    });

    System.import('jquery-ui').then(() => {
      const datePicker = $(this.el.nativeElement).datepicker(options);
      if (this.value) {
        datePicker.datepicker("setDate", this.value);
      }
    });
  }
}


Использование в template-driven forms
<form #templateForm="ngForm" (ngSubmit)="submit(templateForm.value)">
  <saUiDatepicker name="data" [(ngModel)]="data" [options]="{...}" 
         placeholder="Выберите дату"></saUiDatepicker>    
  <button type="submit">Submit</button>
</form>

И reactive/model-driven forms

<form [formGroup]="reactiveForm">
   <saUiDatepicker formControlName="data" [options]="{...}" 
       placeholder="Выберите дату"></saUiDatepicker>  
    <pre>{{ reactiveForm.value | json }}</pre> 
</form>

constructor(private fb: FormBuilder) {}
  
ngOnInit() {
  this.reactiveForm = this.fb.group({
      data: ''
  });
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы