Base solution for your next web application
Open Closed

Angular 2 - Datepicker #2984


User avatar
0
jonas452 created

Hi,

I'm quite the novice regarding angular and typescript so i am sorry for asking such a basic and easy question. However i can't seem to figure this one out.

In a plane modal i want to use the metronic ui datepicker. i've copied this from the metronic example page to my modal.

<div class="input-group date" data-provide="datepicker">
    <input type="text" class="form-control">
    <div class="input-group-addon">
        <span class="glyphicon glyphicon-th"></span>
    </div>
</div>

however it remains a basic text field.

what am i forgetting? Can you point me in the right direction? Thx.

this is my create-employee-modal.component.ts class and html page

import { Component, Injector, OnInit } from '@angular/core';
import { AppComponentBase } from '@shared/common/app-component-base';
import { appModuleAnimation } from '@shared/animations/routerTransition';
import { PersonServiceProxy, EmployeeDto, ListResultDtoOfEmployeeDto } from '@shared/service-proxies/service-proxies';

@Component({
    templateUrl: './employeepanel.component.html',
    animations: [appModuleAnimation()]
})
export class EmployeePanelComponent extends AppComponentBase implements OnInit {

    employees: EmployeeDto[] = [];
    filter: string = '';

    constructor(
        injector: Injector,        
        private _personService: PersonServiceProxy
    ) {
        super(injector);
    }

        ngOnInit(): void {
        this.getEmployee();
    }

    getEmployee(): void {
        this._personService.getEmployees(this.filter).subscribe((result) => {
            this.employees = result.items;
        });
    }

}
<div bsModal #modal="bs-modal" (onShown)="onShown()" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true" [config]="{backdrop: 'static'}">
    <div class="modal-dialog">
        <div class="modal-content">
            <form *ngIf="active" #employeeForm="ngForm" novalidate (ngSubmit)="save()">
                <div class="modal-header">
                    <button type="button" class="close" (click)="close()" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                    <h4 class="modal-title">
                        <span>{{l("CreateNewEmployee")}}</span>
                    </h4>
                </div>
                <div class="modal-body">
                    
                    <div class="form-group form-md-line-input form-md-floating-label no-hint">
                        <input #nameInput class="form-control" type="text" name="name" [(ngModel)]="employee.name" required maxlength="32">
                        <label>{{l("Name")}}</label>
                    </div>

                    <div class="form-group form-md-line-input form-md-floating-label no-hint">
                        <input class="form-control" type="text" name="firstName" [(ngModel)]="employee.firstName" required maxlength="32">
                        <label>{{l("Surname")}}</label>
                    </div>                    

                    <div class="form-group form-md-line-input form-md-floating-label no-hint">
                        <input class="form-control" type="email" name="email" [(ngModel)]="employee.email" required maxlength="255" pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,})+$">
                        <label>{{l("EmailAddress")}}</label>
                    </div>

                    <div class="form-group form-md-line-input form-md-floating-label no-hint">
                        <input class="form-control" type="text" name="phoneNr" [(ngModel)]="employee.phoneNr" >
                        <label>{{l("PhoneNr")}}</label>
                    </div> 

<div class="input-group date" data-provide="datepicker">
    <input type="text" class="form-control">
    <div class="input-group-addon">
        <span class="glyphicon glyphicon-th"></span>
    </div>
</div>
                    <div class="form-group form-md-line-input form-md-floating-label no-hint">                        
                        <input class="form-control"
                                type="date" name="dateOfBirth" [(ngModel)]="employee.dateOfBirth" >
                        
                    </div>                                       

                </div>
                <div class="modal-footer">
                    <button [disabled]="saving" type="button" class="btn btn-default" (click)="close()">{{l("Cancel")}}</button>
                    <button type="submit" class="btn btn-primary blue" [disabled]="!employeeForm.form.valid" [buttonBusy]="saving" [busyText]="l('SavingWithThreeDot')"><i class="fa fa-save"></i> 
                    <span>{{l("Save")}}</span></button>
                </div>
            </form>
        </div>
    </div>
</div>

