src/lib/directives/clientClickDirective/clientClick.directive.ts
Angular directive to handle the OnClientClick script and the Click event when a button is clicked.
Selector | [wmClientClick] |
constructor(internalEventHandler: InternalEventHandlerService, linkbuttonComponent: LinkButtonComponent, buttonComponent: ButtonComponent)
|
||||||||||||
Creates an instance of ClientClickDirective.
Parameters :
|
commandArgument | |
Type : string
|
|
Gets/sets the commandArgument property. |
commandName | |
Type : string
|
|
Gets/sets the commandName property. |
eventsContext | |
Type : any
|
|
Property used to save the context where the functions need to be executed. Usually it is used as [eventsContext]='this' in the migrated control. |
model | |
Type : any
|
|
Property used to save the model. |
onClientClick | |
Type : string
|
|
Gets/sets the onClientClick property. |
click | ||||
Arguments : '$event'
|
||||
Listener for the click event.
Parameters :
|
clickListener | ||||||
clickListener(event: any)
|
||||||
Decorators :
@HostListener('click', ['$event'])
|
||||||
Listener for the click event.
Parameters :
Returns :
void
|
executeAsJSCode | ||||||
executeAsJSCode(jsCode: string)
|
||||||
Runs JS code that is not calling an external function.
Example:
Parameters :
Returns :
boolean
{boolean} |
getClientClickFunction | ||||||
getClientClickFunction(event: any)
|
||||||
Returns the arrow function to be called and execute the function in the right context.
Parameters :
Returns :
any
{*} |
getFunctionParams | ||||||
getFunctionParams(func: string)
|
||||||
Returns a params collection based on the function name.
Parameters :
Returns :
string[]
{string[]} |
getOnClientClickFunctionCompleteName |
getOnClientClickFunctionCompleteName()
|
Returns the complete function name from JS code.
Example:
Returns :
string
{string} |
getOnClientClickFunctionName | ||||||
getOnClientClickFunctionName(functionCompleteName: string)
|
||||||
Returns the function name without parentheses.
Parameters :
Returns :
string
{string} |
ngOnInit |
ngOnInit()
|
OnInit lifecycle hook.
Returns :
void
|
onClientClickHandler | ||||||
onClientClickHandler(event: any)
|
||||||
Handles the OnClientClick. Validates the scenarios to execute the script correctly and triggers the click if necessary.
Parameters :
Returns :
boolean
{boolean} |
onClientClickHasReturn |
onClientClickHasReturn()
|
Validates if the onClientClick function has a 'return'.
Returns :
boolean
{boolean} |
setButtonServerClick | ||||||
setButtonServerClick(clickEnabled: boolean)
|
||||||
Enables/disables the serverEvent for the button's click.
Parameters :
Returns :
void
|
setControlOutputEvents | ||||||
setControlOutputEvents(clickOutputEnabled: boolean)
|
||||||
Enables/disables the emitter for the button's click.
Parameters :
Returns :
void
|
setThisContext | |||||||||
setThisContext(params: string[], context: any)
|
|||||||||
Changes 'this' to the correct context if it is defined in the function params.
Parameters :
Returns :
any[]
{any[]} |
triggerClick | ||||||
triggerClick(event: any)
|
||||||
Triggers the Click depending on the host component (Button/LinkButton).
Parameters :
Returns :
void
|
triggerClickedInternal |
triggerClickedInternal()
|
Triggers the internal Click event mechanism. This mechanism allows the Button to trigger the DataList's OnItemCommand and the Grid's OnRowCommand events.
Returns :
void
|
triggerClickMechanism | ||||||
triggerClickMechanism(event: any)
|
||||||
Triggers the click mechanism.
Parameters :
Returns :
void
|
commandArgumentInternal |
Type : string
|
Default value : ''
|
Property used to save the commandArgument value. |
Private commandNameInternal |
Type : string
|
Default value : ''
|
Property used to save the commandName value. |
Private onClientClickInternal |
Type : string
|
Default value : ''
|
Property to save the onClientClick value. |
commandName | ||||||
getcommandName()
|
||||||
setcommandName(value: string)
|
||||||
Gets/sets the commandName property.
Parameters :
Returns :
void
|
commandArgument | ||||||
getcommandArgument()
|
||||||
setcommandArgument(value: string)
|
||||||
Gets/sets the commandArgument property.
Parameters :
Returns :
void
|
onClientClick | ||||||
getonClientClick()
|
||||||
setonClientClick(value: string)
|
||||||
Gets/sets the onClientClick property.
Parameters :
Returns :
void
|
import {
Directive,
HostListener,
Input,
OnInit,
Optional
} from '@angular/core';
import { ButtonComponent } from '@mobilize/winforms-components';
import { InternalEventHandlerService } from '../../services';
import { LinkButtonComponent } from '../../components/link-button/link-button.component';
/**
* Angular directive to handle the OnClientClick script and the Click event when a button is clicked.
*
* @export
* @class ClientClickDirective
* @implements {OnInit}
*/
@Directive({
selector: '[wmClientClick]'
})
export class ClientClickDirective implements OnInit {
/**
* Property used to save the model.
*
* @type {*}
* @memberof ClientClickDirective
*/
@Input()
model: any;
/**
* Property to save the onClientClick value.
*
* @private
* @memberof ClientClickDirective
*/
private onClientClickInternal = '';
/**
* Property used to save the context where the functions need to be executed.
* Usually it is used as [eventsContext]='this' in the migrated control.
*
* @type {*}
* @memberof ClientClickDirective
*/
@Input()
eventsContext!: any;
/**
* Property used to save the commandName value.
*
* @private
* @memberof ClientClickDirective
*/
private commandNameInternal = '';
/**
* Gets/sets the commandName property.
*
* @memberof ClientClickDirective
*/
@Input()
set commandName(value: string) {
this.commandNameInternal = value;
}
get commandName(): string {
return this.model.CommandName ?? this.commandNameInternal;
}
/**
* Property used to save the commandArgument value.
*
* @memberof ClientClickDirective
*/
commandArgumentInternal = '';
/**
* Gets/sets the commandArgument property.
*
* @memberof ClientClickDirective
*/
@Input()
set commandArgument(value: string) {
this.commandArgumentInternal = value;
}
get commandArgument(): string {
return this.model.CommandArgument ?? this.commandArgumentInternal;
}
/**
* Gets/sets the onClientClick property.
*
* @memberof ClientClickDirective
*/
@Input()
set onClientClick(value: string) {
this.onClientClickInternal = value;
}
get onClientClick(): string {
return this.model.OnClientClick ?? this.onClientClickInternal;
}
/**
* Creates an instance of ClientClickDirective.
*
* @param {InternalEventHandlerService} internalEventHandler
* @param {LinkButtonComponent} linkbuttonComponent
* @param {ButtonComponent} buttonComponent
* @memberof ClientClickDirective
*/
constructor(
private internalEventHandler: InternalEventHandlerService,
@Optional() private linkbuttonComponent: LinkButtonComponent,
@Optional() private buttonComponent: ButtonComponent
) {}
/**
* OnInit lifecycle hook.
*
* @memberof ClientClickDirective
*/
ngOnInit(): void {
this.setButtonServerClick(false);
this.setControlOutputEvents(false);
}
/**
* Enables/disables the serverEvent for the button's click.
*
* @param {boolean} clickEnabled
* @memberof ClientClickDirective
*/
setButtonServerClick(clickEnabled: boolean): void {
/* c8 ignore else */
if (this.model?.events?.Click != null) {
this.model.events.Click = clickEnabled;
}
}
/**
* Enables/disables the emitter for the button's click.
*
* @param {boolean} clickOutputEnabled
* @memberof ClientClickDirective
*/
setControlOutputEvents(clickOutputEnabled: boolean): void {
/* c8 ignore else*/
if (this.linkbuttonComponent) {
this.linkbuttonComponent.isClickStopped = !clickOutputEnabled;
} else if (this.buttonComponent) {
this.buttonComponent.isClickStopped = !clickOutputEnabled;
}
}
/**
* Listener for the click event.
*
* @param {*} event
* @memberof ClientClickDirective
*/
@HostListener('click', ['$event'])
clickListener(event: any): void {
this.onClientClickHandler(event);
}
/**
* Handles the OnClientClick.
* Validates the scenarios to execute the script correctly and triggers the click if necessary.
*
* @param {*} event
* @return {*} {boolean}
* @memberof ClientClickDirective
*/
onClientClickHandler(event: any): boolean {
const functionCompleteName = this.getOnClientClickFunctionCompleteName();
const functionName =
this.getOnClientClickFunctionName(functionCompleteName);
let response: any;
if (functionCompleteName) {
if (this.eventsContext && this.eventsContext[functionName]) {
const eventFunction = this.getClientClickFunction(event);
response = eventFunction.call(this);
} else {
response = this.executeAsJSCode(this.onClientClick);
}
} else {
this.executeAsJSCode(this.onClientClick);
}
/* c8 ignore else */
if (
(this.onClientClickHasReturn() && response) ||
!this.onClientClickHasReturn()
) {
this.triggerClickMechanism(event);
}
return true;
}
/**
* Returns the arrow function to be called and execute the function in the right context.
*
* @param {*} event
* @return {*} {*}
* @memberof ClientClickDirective
*/
getClientClickFunction(event: any): any {
const functionCompleteName = this.getOnClientClickFunctionCompleteName();
const functionName =
this.getOnClientClickFunctionName(functionCompleteName);
/* c8 ignore start */
return () => {
let params = this.getFunctionParams(functionCompleteName);
params = this.setThisContext(params, event.target);
return this.eventsContext[functionName].call(
this.eventsContext,
...params
);
}; /* c8 ignore stop */
}
/**
* Triggers the click mechanism.
*
* @param {*} event
* @memberof ClientClickDirective
*/
triggerClickMechanism(event: any): void {
this.setButtonServerClick(true);
this.setControlOutputEvents(true);
this.triggerClick(event);
this.setButtonServerClick(false);
this.setControlOutputEvents(false);
this.triggerClickedInternal();
}
/**
* Runs JS code that is not calling an external function.
* Example: `console.log(''); return true;`
*
* @param {string} jsCode
* @return {*} {boolean}
* @memberof ClientClickDirective
*/
executeAsJSCode(jsCode: string): boolean {
/* c8 ignore else */
if (this.eventsContext) {
return new Function(jsCode).call(this.eventsContext);
}
return true;
}
/**
* Returns the complete function name from JS code.
* Example:
* `'return function()'` => `'function()'`.
*
* @return {*} {string}
* @memberof ClientClickDirective
*/
getOnClientClickFunctionCompleteName(): string {
let funcName = '';
/* c8 ignore else */
if (this.onClientClick) {
if (this.onClientClickHasReturn()) {
const init = this.onClientClick.toLowerCase().indexOf('return ') + 6;
const end = this.onClientClick.indexOf(')') + 2;
funcName = this.onClientClick.substring(init, end).trim();
} else if (
/* c8 ignore else */
!this.onClientClickHasReturn() &&
this.onClientClick.includes('(') &&
this.onClientClick.includes(')')
) {
return this.onClientClick;
}
}
return funcName;
}
/**
* Returns the function name without parentheses.
*
* @param {string} functionCompleteName
* @return {*} {string}
* @memberof ClientClickDirective
*/
getOnClientClickFunctionName(functionCompleteName: string): string {
return functionCompleteName
.slice(0, functionCompleteName.indexOf('('))
.trim();
}
/**
* Validates if the onClientClick function has a 'return'.
*
* @return {*} {boolean}
* @memberof ClientClickDirective
*/
onClientClickHasReturn(): boolean {
return this.onClientClick?.trim().toLowerCase().includes('return');
}
/**
* Returns a params collection based on the function name.
*
* @param {string} func
* @return {*} {string[]}
* @memberof ClientClickDirective
*/
getFunctionParams(func: string): string[] {
let params: string[] = [];
/* c8 ignore else */
if (func.includes('(') && func.includes(')')) {
params = func
.slice(func.indexOf('(') + 1, func.indexOf(')'))
.split(',')
.map((param) => {
return param.trim().replace(/'/, '');
});
return params;
}
return params;
}
/**
* Changes 'this' to the correct context if it is defined in the function params.
*
* @param {string[]} params
* @param {*} context
* @return {*} {any[]}
* @memberof ClientClickDirective
*/
setThisContext(params: string[], context: any): any[] {
return params.map((param) => {
/* c8 ignore else */
if (param === 'this') {
return context;
}
return param;
});
}
/**
* Triggers the internal Click event mechanism.
* This mechanism allows the Button to trigger the DataList's OnItemCommand and the Grid's OnRowCommand events.
*
* @memberof ClientClickDirective
*/
triggerClickedInternal(): void {
const clientClickArgs = {
CommandName: this.commandName,
CommandArgument: this.commandArgument,
CommandSource: this.model
};
this.internalEventHandler.onButtonClickEmit({
clientClickArgs,
id: this.model.id
});
}
/**
* Triggers the Click depending on the host component (Button/LinkButton).
*
* @param {*} event
* @memberof ClientClickDirective
*/
triggerClick(event: any): void {
/* c8 ignore else */
if (this.linkbuttonComponent) {
this.linkbuttonComponent.click(event);
} else if (this.buttonComponent) {
this.buttonComponent.click(event);
}
}
}