diff --git a/src/Framework/Framework/Resources/Scripts/dotvvm-root.ts b/src/Framework/Framework/Resources/Scripts/dotvvm-root.ts index 1064edfdef..952762ea1b 100644 --- a/src/Framework/Framework/Resources/Scripts/dotvvm-root.ts +++ b/src/Framework/Framework/Resources/Scripts/dotvvm-root.ts @@ -109,6 +109,7 @@ const dotvvmExports = { registerOne: viewModuleManager.registerViewModule, init: viewModuleManager.initViewModule, call: viewModuleManager.callViewModuleCommand, + callNamedCommand: viewModuleManager.callNamedCommand, registerMany: viewModuleManager.registerViewModules }, resourceLoader: { diff --git a/src/Framework/Framework/Resources/Scripts/viewModules/viewModuleManager.ts b/src/Framework/Framework/Resources/Scripts/viewModules/viewModuleManager.ts index 4c2915a88a..d3ad0d75c4 100644 --- a/src/Framework/Framework/Resources/Scripts/viewModules/viewModuleManager.ts +++ b/src/Framework/Framework/Resources/Scripts/viewModules/viewModuleManager.ts @@ -105,6 +105,38 @@ export function callViewModuleCommand(viewIdOrElement: string | HTMLElement, com } } +export function callNamedCommand(viewIdOrElement: string | HTMLElement, commandName: string, args: any[], allowAsync: boolean = true) { + if (compileConstants.debug && commandName == null) { throw new Error("commandName has to have a value"); } + if (compileConstants.debug && !(args instanceof Array)) { throw new Error("args must be an array"); } + + const foundModules: ModuleContext[] = []; + + for (let context of getModules(viewIdOrElement)) { + if (commandName in context.namedCommands && typeof context.namedCommands[commandName] === "function") { + foundModules.push(context); + } + } + + if (compileConstants.debug && !foundModules.length) { + throw new Error(`Named command ${commandName} could not be found in view ${viewIdOrElement}.`); + } + + if (compileConstants.debug && foundModules.length > 1) { + throw new Error(`Conflict: There were multiple named commands ${commandName} in view ${viewIdOrElement}.`); + } + + try { + var result = foundModules[0].namedCommands[commandName](...args.map(v => serialize(v))); + if (!allowAsync && result instanceof Promise) { + throw compileConstants.debug ? `Named command returned Promise even though it was called through _js.Invoke("${commandName}", ...). Use the _js.InvokeAsync method to call commands which (may) return a promise.` : "Command returned Promise"; + } + return result + } + catch (e: unknown) { + throw new Error(`While executing command ${commandName}(${args.map(v => JSON.stringify(serialize(v)))}), an error occurred. ${e}`); + } +} + const globalComponent: { [key: string]: DotvvmJsComponentFactory } = {} export function findComponent( @@ -244,7 +276,7 @@ function mapCommandResult(result: any) { } export class ModuleContext { - private readonly namedCommands: { [name: string]: (...args: any[]) => Promise } = {}; + readonly namedCommands: { [name: string]: (...args: any[]) => Promise } = {}; public module: any; constructor(