diff --git a/ng2-components/ng2-activiti-form/README.md b/ng2-components/ng2-activiti-form/README.md
index 5f025df8a4..e766b05e0b 100644
--- a/ng2-components/ng2-activiti-form/README.md
+++ b/ng2-components/ng2-activiti-form/README.md
@@ -106,8 +106,9 @@ The recommended set of properties can be found in the following table:
| formLoaded | Invoked when form is loaded or reloaded. |
| formSaved | Invoked when form is submitted with `Save` or custom outcomes. |
| formCompleted | Invoked when form is submitted with `Complete` outcome. |
+| executeOutcome | Invoked when any outcome is executed, default behaviour can be prevented via `event.preventDefault()` |
-All `form*` events recieve an instance of the `FormModel` as event argument for ease of development:
+All `form*` events receive an instance of the `FormModel` as event argument for ease of development:
**MyView.component.html**
```html
@@ -124,6 +125,56 @@ onFormSaved(form: FormModel) {
}
```
+#### Controlling outcome execution behaviour
+
+If absolutely needed it is possible taking full control over form outcome execution by means of `executeOutcome` event.
+This event is fired upon each outcome execution, both system and custom ones.
+
+You can prevent default behaviour by calling `event.preventDefault()`.
+This allows for example having custom form validation scenarios and/or additional validation summary presentation.
+
+Alternatively you may want just running additional code on outcome execution without suppressing default one.
+
+**MyView.component.html**
+```html
+
+
+```
+
+**MyView.component.ts**
+```ts
+import { FormOutcomeEvent } from 'ng2-activiti-form';
+
+export class MyView {
+
+ validateForm(event: FormOutcomeEvent) {
+ let outcome = event.outcome;
+
+ // you can also get additional properties of outcomes
+ // if you defined them within outcome definition
+
+ if (outcome) {
+ let form = outcome.form;
+ if (form) {
+ // check/update the form here
+ event.preventDefault();
+ }
+ }
+ }
+
+}
+```
+
+There are two additional functions that can be of a great value when controlling outcomes:
+
+- `saveTaskForm()` - saves current form
+- `completeTaskForm(outcome?: string)` - save and complete form with a given outcome name
+
+**Please note that if `event.preventDefault()` is not called then default outcome behaviour
+will also be executed after your custom code.**
+
## Build from sources
Alternatively you can build component from sources with the following commands:
diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.spec.ts b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.spec.ts
index a55bb0445a..8a2a2911cf 100644
--- a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.spec.ts
+++ b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.spec.ts
@@ -19,7 +19,7 @@ import { it, describe, expect } from '@angular/core/testing';
import { Observable } from 'rxjs/Rx';
import { SimpleChange } from '@angular/core';
import { ActivitiForm } from './activiti-form.component';
-import { FormModel, FormOutcomeModel, FormFieldModel } from './widgets/index';
+import { FormModel, FormOutcomeModel, FormFieldModel, FormOutcomeEvent } from './widgets/index';
import { FormService } from './../services/form.service';
import { WidgetVisibilityService } from './../services/widget-visibility.service';
import { ContainerWidget } from './widgets/container/container.widget';
@@ -582,4 +582,56 @@ describe('ActivitiForm', () => {
expect(formComponent.checkVisibility).toHaveBeenCalledWith(fakeField);
});
+ it('should prevent default outcome execution', () => {
+
+ let outcome = new FormOutcomeModel(new FormModel(), {
+ id: ActivitiForm.CUSTOM_OUTCOME_ID,
+ name: 'Custom'
+ });
+
+ formComponent.form = new FormModel();
+ formComponent.executeOutcome.subscribe((event: FormOutcomeEvent) => {
+ expect(event.outcome).toBe(outcome);
+ event.preventDefault();
+ expect(event.defaultPrevented).toBeTruthy();
+ });
+
+ let result = formComponent.onOutcomeClicked(outcome);
+ expect(result).toBeFalsy();
+ });
+
+ it('should not prevent default outcome execution', () => {
+ let outcome = new FormOutcomeModel(new FormModel(), {
+ id: ActivitiForm.CUSTOM_OUTCOME_ID,
+ name: 'Custom'
+ });
+
+ formComponent.form = new FormModel();
+ formComponent.executeOutcome.subscribe((event: FormOutcomeEvent) => {
+ expect(event.outcome).toBe(outcome);
+ expect(event.defaultPrevented).toBeFalsy();
+ });
+
+ spyOn(formComponent, 'completeTaskForm').and.callThrough();
+
+ let result = formComponent.onOutcomeClicked(outcome);
+ expect(result).toBeTruthy();
+
+ expect(formComponent.completeTaskForm).toHaveBeenCalledWith(outcome.name);
+ });
+
+ it('should check visibility only if field with form provided', () => {
+
+ formComponent.checkVisibility(null);
+ expect(visibilityService.updateVisibilityForForm).not.toHaveBeenCalled();
+
+ let field = new FormFieldModel(null);
+ formComponent.checkVisibility(field);
+ expect(visibilityService.updateVisibilityForForm).not.toHaveBeenCalled();
+
+ field = new FormFieldModel(new FormModel());
+ formComponent.checkVisibility(field);
+ expect(visibilityService.updateVisibilityForForm).toHaveBeenCalledWith(field.form);
+ });
+
});
diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts
index 57bf834072..69865b8a1c 100644
--- a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts
+++ b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts
@@ -26,7 +26,7 @@ import {
import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core';
import { FormService } from './../services/form.service';
-import { FormModel, FormOutcomeModel, FormValues, FormFieldModel } from './widgets/core/index';
+import { FormModel, FormOutcomeModel, FormValues, FormFieldModel, FormOutcomeEvent } from './widgets/core/index';
import { TabsWidget } from './widgets/tabs/tabs.widget';
import { ContainerWidget } from './widgets/container/container.widget';
@@ -116,6 +116,9 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
@Output()
formLoaded: EventEmitter = new EventEmitter();
+ @Output()
+ executeOutcome: EventEmitter = new EventEmitter();
+
form: FormModel;
debugMode: boolean = false;
@@ -185,6 +188,13 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
*/
onOutcomeClicked(outcome: FormOutcomeModel): boolean {
if (!this.readOnly && outcome && this.form) {
+
+ let args = new FormOutcomeEvent(outcome);
+ this.executeOutcome.emit(args);
+ if (args.defaultPrevented) {
+ return false;
+ }
+
if (outcome.isSystem) {
if (outcome.id === ActivitiForm.SAVE_OUTCOME_ID) {
this.saveTaskForm();
@@ -340,6 +350,8 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
}
checkVisibility(field: FormFieldModel) {
- this.visibilityService.updateVisibilityForForm(field.form);
+ if (field && field.form) {
+ this.visibilityService.updateVisibilityForForm(field.form);
+ }
}
}
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-outcome-event.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-outcome-event.model.ts
new file mode 100644
index 0000000000..abb290c072
--- /dev/null
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-outcome-event.model.ts
@@ -0,0 +1,41 @@
+/*!
+ * @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 { FormOutcomeModel } from './form-outcome.model';
+
+export class FormOutcomeEvent {
+
+ private _outcome: FormOutcomeModel;
+ private _defaultPrevented: boolean = false;
+
+ get outcome(): FormOutcomeModel {
+ return this._outcome;
+ }
+
+ get defaultPrevented() {
+ return this._defaultPrevented;
+ }
+
+ constructor(outcome: FormOutcomeModel) {
+ this._outcome = outcome;
+ }
+
+ preventDefault() {
+ this._defaultPrevented = true;
+ }
+
+}
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts
index ce68bdba24..7a28d27c75 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts
@@ -26,3 +26,4 @@ export * from './container-column.model';
export * from './container.model';
export * from './tab.model';
export * from './form-outcome.model';
+export * from './form-outcome-event.model';