18 Answer(s)
  • User Avatar
    0
    jonas452 created

    i'm assuming i still have to add some js lib and perhaps some css file. Only i don't know where the right place is to add those. the angular 2 project structure is somewhat a mysterie to me :o

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    In angular2 application, you need to convert your input to datetime picker by jquery in the show method of your modal. It will be basically something like this:

    @ViewChild('dateInput') dateInput: ElementRef;
    
    show(....): void {
        $(this.dateInput.nativeElement).datetimepicker({});
    }
    

    and change your date input to

    <input type="text" #dateInput class="form-control">
    

    Also you might need to add datetimepicker js and css file sto .angular-cli.json file.

    Before writing above code, you can run your app, open your modal and try to convert your input to datetimepicker using

    [code]$('#idOfYourDateField').datetimepicker({});
    

    [/code:1vz9428q] and see if it works.

  • User Avatar
    0
    jonas452 created

    Finaly got around to trying it. Been building this project on my own time ;) It works. thx!

  • User Avatar
    0
    jonas452 created

    Okay, I got the datetimepicker working. No issue. However. the datepicker is an issue.

    <a href="https://ibb.co/ih00WQ">Klembord_afbeelding_2017_04_27_23_54_55<a target='_blank' href='https://nl.imgbb.com/'>upload picture</a><br />

    As you can see. the datepicker isn't showing. here is my angular-cli.json file for clarity sake. everything linked to the datetimepicker has been removed.

    {
      "project": {
        "version": "1.0.0-beta.30",
        "name": "abp-zero-template"
      },
      "apps": [
        {
          "root": "src",
          "outDir": "dist",
          "assets": [
            "assets",
            {
              "glob": "abp.signalr.js",
              "input": "../node_modules/abp-web-resources/Abp/Framework/scripts/libs/",
              "output": "./assets/abp/"
            },
            {
              "glob": "**.*",
              "input": "../node_modules/jtable/lib/localization/",
              "output": "./assets/localization/jtable/"
            },
            {
              "glob": "**.*",
              "input": "../node_modules/bootstrap-select/dist/js/i18n/",
              "output": "./assets/localization/bootstrap-select/"
            },
            {
              "glob": "**.*",
              "input": "../node_modules/timeago/locales/",
              "output": "./assets/localization/jquery-timeago/"
            }
          ],
          "index": "index.html",
          "main": "main.ts",
          "polyfills": "polyfills.ts",
          "test": "test.ts",
          "tsconfig": "tsconfig.json",
          "prefix": "app",
          "mobile": false,
          "styles": [
            "../node_modules/simple-line-icons/css/simple-line-icons.css",
            "../node_modules/font-awesome/css/font-awesome.css",
            "../node_modules/famfamfam-flags/dist/sprite/famfamfam-flags.css",
    
            "../node_modules/bootstrap-select/dist/css/bootstrap-select.css",
            "../node_modules/jquery.uniform/dist/css/default.css",
            "../node_modules/toastr/build/toastr.css",
            "../node_modules/sweetalert/dist/sweetalert.css",
            "../node_modules/jstree/dist/themes/default/style.min.css",
            "../node_modules/jtable/lib/themes/metro/blue/jtable.min.css",
            "../node_modules/morris.js/morris.css",
    
            "../external_libs/Jcrop/css/Jcrop.css",
            "../node_modules/bootstrap-daterangepicker/daterangepicker.css",
            "../node_modules/bootstrap-switch/dist/css/bootstrap3/bootstrap-switch.min.css",                      
    
            "../src/app/shared/core.less",
            "../src/app/shared/layout/layout.less",
    
            "../src/assets/metronic/global/plugins/bootstrap-datepicker/css/bootstrap-datepicker3.standalone.css",  
    
            "styles.css"
          ],
          "scripts": [
            "../node_modules/jquery/dist/jquery.min.js",
            "../node_modules/jquery-migrate/dist/jquery-migrate.min.js",
            "../node_modules/jqueryui/jquery-ui.min.js",
            "../node_modules/js-cookie/src/js.cookie.js",
            "../node_modules/jstree/dist/jstree.min.js",
    
            "../node_modules/bootstrap/dist/js/bootstrap.js",
            "../node_modules/bootstrap-select/dist/js/bootstrap-select.js",
            "../node_modules/tether/dist/js/tether.min.js",
    
            "../node_modules/lodash/lodash.min.js",
            "../node_modules/moment/min/moment.min.js",
    
            "../node_modules/signalr/jquery.signalR.js",
    
            "../node_modules/jtable/lib/jquery.jtable.min.js",
            "../node_modules/jtable/lib/extensions/jquery.jtable.record-actions.js",
            "../external_libs/Jcrop/js/Jcrop.js",
            "../node_modules/morris.js/morris.min.js",
            "../node_modules/raphael/raphael.min.js",
            "../node_modules/jquery-sparkline/jquery.sparkline.min.js",
    
            "../node_modules/toastr/toastr.js",
            "../node_modules/sweetalert/dist/sweetalert-dev.js",
            "../node_modules/block-ui/jquery.blockUI.js",
            "../node_modules/spin.js/spin.min.js",
            "../node_modules/spin.js/jquery.spin.js",
    
            "../node_modules/bootstrap-daterangepicker/daterangepicker.js",
            "../node_modules/jquery-slimscroll/jquery.slimscroll.min.js",
            "../node_modules/timeago/jquery.timeago.js",
            "../node_modules/localforage/dist/localforage.min.js",
            "../node_modules/bootstrap-switch/dist/js/bootstrap-switch.min.js",
            "../node_modules/push.js/push.min.js",
    
            "../node_modules/abp-web-resources/Abp/Framework/scripts/abp.js",
            "../node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.jquery.js",
            "../node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.toastr.js",
            "../node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.blockUI.js",
            "../node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.spin.js",
            "../node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.sweet-alert.js",
            "../node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.moment.js",
    
            "../src/assets/metronic/global/scripts/app.js",
    
            "../src/assets/metronic/global/plugins/bootstrap-datepicker/js/bootstrap-datepicker.js",
    
            "../src/assets/metronic/admin/layout4/scripts/layout.js",
            "../src/assets/metronic/layouts/global/scripts/quick-sidebar.js"
          ],
          "environmentSource": "environments/environment.ts",
          "environments": {
            "dev": "environments/environment.ts",
            "hmr": "environments/environment.hmr.ts",
            "prod": "environments/environment.prod.ts"
          }
        }
      ],
      "addons": [],
      "packages": [],
      "e2e": {
        "protractor": {
          "config": "./protractor.conf.js"
        }
      },
      "lint": [
        {
          "files": "src/**/*.ts",
          "project": "src/tsconfig.json"
        },
        {
          "files": "e2e/**/*.ts",
          "project": "e2e/tsconfig.json"
        }
      ],
      "test": {
        "karma": {
          "config": "./karma.conf.js"
        }
      },
      "defaults": {
        "styleExt": "css",
        "prefixInterfaces": false,
        "inline": {
          "style": false,
          "template": false
        },
        "spec": {
          "class": false,
          "component": true,
          "directive": true,
          "module": false,
          "pipe": true,
          "service": true
        }
      }
    }
    

    I have tried every datepicker css. don't get why it doesnt show up correctly.

    Thx for your help.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Can you share your modal component's html and ts files ?

    Thanks.

  • User Avatar
    0
    jonas452 created

    Sure. Here you go. Thx

    import { Component, ViewChild, Injector, ElementRef, Output, EventEmitter } from '@angular/core';
    import { ModalDirective } from 'ng2-bootstrap';
    import { PersonServiceProxy, EmployeeFullDto } from '@shared/service-proxies/service-proxies';
    import { AppComponentBase } from '@shared/common/app-component-base';
    
    @Component({
        selector: 'createEmployeeModal',
        templateUrl: './create-Employee-modal.component.html'
    })
    export class CreateEmployeeModalComponent extends AppComponentBase {
    
        @Output() modalSave: EventEmitter<any> = new EventEmitter<any>();
    
        @ViewChild('modal') modal: ModalDirective;
        @ViewChild('nameInput') nameInput: ElementRef;
        @ViewChild('dateInput') dateInput: ElementRef;
    
    
        employee: EmployeeFullDto;
    
        active: boolean = false;
        saving: boolean = false;
    
        constructor(
            injector: Injector,
            private _personService: PersonServiceProxy
        ) {
            super(injector);
        }
    
        show(): void {
            this.active = true;
            this.employee = new EmployeeFullDto();        
            this.modal.show();
        }
    
        onShown(): void {
            $(this.dateInput.nativeElement).datepicker({});
            $(this.nameInput.nativeElement).focus();
        }
    
        save(): void {
            this.saving = true;
            this._personService.createEmployee(this.employee[0])
                .finally(() => this.saving = false)
                .subscribe(() => {
                    this.notify.info(this.l('SavedSuccessfully'));
                    this.close();
                    this.modalSave.emit(this.employee);
                });
        }
    
        close(): void {
            this.modal.hide();
            this.active = false;
        }
    }
    
    <div bsModal #modal="bs-modal" (onShown)="onShown()" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true" [config]="{backdrop: 'static'}">
        <div class="modal-dialog">
            <div class="modal-content">
                <form *ngIf="active" #employeeForm="ngForm" novalidate (ngSubmit)="save()">
                    <div class="modal-header">
                        <button type="button" class="close" (click)="close()" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                        <h4 class="modal-title">
                            <span>{{l("CreateNewEmployee")}}</span>
                        </h4>
                    </div>
                    <div class="modal-body">
                        
                        <div class="form-group form-md-line-input form-md-floating-label no-hint">
                            <input #nameInput class="form-control" type="text" name="name" [(ngModel)]="employee.name" required maxlength="32">
                            <label>{{l("Name")}}</label>
                        </div>
    
                        <div class="form-group form-md-line-input form-md-floating-label no-hint">
                            <input class="form-control" type="text" name="firstName" [(ngModel)]="employee.firstName" required maxlength="32">
                            <label>{{l("Surname")}}</label>
                        </div>                    
    
                        <div class="form-group form-md-line-input form-md-floating-label no-hint">
                            <input class="form-control" type="email" name="email" [(ngModel)]="employee.email" required maxlength="255" pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,})+$">
                            <label>{{l("EmailAddress")}}</label>
                        </div>
    
                        <div class="form-group form-md-line-input form-md-floating-label no-hint">
                            <input class="form-control" type="text" name="phoneNr" [(ngModel)]="employee.phoneNr" >
                            <label>{{l("PhoneNr")}}</label>
                        </div> 
    
                        
    
                        <div class="form-group form-md-line-input form-md-floating-label no-hint">
                            <input #dateInput class="form-control" type="text" name="dateInput" [(ngModel)]="employee.dateOfBirth" >
                            <label>{{l("DateOfBirth")}}</label>
                        </div>
    
    
                        
    
                    </div>
                    <div class="modal-footer">
                        <button [disabled]="saving" type="button" class="btn btn-default" (click)="close()">{{l("Cancel")}}</button>
                        <button type="submit" class="btn btn-primary blue" [disabled]="!employeeForm.form.valid" [buttonBusy]="saving" [busyText]="l('SavingWithThreeDot')"><i class="fa fa-save"></i> 
                        <span>{{l("Save")}}</span></button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Your usage seems right at first look. Can you share your project with us. You can send it to <a href="mailto:[email protected]">[email protected]</a>.

    We will take a look at it for you.

    Thanks.

  • User Avatar
    0
    jonas452 created

    Thx, email with a wetransfer link has been sent. I've only recently started on the front end. So the angular project is almost exactly the same as the template project.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Thank you for sharing project with us. It seems like including css files is not working for your project.

    I have followed below steps to use datepicker in your project. You can use npm packages instead of metronic plugins, in that way you can also upgrade your packages easily.

    1. install bootstrap-datepicker using this command
    npm i bootstrap-datepicker --save
    
    1. Then, in your .angular-cli.json change paths to for js:
    "../node_modules/bootstrap-datepicker/dist/js/bootstrap-datepicker.js"
    

    for css:

    "../node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css"
    
    1. Define typing in typings.d.ts by adding below statement
    interface JQuery {
      datepicker(...any): any;
    }
    
    1. In your modal component below code will convert your input to datepicker
    $(this.dateInput.nativeElement).datepicker({
      startDate: '-3d'
    });
    
  • User Avatar
    0
    jonas452 created

    Thx for figuring out a solution for me! Any idea why just adding css/js wasn't okay for the datepicker but it was for the datetimepicker? You never know when i run against this problem again ;)

    Anyway, many thanks for your help!

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    I couldnt figure that out as well :) . Normally you can use files under assets folder without a problem but this might be related to angular-cli.

  • User Avatar
    0
    onecontact created

    Hi!, I follow this steps, and still couldn't see the datepicker :(

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Discussion was long, you had some problems, some of them are OK now. What is the latest situation/problem with the datepicker? How can I help you? Can you share error message if one exists?

  • User Avatar
    0
    michaelhilgers created

    Hi,

    I got some problems with the bootstrap datepicker. If I try the datepicker inside a component it worked. But If I used the datpicker inside a modal it doesn't work. If I change the date inside the modal the "changeDate"event wasn't triggered.

    HTML

    <div *ngIf="mitarbeiterJN">
                        <div class="form-group form-md-line-input no-hint">
                            <label>{{l("StartArbeitsverhaeltnis")}}</label>
                            
                        </div>
                        <div class="input-group date" data-provide="datepicker" data-date-format="dd/mm/yyyy">
                            <input id="datumArbeitsverhaeltnisBeginn" type="text" name="datumArbeitsverhaeltnisBeginn" class="form-control">
                            <div class="input-group-addon">
                                <span class="glyphicon glyphicon-th"></span>
                            </div>
                        </div>
                        <div class="form-group form-md-line-input no-hint">
                            <label>{{l("EndeArbeitsverhaeltnis")}}</label>
                            
                        </div>
                        <div class="input-group date" data-provide="datepicker" data-date-format="dd/mm/yyyy">
                            <input id="datumArbeitsverhaeltnisEnde" type="text" name="endeArbeitsverhaeltnis" class="form-control">
                            <div class="input-group-addon">
                                <span class="glyphicon glyphicon-th"></span>
                            </div>
                        </div>
    .
    .
    .
    </div>
    

    Modal code

    ngAfterViewInit() {
            $('.date').datepicker({
                weekStart: 1,
                format: "dd/mm/yyyy",
                todayHighlight: true,
                todayBtn: "linked"
            });
    
            this.setDatePickerArbeitsverhaeltnisBeginn();
            this.setDatePickerArbeitsverhaeltnisEnde();
        }
    
        setDatePickerArbeitsverhaeltnisBeginn() {
            $('#datumArbeitsverhaeltnisBeginn').datepicker().on("changeDate", e => {
                let day = e.date.getDate();
                let month = e.date.getMonth();
                let year = e.date.getFullYear();
    
                if (day > 0 && month > 0 && month < 13 && year > 1000) {
                    let d = new Date(Date.UTC(year, month, day));
                    this.newMitarbeiter.datumArbeitsverhaeltnisBeginn = moment(d);
                }
            });
    
            //$("#datumArbeitsverhaeltnisBeginn").datepicker('setDate', this.newMitarbeiter.datumArbeitsverhaeltnisBeginn.toDate());
        }
    
        setDatePickerArbeitsverhaeltnisEnde() {
            $('#datumArbeitsverhaeltnisEnde').datepicker().on("changeDate", e => {
                let day = e.date.getDate();
                let month = e.date.getMonth();
                let year = e.date.getFullYear();
    
                if (day > 0 && month > 0 && month < 13 && year > 1000) {
                    let d = new Date(Date.UTC(year, month, day));
                    this.newMitarbeiter.datumArbeitsverhaeltnisEnde = moment(d);
                }
            });
    
            //$("#datumArbeitsverhaeltnisEnde").datepicker('setDate', this.newMitarbeiter.datumArbeitsverhaeltnisEnde.toDate());
        }
    

    Could you help me please ?

    Thanks !

  • User Avatar
    0
    michaelhilgers created

    Any news ?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Sorry, somehow we have missed your question. Can you try to convert your input to datepicker in the onShown event of modal instead of ngAfterViewInit ?

    Thanks.

  • User Avatar
    0
    michaelhilgers created

    Hi,

    Yes it works ! Thanks :D

    But I have to put the whole jQuery Code inside the onShow()-Methode

    onShown(): void { $(this.nameInput.nativeElement).focus();

        $('.date').datepicker({
            weekStart: 1,
            format: "dd/mm/yyyy",
            todayHighlight: true,
            todayBtn: "linked"
        });
    
        $('#datumArbeitsverhaeltnisBeginn').datepicker().on("changeDate", e => {
            let day = e.date.getDate();
            let month = e.date.getMonth();
            let year = e.date.getFullYear();
    
            if (day > 0 && month > 0 && month &lt; 13 &amp;&amp; year &gt; 1000) {
                let d = new Date(Date.UTC(year, month, day));
                this.newMitarbeiter.datumArbeitsverhaeltnisBeginn = moment(d);
            }
        });
    
        $('#datumArbeitsverhaeltnisEnde').datepicker().on("changeDate", e => {
            let day = e.date.getDate();
            let month = e.date.getMonth();
            let year = e.date.getFullYear();
    
            if (day > 0 && month > 0 && month &lt; 13 &amp;&amp; year &gt; 1000) {
                let d = new Date(Date.UTC(year, month, day));
                this.newMitarbeiter.datumArbeitsverhaeltnisEnde = moment(d);
            }
        });
    }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @MichaelHilgers,

    Yes, you need to. That is the disadvantage of using jQuery with angular :)