;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/projects/demo/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "../../../out-tsc/e2e",
5 | "module": "commonjs",
6 | "target": "es2018",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/projects/demo/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../../coverage/demo'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/projects/demo/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 | Select a date
3 |
9 |
10 | Selected date: {{ localValue1 }}
11 |
12 |
13 |
14 | Select a time
15 |
21 |
22 | Selected date: {{ localValue2 }}
23 |
24 |
25 |
26 | Select a date and time
27 |
33 |
34 | Selected date: {{ localValue3 }}
35 |
36 |
37 |
--------------------------------------------------------------------------------
/projects/demo/src/app/app.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gillardo/ngx-bootstrap-datetime-popup/1fa36507fbd7819295129be40327a6b96244a1ec/projects/demo/src/app/app.component.scss
--------------------------------------------------------------------------------
/projects/demo/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ApplicationModule } from '@angular/core';
2 | import { TestBed, waitForAsync } from '@angular/core/testing';
3 | import { AppComponent } from './app.component';
4 |
5 | describe('AppComponent', () => {
6 | beforeEach(
7 | waitForAsync(() => {
8 | TestBed.configureTestingModule({
9 | imports: [ApplicationModule],
10 | }).compileComponents();
11 | })
12 | );
13 |
14 | it('should create the app', () => {
15 | const fixture = TestBed.createComponent(AppComponent);
16 | const app = fixture.componentInstance;
17 | expect(app).toBeTruthy();
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/projects/demo/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-root',
5 | templateUrl: './app.component.html',
6 | styleUrls: ['./app.component.scss']
7 | })
8 | export class AppComponent {
9 | public localValue1: Date = null;
10 | public showPicker1 = false;
11 | public localValue2: Date = null;
12 | public showPicker2 = false;
13 | public localValue3: Date = null;
14 | public showPicker3 = false;
15 | }
16 |
--------------------------------------------------------------------------------
/projects/demo/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 | import { FormsModule } from '@angular/forms';
4 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
5 | import { BsDatepickerModule, DatepickerModule } from 'ngx-bootstrap/datepicker';
6 | import { TimepickerModule } from 'ngx-bootstrap/timepicker';
7 | import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
8 | import { DatetimePopupModule } from 'projects/ngx-bootstrap-datetime-popup/src/public-api';
9 |
10 | import { AppComponent } from './app.component';
11 |
12 | @NgModule({
13 | declarations: [AppComponent],
14 | imports: [
15 | BrowserModule,
16 | BrowserAnimationsModule,
17 | FormsModule,
18 | BsDatepickerModule.forRoot(),
19 | DatepickerModule.forRoot(),
20 | TimepickerModule.forRoot(),
21 | BsDropdownModule.forRoot(),
22 | DatetimePopupModule,
23 | ],
24 | bootstrap: [AppComponent],
25 | })
26 | export class AppModule {}
27 |
--------------------------------------------------------------------------------
/projects/demo/src/app/date.component.html:
--------------------------------------------------------------------------------
1 |
26 |
--------------------------------------------------------------------------------
/projects/demo/src/app/date.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, EventEmitter, Input, Output } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'input-date',
5 | templateUrl: './date.component.html'
6 | })
7 |
8 | export class DateComponent {
9 |
10 | @Input()
11 | public name: string;
12 |
13 | @Input()
14 | public showDate = true;
15 |
16 | @Input()
17 | public showTime = false;
18 |
19 | @Input()
20 | public defaultTimeEndOfDay = false;
21 |
22 | @Input()
23 | public appendTo: string = undefined;
24 |
25 | @Input()
26 | public value: Date;
27 |
28 | @Input()
29 | public minDate: Date = null;
30 |
31 | @Input()
32 | public maxDate: Date = null;
33 |
34 | @Input()
35 | public placeholder = '';
36 |
37 | @Output()
38 | public valueChange = new EventEmitter();
39 |
40 | @Input()
41 | public showPicker = false;
42 |
43 | @Output()
44 | public showPickerChange = new EventEmitter();
45 |
46 | public onBlur(value: string) {
47 | console.log('blur event');
48 | }
49 |
50 | public onFocus($event: any) {
51 | $event.stopPropagation();
52 | $event.preventDefault();
53 |
54 | this.showPicker = true;
55 | this.showPickerChange.emit(true);
56 | }
57 |
58 | public onChange(value: string) {
59 | this.valueChange.emit(value);
60 | }
61 |
62 | public onTogglePicker($event, showPicker) {
63 | $event.stopPropagation();
64 | $event.preventDefault();
65 |
66 | this.showPicker = showPicker;
67 | this.showPickerChange.emit(showPicker);
68 | }
69 |
70 | public onPopupChange(val: Date) {
71 | // if we're going from NULL to a DATE default the time to the end of the day
72 | if (this.value == null && val != null && this.defaultTimeEndOfDay) {
73 | val.setHours(23, 59, 59, 0);
74 | }
75 |
76 | this.valueChange.emit(val);
77 |
78 | if (this.showDate === true && this.showTime === false) {
79 | this.showPicker = false;
80 | this.showPickerChange.emit(false);
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/projects/demo/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gillardo/ngx-bootstrap-datetime-popup/1fa36507fbd7819295129be40327a6b96244a1ec/projects/demo/src/assets/.gitkeep
--------------------------------------------------------------------------------
/projects/demo/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/projects/demo/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/projects/demo/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gillardo/ngx-bootstrap-datetime-popup/1fa36507fbd7819295129be40327a6b96244a1ec/projects/demo/src/favicon.ico
--------------------------------------------------------------------------------
/projects/demo/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
ngx-bootstrap-datetime-picker demo
17 |
Demo pages to show features of datetime picker
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/projects/demo/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule)
12 | .catch(err => console.error(err));
13 |
--------------------------------------------------------------------------------
/projects/demo/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /**
22 | * By default, zone.js will patch all possible macroTask and DomEvents
23 | * user can disable parts of macroTask/DomEvents patch by setting following flags
24 | * because those flags need to be set before `zone.js` being loaded, and webpack
25 | * will put import in the top of bundle, so user need to create a separate file
26 | * in this directory (for example: zone-flags.ts), and put the following flags
27 | * into that file, and then add the following code before importing zone.js.
28 | * import './zone-flags';
29 | *
30 | * The flags allowed in zone-flags.ts are listed here.
31 | *
32 | * The following flags will work for all browsers.
33 | *
34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
37 | *
38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
40 | *
41 | * (window as any).__Zone_enable_cross_context_check = true;
42 | *
43 | */
44 |
45 | /***************************************************************************************************
46 | * Zone JS is required by default for Angular itself.
47 | */
48 | import 'zone.js'; // Included with Angular CLI.
49 |
50 |
51 | /***************************************************************************************************
52 | * APPLICATION IMPORTS
53 | */
54 |
--------------------------------------------------------------------------------
/projects/demo/src/styles.scss:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/projects/demo/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: {
11 | context(path: string, deep?: boolean, filter?: RegExp): {
12 | keys(): string[];
13 | (id: string): T;
14 | };
15 | };
16 |
17 | // First, initialize the Angular testing environment.
18 | getTestBed().initTestEnvironment(
19 | BrowserDynamicTestingModule,
20 | platformBrowserDynamicTesting(), {
21 | teardown: { destroyAfterEach: false }
22 | }
23 | );
24 | // Then we find all the tests.
25 | const context = require.context('./', true, /\.spec\.ts$/);
26 | // And load the modules.
27 | context.keys().map(context);
28 |
--------------------------------------------------------------------------------
/projects/demo/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/app",
5 | "types": []
6 | },
7 | "files": [
8 | "src/main.ts",
9 | "src/polyfills.ts"
10 | ],
11 | "include": [
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/projects/demo/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | ],
13 | "include": [
14 | "src/**/*.spec.ts",
15 | "src/**/*.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/projects/demo/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "camelCase"
8 | ],
9 | "component-selector": [
10 | true,
11 | "element",
12 | "kebab-case"
13 | ]
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/README.md:
--------------------------------------------------------------------------------
1 | ## NOTES
2 | - DO NOT USE 5.0.0 THIS IS BROKEN!! PLEASE USE 5.0.1 WITH NGX-BOOTSTRAP 5.0.0. If you require ngx-bootstrap v4+ then continue to use 4.3.0+
3 | - VERSION 6.0.0+ of this library uses a Library template built from Angular/Cli so it will be compatible with Ivy
4 |
5 |
6 | # ngx-bootstrap-datetime-popup
7 | Date and time popup picker using ngx-bootstrap library
8 |
9 | This is currently a very simple date time picker, with only the features i needed for a project that i use this in. Happy to add more features
10 |
11 | 
12 | 
13 | 
14 |
15 | Simple example in demo folder, which can also be found on github pages at https://gillardo.github.io/ngx-bootstrap-datetime-popup/
16 |
17 | To use the component, import the `DatetimePopupModule` via your .ts code, and add it to your modules using `forRoot()` method. You must also import the modules `datepicker`, `timepicker` and `dropdown` from `ngx-bootstrap` as there are services that are used
18 |
19 | ```
20 | import { NgModule } from '@angular/core';
21 | import { FormsModule } from '@angular/forms';
22 | import { BrowserModule } from '@angular/platform-browser';
23 | import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
24 | import { DatepickerModule } from 'ngx-bootstrap/datepicker';
25 | import { TimepickerModule } from 'ngx-bootstrap/timepicker';
26 | import { NgxBootstrapDatetimePopupModule } from 'ngx-bootstrap-datetime-popup';
27 |
28 | import { AppComponent } from './app.component';
29 |
30 | @NgModule({
31 | imports: [
32 | FormsModule,
33 | BrowserModule,
34 | BsDropdownModule.forRoot(),
35 | DatepickerModule.forRoot(),
36 | TimepickerModule.forRoot(),
37 | NgxBootstrapDatetimePopupModule.forRoot()
38 | ],
39 | declarations: [ AppComponent ],
40 | bootstrap: [ AppComponent ]
41 | })
42 | export class AppModule {
43 |
44 | }
45 |
46 | ```
47 |
48 | Now add the component to your HTML.
49 |
50 | ```
51 |
52 | ```
53 |
54 | I have now added code so you can change attributes on the "Clear", "Now" and "Close" buttons. in order to do this, you must use an object that implements the same properties as the INgxBootstrapDatetimePopupButtonOptions interface
55 |
56 | ```
57 | export interface INgxBootstrapDatetimePopupButtonOptions {
58 | // should the button be shown
59 | show: boolean;
60 |
61 | // What text label should it be given
62 | label: string;
63 |
64 | // css classes to be used, default is 'btn btn-sm btn-secondary'
65 | cssClass: string;
66 | }
67 | ```
68 |
69 | The component accepts 3 inputs `closeButton`, `clearButton` and `nowButton`, so you can bind your options like so:
70 |
71 | ```
72 |
73 | ```
74 |
75 | Since i dont really like the style of the ngx-bootstrap datePicker, you can override the css like any other style, here is an example
76 |
77 | This css also overrides the glyphicon icons that are no longer used in bootstrap 4.
78 |
79 | ```
80 | ngx-bootstrap-datetime-popup.dropdown .glyphicon {
81 | display: inline-block;
82 | font: normal normal normal 14px/1 FontAwesome;
83 | font-size: inherit;
84 | text-rendering: auto;
85 | -webkit-font-smoothing: antialiased;
86 | -moz-osx-font-smoothing: grayscale;
87 | }
88 |
89 | ngx-bootstrap-datetime-popup.dropdown timepicker {
90 | display: flex;
91 | justify-content: center;
92 | }
93 |
94 | ngx-bootstrap-datetime-popup.dropdown .bg-faded {
95 | border:0;
96 | background-color: #fff;
97 | }
98 |
99 | ngx-bootstrap-datetime-popup.dropdown datepicker button {
100 | border:0;
101 | background-color: #fff;
102 | }
103 |
104 | ngx-bootstrap-datetime-popup.dropdown datepicker button.active {
105 | background-color: #ddd;
106 | }
107 |
108 | ngx-bootstrap-datetime-popup.dropdown .glyphicon.glyphicon-remove-circle:before {
109 | content: "\f05c";
110 | }
111 |
112 | ngx-bootstrap-datetime-popup.dropdown .glyphicon.glyphicon-chevron-down:before {
113 | content: "\f078";
114 | }
115 |
116 | ngx-bootstrap-datetime-popup.dropdown .glyphicon.glyphicon-chevron-up:before {
117 | content: "\f077";
118 | }
119 |
120 | ngx-bootstrap-datetime-popup.dropdown .glyphicon.glyphicon-chevron-left:before {
121 | content: "\f053";
122 | }
123 |
124 | ngx-bootstrap-datetime-popup.dropdown .glyphicon.glyphicon-chevron-right:before {
125 | content: "\f054";
126 | }
127 |
128 | ngx-bootstrap-datetime-popup.dropdown .glyphicon.hidden {
129 | display: none !important;
130 | }
131 | ```
132 |
133 | If you want more features please create a PR as i am a little struck for time at the moment. Happy coding!
134 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../../coverage/ngx-bootstrap-datetime-popup'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../dist",
4 | "lib": {
5 | "entryFile": "src/public-api.ts"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ngx-bootstrap-datetime-popup",
3 | "version": "5.1.0",
4 | "lockfileVersion": 1
5 | }
6 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ngx-bootstrap-datetime-popup",
3 | "version": "7.0.4",
4 | "description": "Datetime popup component using ngx-bootstrap datePicker, timePicker and bsDropdown",
5 | "keywords": [
6 | "angular",
7 | "angular10",
8 | "aot",
9 | "aot-compatible",
10 | "aot-compilation",
11 | "library",
12 | "ng",
13 | "timepicker",
14 | "datepicker",
15 | "ngx-bootstrap",
16 | "ngx-bootstrap-datetime-popup",
17 | "typescript"
18 | ],
19 | "peerDependencies": {
20 | "@angular/common": "^12.0.0 || ^13.0.0",
21 | "@angular/core": "^12.0.0 || ^13.0.0",
22 | "@angular/forms": "^12.0.0 || ^13.0.0",
23 | "ngx-bootstrap": "^7.0.0"
24 | },
25 | "dependencies": {
26 | "tslib": "^2.0.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/src/lib/ngx-bootstrap-datetime-popup-botton-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface IDatetimePopupButtonOptions {
2 | show: boolean;
3 | label: string;
4 | cssClass: string;
5 | }
6 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/src/lib/ngx-bootstrap-datetime-popup.component.html:
--------------------------------------------------------------------------------
1 |
2 |
42 |
43 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/src/lib/ngx-bootstrap-datetime-popup.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2 |
3 | import { DatetimePopupComponent } from './ngx-bootstrap-datetime-popup.component';
4 |
5 | describe('NgxBootstrapDatetimePopupComponent', () => {
6 | let component: DatetimePopupComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(
10 | waitForAsync(() => {
11 | TestBed.configureTestingModule({
12 | declarations: [DatetimePopupComponent],
13 | }).compileComponents();
14 | })
15 | );
16 |
17 | beforeEach(() => {
18 | fixture = TestBed.createComponent(DatetimePopupComponent);
19 | component = fixture.componentInstance;
20 | fixture.detectChanges();
21 | });
22 |
23 | it('should create', () => {
24 | expect(component).toBeTruthy();
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/src/lib/ngx-bootstrap-datetime-popup.component.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Component,
3 | ElementRef,
4 | EventEmitter, HostListener,
5 | Input,
6 | OnChanges,
7 | Output,
8 | ViewChild
9 | } from '@angular/core';
10 | import { IDatetimePopupButtonOptions } from './ngx-bootstrap-datetime-popup-botton-options.interface';
11 | import { BsDropdownDirective } from 'ngx-bootstrap/dropdown';
12 |
13 | @Component({
14 | selector: 'datetime-popup',
15 | templateUrl: './ngx-bootstrap-datetime-popup.component.html' ,
16 | styles: [
17 | ],
18 | })
19 |
20 | export class DatetimePopupComponent implements OnChanges {
21 |
22 | @ViewChild('dropdown', { static: true })
23 | public dropdown: BsDropdownDirective;
24 |
25 | @Input()
26 | public appendTo: string = undefined;
27 |
28 | @Input()
29 | public value: Date;
30 |
31 | @Output()
32 | public valueChange = new EventEmitter();
33 |
34 | @Input()
35 | public showPopup = false;
36 |
37 | @Output()
38 | public showPopupChange = new EventEmitter();
39 |
40 | @Input()
41 | public showDate = true;
42 |
43 | @Input()
44 | public showTime = true;
45 |
46 | @Input()
47 | public showWeeks = false;
48 |
49 | @Input()
50 | public showMeridian = false;
51 |
52 | @Input()
53 | public showSeconds = false;
54 |
55 | @Input()
56 | public datepickerMode = 'day';
57 |
58 | @Input()
59 | public initDate: Date = null;
60 |
61 | @Input()
62 | public minDate: Date = null;
63 |
64 | @Input()
65 | public maxDate: Date = null;
66 |
67 | @Input()
68 | public dateDisabled: any[] = [];
69 |
70 | @Input()
71 | public nowButton: IDatetimePopupButtonOptions;
72 |
73 | @Input()
74 | public clearButton: IDatetimePopupButtonOptions;
75 |
76 | @Input()
77 | public closeButton: IDatetimePopupButtonOptions;
78 |
79 | @Input()
80 | public minuteStep = 5;
81 |
82 | @Input()
83 | public hourStep = 1;
84 |
85 | @Input()
86 | public secondsStep = 1;
87 |
88 | public localValue: Date = null;
89 | public isOpening = false;
90 | public isDropUp = false;
91 |
92 | constructor(private elementRef: ElementRef) {
93 |
94 | }
95 |
96 | public ngOnChanges(changes: any) {
97 | if (!this.nowButton) {
98 | this.nowButton = { show: true, label: 'Now', cssClass: 'btn btn-secondary btn-sm'};
99 | }
100 |
101 | if (!this.clearButton) {
102 | this.clearButton = { show: true, label: 'Clear', cssClass: 'btn btn-secondary btn-sm'};
103 | }
104 |
105 | if (!this.closeButton) {
106 | this.closeButton = { show: true, label: 'Close', cssClass: 'btn btn-secondary btn-sm'};
107 | }
108 |
109 | // user maybe typing a value into an input box, so would come in as string
110 | if (typeof this.value === 'string') {
111 | // check if the string is a valid date
112 | if (!isNaN(new Date(this.value).getTime())) {
113 | this.localValue = new Date(this.value);
114 | }
115 | } else if (this.value) {
116 | this.localValue = this.value;
117 | }
118 |
119 | if (changes.showPopup && this.dropdown) {
120 | if (changes.showPopup.currentValue === true) {
121 | this.dropdown.show();
122 | } else if (changes.showPopup.currentValue === false) {
123 | this.dropdown.hide();
124 | }
125 | }
126 | }
127 |
128 | @HostListener('window:scroll', [])
129 | @HostListener('window:resize', [])
130 | public onWindowScroll() {
131 | const nativeEl: HTMLElement = this.elementRef.nativeElement;
132 | const clientRect: ClientRect = nativeEl.getBoundingClientRect();
133 | const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
134 | const offsetTop = clientRect.top + window.pageYOffset;
135 | const height = clientRect.height;
136 | const dropdownEl: HTMLElement = nativeEl.children.item(0) as HTMLElement;
137 | const menuEl: HTMLElement = dropdownEl.children.length > 0 ? dropdownEl.children.item(0) as HTMLElement : null;
138 | let menuHeight = this.showDate && this.showTime ? 402 : this.showDate ? 300 : 102;
139 |
140 | if (menuEl != null) {
141 | // get the style
142 | const display = menuEl.style.display;
143 | menuEl.style.display = 'block';
144 |
145 | menuHeight = menuEl.getBoundingClientRect().height;
146 | menuEl.style.display = display;
147 | }
148 |
149 | if ((offsetTop - menuHeight) <= 0) {
150 | this.isDropUp = false;
151 | } else {
152 | this.isDropUp = ((offsetTop + height + menuHeight) > (scrollTop + document.documentElement.clientHeight));
153 | }
154 | }
155 |
156 | public onOpenChange(opened: boolean) {
157 | if (opened === true) {
158 | this.isOpening = true;
159 | this.onWindowScroll();
160 | this.dropdown.show();
161 |
162 | setTimeout(() => this.isOpening = false, 250);
163 | } else {
164 | this.showPopupChange.emit(false);
165 | }
166 | }
167 |
168 | public onNow() {
169 | this.localValue = new Date();
170 | this.onPickerChange('timepicker');
171 | }
172 |
173 | public onClear() {
174 | this.valueChange.emit(null);
175 | }
176 |
177 | public onClose() {
178 | this.showPopupChange.emit(false);
179 | }
180 |
181 | public onOffClick($event: any) {
182 | this.showPopupChange.emit(false);
183 | }
184 |
185 | public onPickerChange(picker: string) {
186 | if (this.isOpening === true) {
187 | return;
188 | }
189 |
190 | if (picker === 'datepicker' && this.value != null) {
191 | const hours = this.value.getHours();
192 | const minutes = this.value.getMinutes();
193 | const seconds = this.value.getSeconds();
194 | const milliseconds = this.value.getMilliseconds();
195 |
196 | this.localValue.setHours(hours, minutes, seconds, milliseconds);
197 | }
198 |
199 | this.valueChange.emit(this.localValue);
200 |
201 | if (this.showDate === true && this.showTime === false) {
202 | this.dropdown.hide();
203 | }
204 | }
205 |
206 | }
207 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/src/lib/ngx-bootstrap-datetime-popup.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule } from '@angular/forms';
4 | import { BsDatepickerConfig, BsDatepickerModule, DatepickerModule } from 'ngx-bootstrap/datepicker';
5 | import { BsDropdownConfig, BsDropdownModule } from 'ngx-bootstrap/dropdown';
6 | import { TimepickerModule } from 'ngx-bootstrap/timepicker';
7 | import { DatetimePopupComponent } from './ngx-bootstrap-datetime-popup.component';
8 | import { OffClickDirective } from './offclick.directive';
9 |
10 | @NgModule({
11 | declarations: [DatetimePopupComponent, OffClickDirective],
12 | imports: [
13 | CommonModule,
14 | FormsModule,
15 | DatepickerModule,
16 | TimepickerModule,
17 | BsDatepickerModule,
18 | BsDropdownModule,
19 | ],
20 | exports: [DatetimePopupComponent],
21 | providers: [BsDatepickerConfig, BsDropdownConfig]
22 | })
23 | export class DatetimePopupModule {}
24 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/src/lib/offclick.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ElementRef, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[offClick]'
5 | })
6 |
7 | export class OffClickDirective implements OnInit, OnDestroy {
8 | @Output()
9 | public offClick = new EventEmitter();
10 |
11 | public eventHandler: any;
12 | constructor(private elementRef: ElementRef) {
13 |
14 | }
15 |
16 | ngOnInit() {
17 | this.eventHandler = ($event: any) => {
18 | $event.stopPropagation();
19 |
20 | if (!this.elementRef.nativeElement.contains($event.target) && $event.target.localName !== 'button') {
21 | this.offClick.emit(null);
22 | }
23 | };
24 |
25 | document.addEventListener('mouseup', this.eventHandler);
26 | }
27 |
28 | ngOnDestroy() {
29 | document.removeEventListener('mouseup', this.eventHandler);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/src/public-api.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Public API Surface of ngx-bootstrap-datetime-popup
3 | */
4 |
5 | export * from './lib/ngx-bootstrap-datetime-popup.component';
6 | export * from './lib/ngx-bootstrap-datetime-popup.module';
7 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js';
4 | import 'zone.js/testing';
5 | import { getTestBed } from '@angular/core/testing';
6 | import {
7 | BrowserDynamicTestingModule,
8 | platformBrowserDynamicTesting
9 | } from '@angular/platform-browser-dynamic/testing';
10 |
11 | declare const require: {
12 | context(path: string, deep?: boolean, filter?: RegExp): {
13 | keys(): string[];
14 | (id: string): T;
15 | };
16 | };
17 |
18 | // First, initialize the Angular testing environment.
19 | getTestBed().initTestEnvironment(
20 | BrowserDynamicTestingModule,
21 | platformBrowserDynamicTesting(), {
22 | teardown: { destroyAfterEach: false }
23 | }
24 | );
25 | // Then we find all the tests.
26 | const context = require.context('./', true, /\.spec\.ts$/);
27 | // And load the modules.
28 | context.keys().map(context);
29 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/lib",
5 | "target": "es2015",
6 | "declaration": true,
7 | "declarationMap": true,
8 | "inlineSources": true,
9 | "types": [],
10 | "lib": [
11 | "dom",
12 | "es2018"
13 | ]
14 | },
15 | "angularCompilerOptions": {
16 | "skipTemplateCodegen": true,
17 | "strictMetadataEmit": true,
18 | "enableResourceInlining": true
19 | },
20 | "exclude": [
21 | "src/test.ts",
22 | "**/*.spec.ts"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/tsconfig.lib.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.lib.json",
3 | "compilerOptions": {
4 | "declarationMap": false
5 | },
6 | "angularCompilerOptions": {
7 | "compilationMode": "partial"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts"
12 | ],
13 | "include": [
14 | "**/*.spec.ts",
15 | "**/*.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/projects/ngx-bootstrap-datetime-popup/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "camelCase"
8 | ],
9 | "component-selector": [
10 | true,
11 | "element",
12 | "kebab-case"
13 | ]
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "downlevelIteration": true,
9 | "experimentalDecorators": true,
10 | "module": "es2020",
11 | "moduleResolution": "node",
12 | "importHelpers": true,
13 | "target": "es2015",
14 | "lib": [
15 | "es2018",
16 | "dom"
17 | ],
18 | },
19 | "angularCompilerOptions": {
20 | "fullTemplateTypeCheck": true,
21 | "strictInjectionParameters": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /*
2 | This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
3 | It is not intended to be used to perform a compilation.
4 |
5 | To learn more about this file see: https://angular.io/config/solution-tsconfig.
6 | */
7 | {
8 | "files": [],
9 | "references": [
10 | {
11 | "path": "./projects/ngx-bootstrap-datetime-popup/tsconfig.lib.json"
12 | },
13 | {
14 | "path": "./projects/ngx-bootstrap-datetime-popup/tsconfig.spec.json"
15 | },
16 | {
17 | "path": "./projects/demo/tsconfig.app.json"
18 | },
19 | {
20 | "path": "./projects/demo/tsconfig.spec.json"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rulesDirectory": [
4 | "codelyzer"
5 | ],
6 | "rules": {
7 | "align": {
8 | "options": [
9 | "parameters",
10 | "statements"
11 | ]
12 | },
13 | "array-type": false,
14 | "arrow-return-shorthand": true,
15 | "curly": true,
16 | "deprecation": {
17 | "severity": "warning"
18 | },
19 | "eofline": true,
20 | "import-blacklist": [
21 | true,
22 | "rxjs/Rx"
23 | ],
24 | "import-spacing": true,
25 | "indent": {
26 | "options": [
27 | "spaces"
28 | ]
29 | },
30 | "max-classes-per-file": false,
31 | "max-line-length": [
32 | true,
33 | 140
34 | ],
35 | "member-ordering": [
36 | true,
37 | {
38 | "order": [
39 | "static-field",
40 | "instance-field",
41 | "static-method",
42 | "instance-method"
43 | ]
44 | }
45 | ],
46 | "no-console": [
47 | true,
48 | "debug",
49 | "info",
50 | "time",
51 | "timeEnd",
52 | "trace"
53 | ],
54 | "no-empty": false,
55 | "no-inferrable-types": [
56 | true,
57 | "ignore-params"
58 | ],
59 | "no-non-null-assertion": true,
60 | "no-redundant-jsdoc": true,
61 | "no-switch-case-fall-through": true,
62 | "no-var-requires": false,
63 | "object-literal-key-quotes": [
64 | true,
65 | "as-needed"
66 | ],
67 | "quotemark": [
68 | true,
69 | "single"
70 | ],
71 | "semicolon": {
72 | "options": [
73 | "always"
74 | ]
75 | },
76 | "space-before-function-paren": {
77 | "options": {
78 | "anonymous": "never",
79 | "asyncArrow": "always",
80 | "constructor": "never",
81 | "method": "never",
82 | "named": "never"
83 | }
84 | },
85 | "typedef-whitespace": {
86 | "options": [
87 | {
88 | "call-signature": "nospace",
89 | "index-signature": "nospace",
90 | "parameter": "nospace",
91 | "property-declaration": "nospace",
92 | "variable-declaration": "nospace"
93 | },
94 | {
95 | "call-signature": "onespace",
96 | "index-signature": "onespace",
97 | "parameter": "onespace",
98 | "property-declaration": "onespace",
99 | "variable-declaration": "onespace"
100 | }
101 | ]
102 | },
103 | "variable-name": {
104 | "options": [
105 | "ban-keywords",
106 | "check-format",
107 | "allow-pascal-case"
108 | ]
109 | },
110 | "whitespace": {
111 | "options": [
112 | "check-branch",
113 | "check-decl",
114 | "check-operator",
115 | "check-separator",
116 | "check-type",
117 | "check-typecast"
118 | ]
119 | },
120 | "component-class-suffix": true,
121 | "contextual-lifecycle": true,
122 | "directive-class-suffix": true,
123 | "no-conflicting-lifecycle": true,
124 | "no-host-metadata-property": true,
125 | "no-input-rename": true,
126 | "no-inputs-metadata-property": true,
127 | "no-output-native": true,
128 | "no-output-on-prefix": true,
129 | "no-output-rename": true,
130 | "no-outputs-metadata-property": true,
131 | "template-banana-in-box": true,
132 | "template-no-negated-async": true,
133 | "use-lifecycle-interface": true,
134 | "use-pipe-transform-interface": true
135 | }
136 | }
137 |
--------------------------------------------------------------------------------