Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transitionTo and handleURL fail silently if triggerEvent is not provided. #333

Open
MichaelPote opened this issue Mar 30, 2022 · 3 comments

Comments

@MichaelPote
Copy link

If you create a new Router() instance and do not create a triggerEvent function on it (eg. router.triggerEvent = function(){}; ) then when you try to use the router via transitionTo or handleURL your route handler functions will not be called, the hidden optional logging function provided as a constructor argument doesnt log any errors, nor does the javascript engine itself. Only the returned Intent object shows a this.triggerEvent is not a function error without any additional information.

Doing a global text search through the entire codebase for "triggerEvent" only returns a function definition in router.d.ts which implies that the function should be implemented inside the router.es.js module but it isnt.

Also reading through the entire README yields no mention of triggerEvent or anything to point towards an issue here.

@MichaelPote
Copy link
Author

MichaelPote commented Mar 30, 2022

I've found another undocumented function: didTransition is not defined either and causes all transitions to be aborted with yet another silent error.

Am I missing something? It seems this project was not meant to be used outside of Ember?

@MichaelPote
Copy link
Author

MichaelPote commented Mar 30, 2022

After a lot of headbashing, I found some code in the Unit Tests which should be explained in the Readme. The Router class provided is not ready to use, you need to extend the class with your own concrete Router class which implements vital functionality. Especially the event handling code which should at least be provided by default.

For anyone stuck on this issue, this is how to properly subclass the Router and provide yourself with a working instance:

import AbstractRouterJS from "router_js";

class RouterJS extends AbstractRouterJS {
	routeDidChange() {}
	routeWillChange() {}
	didTransition() {}
	willTransition() {}

	triggerEvent(handlerInfos,ignoreFailure,name,args) {

			if (!handlerInfos) {
				if (ignoreFailure) {
					return;
				}
				throw new Error("Could not trigger event '" + name + "'. There are no active handlers");
			}

			let eventWasHandled = false;

			for (let i = handlerInfos.length - 1; i >= 0; i--)
			{
				let currentHandlerInfo = handlerInfos[i],
				    currentHandler = currentHandlerInfo.route;

				// If there is no handler, it means the handler hasn't resolved yet which
				// means that we should trigger the event later when the handler is available
				if (!currentHandler)
				{
					if (currentHandlerInfo.routePromise)
					{
						currentHandlerInfo.routePromise.then(function (resolvedHandler)
						{
							if (resolvedHandler.events.hasOwnProperty(name))
							{
								resolvedHandler.events[name].apply(resolvedHandler, args);
							}
						});
					}
					continue;
				}

				if (currentHandler.events && currentHandler.events[name]) {
					if (currentHandler.events[name].apply(currentHandler, args) === true) {
						eventWasHandled = true;
					} else {
						return;
					}
				}
			}

			// In the case that we got an UnrecognizedURLError as an event with no handler,
			// let it bubble up
			if (name === 'error' && (args[0] && args[0].name === 'UnrecognizedURLError')) {
				throw args[0];
			} else if (!eventWasHandled && !ignoreFailure) {
				throw new Error("Nothing handled the event '" + name + "'.");
			}

	}

	getRoute(name) {
	 	throw new Error("getRoute is not defined!");
	}

	updateURL(newUrl) {
		console.log("Updating browser URL to ", url);
		window.history.pushState('', '', url);
	}

	replaceURL(url)	{
		console.log("Replace browser URL with ", url);
		window.history.replaceState('', '', url);
	}
}

@amiramitai
Copy link

I ran into this too.
I found that the following hack gave me the trigger and it satisfied my purposes.

router.triggerEvent = (handlerInfos, ignoreFailure, name, args) => {}
router.routeWillChange = (newTransition) => {};
router.willTransition = (oldRouteInfos, routeInfos, newTransition) => {};
router.routeDidChange = (newTransition) => {};
router.didTransition = (routeInfos) => {
    let {name, params} = routeInfos[0];
    handlers[name].model(params);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants