tehshrike / abstract-state-router Goto Github PK
View Code? Open in Web Editor NEWLike ui-router, but without all the Angular. The best way to structure a single-page webapp.
Home Page: http://tehshrike.github.io/state-router-example
Like ui-router, but without all the Angular. The best way to structure a single-page webapp.
Home Page: http://tehshrike.github.io/state-router-example
I was reminded by @crissdev in this tweet that there need to be documentation somewhere on creating renderers.
Right now the best places to look are
But there needs to be better documentation.
It should be added to this file
As phrased by @daytonlowell:
huh, totally annoying thing I just now noticed. If you're on state A and scroll down the page and then go to state B, you won't be taken back to the top when state B loads.
A reasonable question that needs a reasonable answer written down somewhere (I know I've answered it a couple times before in chats, so it really needs to be documented).
There are other general questions like this that I know need answers, so I'm thinking there should be a new markdown file at the root of the repo named "reasonable-questions.md" or something, and a list of questions linking to the answers in that file at the bottom of readme.md.
Pull requests accomplishing any of the above bits should be opened against the server-side-rendering branch.
I really need to have fake states in the route just for grouping pages.
Currently, we should implement new state and render page with one uiView tag, it looks too complicated and we should have an extra rending pass. Also, our URL became too long.
How I want, example:
A.B.C.D - /a/b/d
A.B.C.E - /a/b/e
but if we will check state to highlight an item in menu A.B.C will be 'active' for both path. C here is the empty state, just for grouping. For .E and .D uiView tag will be from A.B state.
In this case, we still have one path for one state but now possible to use different levels in URL and in the state.
In vue-router some part of similar problem solved by named-views - https://router.vuejs.org/en/essentials/named-views.html
and other by alias.
Right now abstract-state-router doesn't require any transforms (beyond CommonJS module resolution) to run in an ES5 environment.
ES2015 spreads and spreads, and at this point I feel like most people using abstract-state-router are probably already transpiling to ES5 if they want to support IE11 or older. Certainly anyone using Webpack is, and anyone using Browserify would continue having no problem, as long as the appropriate transforms were added to the package.json.
What could/should be done during such an upgrade? Things that come to mind are
const
and arrow functions and object destructuringresolve
function to take an arguments object instead of two ordered arguments before the callback (probably should have been that way already)You should be able to set default parameters that will get applied to the route parameters if you do stateRouter.go('someState')
or if a default child state is loaded.
defaultQuerystringParameters
may already be applied to route parameters, in which case its name (and the documentation) should be updated.
How can I handle the urls that are not found?
This is one of my diversions from ui-router behavior that I regret.
Right now, you can pass whatever parameters into stateRouter.go
or stateRouter.makePath
and they will get put into the url and show up on the parameters object, even if no state depends on them.
I think that if you attempt to create a route, or if you try to navigate to a route, and you use any parameters that are not used by any of the states at the route you're going to, then those parameters should just be dropped and shouldn't show up in the url.
This could be accomplished with only a feature bump if a new option was added to stateRouter
initialization, something like allowParametersNotUsedByAnyState
or whatever. It could default to true
(the current behavior).
Eventually, we could log a deprecation warning when that value was true
, and eventually eventually we could flip the default to false
.
Any thoughts?
The following link if navigated directly displays a blank page.
http://tehshrike.github.io/state-router-example/implementations/ractive/index.html#/app/topics/
Reported in TehShrike/riot-state-renderer#5 , I have added some failing tests in the change-route-on-default-child branch.
app
state has the defaultChild
: default-child-state
app
state has a template
stateRouter.evaluateCurrentState('app')
on an invalid routestateRouter.evaluateCurrentState('app.default-child-state')
on an invalid path, and app.default-child-state
is loadedWhen adding a state that includes a named parameter eg /user/:userId
, if the named parameter portion of the url includes a dot (eg. /user/123.345) you get the error Cannot GET <path>
(see screenshot)
Route code
stateRouter.addState({
name: 'app.user',
route: 'user/:userId',
template: User,
resolve: (data, parameters, cb) => {
const {userId} = parameters;
cb(undefined, { userId });
}
});
Result
If the first argument to state.go
is not a string, then it should behave as if you had passed in the name of the current state.
Discussion point: should the "current state" be the last state that the router started transitioning to, or should it be the last state that was fully loaded?
Put another way, if you call redirect({ someParameter: 'some other option' })
inside a resolve
function, should it redirect you to the state that was in the middle of being loaded, or the state before that?
I'm leaning towards the state that you're in the middle of transitioning to, but I'm open to other arguments.
Failing test committed in 9739c39
Fails with an error:
/Users/josh/code/abstract-state-router/index.js:279
throw e
^
Error: Must supply argument someParam for path /parent/:someParam/yarp/child1
at /Users/josh/code/abstract-state-router/node_modules/page-path-builder/index.js:17:11
Reported by @daytonlowell
On Twitter, Ryan Grove brought up the need to painlessly lazy-load route modules.
On the surface, this seems like it would be easy to implement. The state's template
property could be a promise-returning function that would return the real template object. Exactly how the function would go out and get the template/code would be an implementation detail that would depend on the bundler the consumer was using.
In practice, I don't feel comfortable writing out specs until I know of at least one (probably Webpack) user willing to give some real use case details here so that I could be sure that the solution I've thought of would solve a real problem.
So, if you're some Webpack user (or anyone else with a lazy-load-friendly bundler that you want to use) and you want this feature, let me know here! I'm willing to implement it if the complexity doesn't get out of hand.
Hi,
As a hobbiest i am writing a custom app for myself that i want alot of things to do. Ui router in Angular is fine and all but i want a custom one because i dont like angular and its move to 2.0.
I want to know what your Ui-router comes out of the box off and if you could give me some help in setting this up for my project
in the attached image i showed you what in projects what i want to develop see as the most commen thing to do for apps yet i was anable to find it if i was good in JS i would be able to pull it off. Thats why im so dependant on good libraries or framework. I do believe though that if you look at my request it can benefit your state router for helping designers like me who arent coders at heart to build a View
regardless of that hats off on making and contributing so much to the open source community
kind regards
Get all the files in this gist
Host them on localhost
Browse to asr-bug.html
Change the hash to #/room/new
...Note that you see room/new
Refresh the page
...Note that you see room/:room
Expected behavior:
URLs should be deterministic, and always send you to the same state
I've found this solution to fix the problem:
in default-router-options.js:
var defaultRouterOptions = module.exports = { "reverse":true}
instead of:
{ "reverse":true}
Great initiative but i noticed a bug.
I have a route route: '/:entity/new'
When i navigate to /one_entity/new
, the associated state is activated and rendered.
Then i navigate to /another_entity/new
, the associated state is not reactivated since its the same route.
Hence the view (riot tag in my case) does not get updated.
As per title, I cannot get the following scenario to work.
stateRouter.addState({
name: "app.foo",
route: "/foo/",
template: {},
defaultChild: "view"
})
stateRouter.addState({
name: "app.foo.view",
route: "",
template: {},
})
stateRouter.addState({
name: "app.foo.edit",
route: "edit",
template: {},
})
When I am on a page that has a link asr.go("app.foo")
, the url correctly shows as /foo/
, but the browser goes to /foo
, and nothing renders. If I manually change the url to /foo/
, it renders. I have tried removing the /
from app.foo
, and tried adding it to app.foo.view
too.
The edit state works in all instances. Changing the route for app.foo.view
to eg view
works too.
I am using svelte-state-renderer with embedded components, but I do no think this is the issue, because your demo implementation handles this scenario successfully (without push state routing). So I think the problem must be in ASR.
index.js
is more than 250 lines long.
I propose a goal of 150 lines.
Is there any way to reload the current route? I know I can just not use event.preventDefault() but that reloads the app as a whole.
It's not clear from the documentation which addState()
options are required.
As far as I know, these are required: name, template, activate and these are not: route, defaultChild, data, resolve, querystringParameters
This should be documented. (Or fixed if this is not the desired case.)
Should an error be thrown when attempting to add a state without all of the required parameters?
My app is using push state routing. In my resolve functions, I am doing some checks before returning a successful callback. For example, you visit book/50
, and I do a check to ensure that book 50 exists, the user has permission, etc. If there is a problem, I am doing a callback.redirect()
to an error page, and sending an error object in the parameters. However, the object doesn't make it intact to the error state's resolve function, as it gets turned into a parameter on the query line. Is there a way to pass the actual error object to the error state's resolve function?
Use https://github.com/michaelrhodes/iso-next-tick instead of process.nextTIck
Use https://www.npmjs.com/package/eventemitter3 instead of `events
There's no reason to make life bad for non-browserify-bundlers
Discovered via KayserCommentaryOrg/revelation-project#1
There needs to be some way to pass in a hash fragment so that you can link to specific parts of the page when you're using HTML5 pushState routing (sausage-router)
hmmm
Whenever a state is create
d, change
d (template reset), or destroy
ed, an event should be fired.
The original state and the domApi should be emitted.
The new events should be documented. We'll need a new documentation section it looks like - stateChangeStart
and stateChangeEnd
and stateChangeError
should be noted too.
If a parent state has a route with a non-querystring-parameter (e.g. /parent/:importantId
), there is no way for child states to indicate that they depend on that parameter. The querystringParameters
array is only used to check actual querystring parameters - there's no way for the child to indicate that it needs to reset when importantId
changes.
Is the following possible? And if not, how would I go about implementing this? I'm open to putting out a PR but am having trouble understanding the codebase.
addState({
// everything else
templates: { // normally just one template
default: componentFn,
nav: navComponentFn,
},
})
<uiView name="nav" />
<uiView />
npm run watch
http://localhost:8080/asr-rbtc/#/
which causes an stateChangeError, and the screen stays blank, and no activate function gets called. (There is not a route for /
.)It's hard to figure out w/o code examples, imo.
I put some test data in the resolve, and forgot to set it as an async function. When I try to load a route, I don't get any error message or anything. It just appears to get stuck.
resolve: () => {
const thing = {
test_data: true
}
return thing
}
I would have expected it to either work as-is, or to throw an error about a missing .then
method.
I'm trying to add a home '/' route to my app (using svelte-state-renderer). I've used the examples over on state-router-example as a base but when I change the route in login.js from 'login' to '/' or an empty string the page is blank on refresh.
Discovered by @Vehmloewff
If you have a parent state with a route parent
and a default child state that has an empty string as its route, makePath
will return a route /parent
but the router will only be listening for a route with a trailing slash /parent/
.
Should probably start with a unit test asserting that the output of both those functions match each other.
I'm just guessing, but the best fix might be to change page-path-builder
(used in makePath
only) to not add a trailing slash when there are empty chunks like that.
Or maybe the root issue is with the arguments being passed to makePath
I ran into a case where I wanted ui-router's inherit
option on a stateRouter.go
call.
The option inherit: true
should cause any properties on the current route to be carried over to whatever route you are generating a link to.
Unlike in ui-router, it should default to false.
Even more events that I need!
These should emit right after the activate function is called on a state, and right before the destroy event is fired.
Also I apparently forgot to document all the events with #54 so I should do that now.
Link to https://wzrd.in/standalone/abstract-state-router@latest for a browser-ready version.
The top part of the page is already pretty crowded, probably need to make a new download section somewhere (still at the top) that incorporates npm/browserify and browser instructions.
xtend is smaller and better, and overlaps with hash-brown-router.
Thanks to some help from another dev, browserstack tests report their results much more reliably now. I've updated package.json to use the better versions. a3a62f8
It looks like some tests aren't passing any more, most notably the webpack test that tries to read from disc. We should have some difference between node tests and browser tests so that that test doesn't get loaded.
I'm not sure why some of those other tests aren't passing (I saw one about console.error not being a function in Chrome, which it totally is). It would probably be easier to make sure everything passes with tape-run first.
Reported by stalkerg in chat.
Current thought on how to fix it: update page-path-builder
to take an encode
function as an option, and then add encode
as an initialization option for ASR as well
Right now evaluateCurrentRoute
only checks "is there any route" before sending you to a default state.
It would probably be more correct to check "is the route empty?" and if so, send you to that default state, and if not, emit a notFound
event or send you to a 404-not-found page.
Thoughts?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.