【问题标题】:JQuery UI Datepicker in angular2Angular2中的JQuery UI Datepicker
【发布时间】:2016-10-07 09:13:48
【问题描述】:


我是 Angular2 的新手。
我正在尝试在 angular2 中实现 JQuery ui datepicker。

我写了一个 datePicker 指令,在那里我启用了 datepicker。在这里我可以选择日期,但很难将所选日期发送到父组件。

为了克服这个问题,我在窗口对象上创建了一个对象并将组件引用传递给该对象。从那里我正在调用组件函数。

我觉得这不是最佳做法。

有人可以帮助我以正确的方式做事吗?

import { Directive, ElementRef, Input, NgZone,HostListener,Output,EventEmitter } from '@angular/core';
    declare  var $:any;
    @Directive({
      selector: '[uiDatePicker]',
     })
    export class UiDatePickerDirective {
      @Input('uiDatePicker') setDate: string;
      @Output() onSelectDate = new EventEmitter();  
      private el: HTMLElement;
      constructor(el: ElementRef,public zone:NgZone) {
        this.el = el.nativeElement;

        window.angularComponentRef = {
          zone: this.zone, 
          component: this
        };
      }

      doEmitDate(dateText:string){
          this.onSelectDate.emit(dateText);
      }
      ngOnInit() {
        $(this.el).datepicker({
         onSelect: function(dateText:string) {
            window.angularComponentRef.component.doEmitDate(dateText);
         }
        });
       }
}

这里我不喜欢使用 window.angularComponentRef.component 对象。因为它只是将引用存储在全局对象中。这对应用程序不利。

【问题讨论】:

    标签: angular angular2-directives


    【解决方案1】:

    import { Directive, ElementRef, Input, forwardRef } from '@angular/core';
    import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
    
    declare var $: any;
    
    export const CUSTOM_INPUT_DATE_PICKER_CONTROL_VALUE_ACCESSOR: any = {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => UiDatePickerDirective),
        multi: true
    };
    
    @Directive({
        selector: '[uiDatePicker]',
        host: { '(blur)': 'onTouched($event)' },
        providers: [CUSTOM_INPUT_DATE_PICKER_CONTROL_VALUE_ACCESSOR]
    })
    export class UiDatePickerDirective implements ControlValueAccessor {
        private innerValue: string;
    
        @Input('changeMonth') changeMonth: boolean = true;
        @Input('changeYear') changeYear: boolean = true;
    
        constructor(private el: ElementRef) {
        }
    
        ngOnInit() {
            $(this.el.nativeElement).datepicker({
                changeMonth: true,
                changeYear: true,
                dateFormat: 'dd/mm/yy'
            }).on('change', (e: any) => {
                this.onChange(e.target.value);
            });
        }
    
    
        public onChange: any = (_:any) => { /*Empty*/ }
        public onTouched: any = () => { /*Empty*/ }
    
        get value(): any {
            return this.innerValue;
        };
    
        //set accessor including call the onchange callback
        set value(v: any) {
            if (v !== this.innerValue) {
                this.innerValue = v;
                this.onChange(v);
            }
        }
    
    
        writeValue(val: string): void {
            this.innerValue = val;
            $(this.el.nativeElement).datepicker("setDate", this.innerValue);
        }
    
        registerOnChange(fn: any): void {
            this.onChange = fn;
        }
    
        registerOnTouched(fn: any): void {
            this.onTouched = fn;
        }
    }
    <input type="text" uiDatePicker [(ngModel)]="note.ValidTo"/>

    这是here的修改版。

    【讨论】:

    • 我已经在我的应用程序中实现了这个解决方案。我面临的一个问题是如何在具有此指令的文本框中务实地设置日期。我正在使用表单生成器来设置数据。
    • 更新 angular 中的 note.ValidTo 变量?
    • 我对此一无所知。这个变量在哪里可用?我试过用谷歌搜索,但没有成功!
    • 我可以通过日期输入字段并在OnInIt()这样的$(this.el.nativeElement).val(value);方法中设置它。但它是一种解决方法。
    • Ngmodel 是指令中使用的变量 angular。您可以使用此属性获取和设置日期。你应该阅读 ngmodel。
    【解决方案2】:

    出于所有意图和目的,您可以使用var self = this 思想和闭包来维护对组件的引用。

    如果您没有在onSelect 回调中进行任何预处理,则可以通过将绑定的doEmitDate 函数作为onSelect 处理程序传递来进一步简化事情。

    import { Directive, ElementRef, Input, NgZone,HostListener,Output,EventEmitter } from '@angular/core';
    declare  var $:any;
    
    @Directive({
      selector: '[uiDatePicker]',
    })
    export class UiDatePickerDirective {
      @Input('uiDatePicker') setDate: string;
      @Output() onSelectDate = new EventEmitter();
      private el: HTMLElement;
    
      constructor(el: ElementRef, public zone: NgZone) {
        this.el = el.nativeElement;
      }
    
      doEmitDate(dateText:string){
        this.onSelectDate.emit(dateText);
      }
    
      ngOnInit() {
        const component = this;
        $(this.el).datepicker({
          onSelect: function(dateText: string) {
            component.doEmitDate(dateText);
          }
        });
    
        // Or if you're not doing anything else in the onSelect callback
        $(this.el).datepicker({
          onSelect: this.doEmitDate.bind(this)
        });
      }
    }
    

    【讨论】:

    • 我认为这是一个简单的答案。你能建议我以 angular2 方式做同样事情的任何其他方法吗?
    • 没有特定于 Angular 的方法来做这样的事情。在这些情况下将元素传递给外部库时,唯一要记住的是使用 ElementRef 获取 nativeElement,而您正在这样做。有时简单的答案就是正确的答案,无需复杂化。
    • 您还可以使用箭头函数简化上下文绑定:onSelect: (date: string) => this.onSelectDate.emit(date)
    • 再注意一点:jQuery组件经常会触发很多angular2变化检测圈。为了防止它,你应该在角度区域(ngZone.runOutside)之外运行 jQuery 绑定
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多