diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts
index 4884865bc2..2c06b4bb17 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts
@@ -31,6 +31,7 @@ export class FormFieldTypes {
static PEOPLE: string = 'people';
static BOOLEAN: string = 'boolean';
static NUMBER: string = 'integer';
+ static DATE: string = 'date';
static READONLY_TYPES: string[] = [
FormFieldTypes.HYPERLINK,
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-validator.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-validator.ts
index 7a483c1294..c8170892e3 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-validator.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-validator.ts
@@ -18,6 +18,8 @@
import { FormFieldModel } from './form-field.model';
import { FormFieldTypes } from './form-field-types';
+declare var moment: any;
+
export interface FormFieldValidator {
isSupported(field: FormFieldModel): boolean;
@@ -107,6 +109,106 @@ export class NumberFieldValidator implements FormFieldValidator {
}
}
+export class DateFieldValidator implements FormFieldValidator {
+
+ private supportedTypes = [
+ FormFieldTypes.DATE
+ ];
+
+ // Validates that the input string is a valid date formatted as (default D-M-YYYY)
+ static isValidDate(dateString: string, dateFormat: string = 'D-M-YYYY'): boolean {
+ if (dateString) {
+ let d = moment(dateString.split('T')[0], dateFormat, true);
+ return d.isValid();
+ }
+
+ return false;
+ }
+
+ isSupported(field: FormFieldModel): boolean {
+ return field && this.supportedTypes.indexOf(field.type) > -1;
+ }
+
+ validate(field: FormFieldModel): boolean {
+ if (this.isSupported(field) && field.value) {
+ if (DateFieldValidator.isValidDate(field.value)) {
+ return true;
+ }
+ field.validationSummary = 'Invalid date format';
+ return false;
+ }
+ return true;
+ }
+}
+
+export class MinDateFieldValidator implements FormFieldValidator {
+
+ private supportedTypes = [
+ FormFieldTypes.DATE
+ ];
+
+ isSupported(field: FormFieldModel): boolean {
+ return field &&
+ this.supportedTypes.indexOf(field.type) > -1 &&
+ !!field.minValue;
+ }
+
+ validate(field: FormFieldModel): boolean {
+ if (this.isSupported(field) && field.value) {
+ const dateFormat = 'D-M-YYYY';
+
+ if (!DateFieldValidator.isValidDate(field.value, dateFormat)) {
+ field.validationSummary = 'Invalid date format';
+ return false;
+ }
+
+ // remove time and timezone info
+ let d = moment(field.value.split('T')[0], dateFormat);
+ let min = moment(field.minValue, dateFormat);
+
+ if (d.isBefore(min)) {
+ field.validationSummary = `Should not be less than ${field.minValue}`;
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+export class MaxDateFieldValidator implements FormFieldValidator {
+
+ private supportedTypes = [
+ FormFieldTypes.DATE
+ ];
+
+ isSupported(field: FormFieldModel): boolean {
+ return field &&
+ this.supportedTypes.indexOf(field.type) > -1 &&
+ !!field.maxValue;
+ }
+
+ validate(field: FormFieldModel): boolean {
+ if (this.isSupported(field) && field.value) {
+ const dateFormat = 'D-M-YYYY';
+
+ if (!DateFieldValidator.isValidDate(field.value, dateFormat)) {
+ field.validationSummary = 'Invalid date format';
+ return false;
+ }
+
+ // remove time and timezone info
+ let d = moment(field.value.split('T')[0], dateFormat);
+ var max = moment(field.maxValue, dateFormat);
+
+ if (d.isAfter(max)) {
+ field.validationSummary = `Should not be greater than ${field.maxValue}`;
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
export class MinLengthFieldValidator implements FormFieldValidator {
private supportedTypes = [
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts
index 1e23b380cb..ae71b5b30f 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts
@@ -29,9 +29,13 @@ import {
MaxLengthFieldValidator,
MinValueFieldValidator,
MaxValueFieldValidator,
- RegExFieldValidator
+ RegExFieldValidator,
+ DateFieldValidator,
+ MinDateFieldValidator,
+ MaxDateFieldValidator
} from './form-field-validator';
+declare var moment: any;
export class FormFieldModel extends FormWidgetModel {
@@ -152,7 +156,10 @@ export class FormFieldModel extends FormWidgetModel {
new MaxLengthFieldValidator(),
new MinValueFieldValidator(),
new MaxValueFieldValidator(),
- new RegExFieldValidator()
+ new RegExFieldValidator(),
+ new DateFieldValidator(),
+ new MinDateFieldValidator(),
+ new MaxDateFieldValidator()
];
this.updateForm();
@@ -191,6 +198,19 @@ export class FormFieldModel extends FormWidgetModel {
}
}
+ /*
+ This is needed due to Activiti desplaying/editing dates in d-M-YYYY format
+ but storing on server in ISO8601 format (i.e. 2013-02-04T22:44:30.652Z)
+ */
+ if (json.type === FormFieldTypes.DATE) {
+ if (value) {
+ let d = moment(value.split('T')[0]);
+ if (d.isValid()) {
+ value = d.format('D-M-YYYY');
+ }
+ }
+ }
+
return value;
}
@@ -241,6 +261,14 @@ export class FormFieldModel extends FormWidgetModel {
this.form.values[this.id] = null;
}
break;
+ case FormFieldTypes.DATE:
+ let d = moment(this.value, 'D-M-YYYY');
+ if (d.isValid()) {
+ this.form.values[this.id] = `${d.format('YYYY-MM-DD')}T00:00:00.000Z`;
+ } else {
+ this.form.values[this.id] = null;
+ }
+ break;
default:
if (!FormFieldTypes.isReadOnlyType(this.type)) {
this.form.values[this.id] = this.value;
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/date/date.widget.css b/ng2-components/ng2-activiti-form/src/components/widgets/date/date.widget.css
new file mode 100644
index 0000000000..48a6b82b45
--- /dev/null
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/date/date.widget.css
@@ -0,0 +1,19 @@
+.date-widget {
+ width: 100%;
+}
+
+.date-widget__invalid .mdl-textfield__input {
+ border-color: #d50000;
+}
+
+.date-widget__invalid .mdl-textfield__label {
+ color: #d50000;
+}
+
+.date-widget__invalid .mdl-textfield__label:after {
+ background-color: #d50000;
+}
+
+.date-widget__invalid .mdl-textfield__error {
+ visibility: visible !important;
+}
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/date/date.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/date/date.widget.html
new file mode 100644
index 0000000000..93177998e1
--- /dev/null
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/date/date.widget.html
@@ -0,0 +1,12 @@
+
+
+
+ {{field.validationSummary}}
+
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/date/date.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/date/date.widget.ts
new file mode 100644
index 0000000000..3348865043
--- /dev/null
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/date/date.widget.ts
@@ -0,0 +1,52 @@
+/*!
+ * @license
+ * Copyright 2016 Alfresco Software, Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Component, ElementRef } from '@angular/core';
+import { WidgetComponent } from './../widget.component';
+
+declare let __moduleName: string;
+
+@Component({
+ moduleId: __moduleName,
+ selector: 'date-widget',
+ templateUrl: './date.widget.html',
+ styleUrls: ['./date.widget.css']
+})
+export class DateWidget extends WidgetComponent {
+
+ constructor(private elementRef: ElementRef) {
+ super();
+ }
+
+ setupMaterialComponents(componentHandler: any): boolean {
+ // workaround for MDL issues with dynamic components
+ if (componentHandler) {
+ componentHandler.upgradeAllRegistered();
+ if (this.elementRef && this.hasValue()) {
+ let el = this.elementRef.nativeElement;
+ let container = el.querySelector('.mdl-textfield');
+ if (container) {
+ container.MaterialTextfield.change(this.field.value);
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/index.ts b/ng2-components/ng2-activiti-form/src/components/widgets/index.ts
index cc4dbeb362..ec4c30f78c 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/index.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/index.ts
@@ -32,6 +32,7 @@ import { AttachWidget } from './attach/attach.widget';
import { TypeaheadWidget } from './typeahead/typeahead.widget';
import { FunctionalGroupWidget } from './functional-group/functional-group.widget';
import { PeopleWidget } from './people/people.widget';
+import { DateWidget } from './date/date.widget';
// core
export * from './widget.component';
@@ -56,6 +57,7 @@ export * from './attach/attach.widget';
export * from './typeahead/typeahead.widget';
export * from './functional-group/functional-group.widget';
export * from './people/people.widget';
+export * from './date/date.widget';
export const WIDGET_DIRECTIVES: any[] = [
TabsWidget,
@@ -73,5 +75,6 @@ export const WIDGET_DIRECTIVES: any[] = [
AttachWidget,
TypeaheadWidget,
FunctionalGroupWidget,
- PeopleWidget
+ PeopleWidget,
+ DateWidget
];