Open NullVoxPopuli opened 3 years ago
How would this play together with location type hash
? I guess it could be only supported for history
location?
I like this proposal!
Perhaps because I've proposed something similar earlier: 😄
What if the Ember Router introduced a new type of "sub-leaf" (could be called e.g. variation), that could be encoded as
my/path#variation-{name}
(for example)?With routable variations we could, for example, show modals (i.e. routable modals) or toggle tabs on a page. Such route variations would share the modal hook (that hook wouldn't re-run when switching between variations) and the variation state would be accessible from templates and controllers (if Ember decides to keep them around).
Link to my similar idea: https://github.com/emberjs/rfcs/issues/662
We should think about what other use-cases there are. For example encoding open modals, scroll position, etc. As mentioned in my quoted issue above, there is some precedent in CSS :target
, in using this for more than just scroll position.
@jelhan For location type hash we could split the hash on some character, e.g. /index.html#/my/route~hashId
or some of the other valid chars as separators.
Made a thing: https://github.com/CrowdStrike/ember-url-hash-polyfill
location type hash
would not / can't be supported, afaik
I think a first iteration on that feature should add support for URL fragments in general. This would enable different use cases. Scrolling to an anchor after transition would be one of them. Persisting state, which should not be sent to the server in the URL, would be another.
To support URLs fragments, I think the following changes are needed:
RouterService.transitionTo()
and RouterService.replaceWith()
methods accept a hash
as part of the existing options object. I think the following rules should apply:
hash
is present, the URL fragment of the target URL should be set to the provided value.hash
is not present and
transitionTo
or replaceWith
is invoked with route and/or models arguments, an existing URL fragment is removed.transitionTo
or replaceWith
is invoked with options has only, an existing URL fragment stays as it.RouterService.urlFor()
accepts a hash
as part of existing options object. If present it is added as URL fragment to the generated URL.RouterService.currentURL
returns the current URL including the URL fragment. (I think this already works.)<LinkTo>
accept a @hash
argument.
href
attribute is,
@hash
argument if set,@hash
argument is not set and either @route
, @model
and/or @models
argument is set,@route
, nor @model
nor @models
arguments are set.@hash
argument is treated the same as for RouterService.transitionTo()
and RouterService.replaceWith()
on the transition triggered on click.Open questions:
hash
property be added to RouteInfo
? The URL fragment is not associated with any specific route. But it would be helpful to have access to it in Transition.to
and Transition.from
. I guess it's the same question as if url
property should be added to RouteInfo
or not.hash
option to Route.transitionTo()
, Route.replaceWith()
, Controller.transitionToRoute()
and Controller.replaceRoute()
even though they are deprecated? What to do with Replace.intermediateTransitionTo()
, which is not (yet) deprecated?hash
? Or should we limit support to transition type history
at least for the first iteration?Sounds good! I think we should swap @hash
for @anchor
tho, per the nomenclature here: https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_URL
This also avoids the naming overload we'd have with the (hash)
helper
Sounds good! I think we should swap
@hash
for@anchor
tho, per the nomenclature here: https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_URLThis also avoids the naming overload we'd have with the
(hash)
helper
Naming is very difficult here in my opinion. I used hash
to follow the naming of URL
interface. But it doesn't seem to be a clear case:
fragment
, while the attribute representing it in the Interfaces for URL manipulation is named hash.HTMLAnchorElement
interface, which represents a <a>
tag. But I didn't found it referencing a specific part of the URL.I fully agree that it is confusing if {{hash}}
helper would be used together with a @hash
argument:
<LinkTo @query={{hash sortBy="title"}} @hash="person-13">
It doesn't get easier as existing argument for setting query parameters does not follow naming in URL
interface and relevant specification. It is named @query
for <LinkTo>
and queryParams
for the options object accepted by RouterService.transitionTo()
etc. This is inline with RFC 3986, which reference them as query. But on URL
interface has search
and searchParams
properties. URL standard maintained by WHATWG uses both terms (again): query for the URI component and search as attribute name on the interface for URL manipulation.
I would tend to follow the URL
interface so that it maps well to native JavaScript API. But that is already not true for existing query
and queryParams
. :sob:
I used hash to follow the naming of URL interface.
oh no. even the URL docs are contradictory! 🙃
yeah, following URL interface is probs best
@jelhan For location type hash we could split the hash on some character, e.g.
/index.html#/my/route~hashId
or some of the other valid chars as separators.
There doesn't seem to be any character, which is allowed in a fragment but is not allowed in a path or query component of a URI. :cry:
Accordingly to RFC 3986: Uniform Resource Identifier (URI): Generic Syntax a fragment may contain the following characters:
fragment = *( pchar / "/" / "?" )
That's exactly the same as for query component of an URI:
query = *( pchar / "/" / "?" )
And a subset of which is allowed in path component of an URI:
path = path-abempty ; begins with "/" or is empty
/ path-absolute ; begins with "/" but not "//"
/ path-noscheme ; begins with a non-colon segment
/ path-rootless ; begins with a segment
/ path-empty ; zero characters
path-abempty = *( "/" segment )
path-absolute = "/" [ segment-nz *( "/" segment ) ]
path-noscheme = segment-nz-nc *( "/" segment )
path-rootless = segment-nz *( "/" segment )
path-empty = 0<pchar>
segment = *pchar
segment-nz = 1*pchar
segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
; non-zero-length segment without any colon ":"
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
I think it would be fine to split on an uncommon character, such as ~
. I know there is a theoretical collision risk, but maybe we could just raise an exception instead of setting a hash where it would collide. Also, could make the separator character configurable (with a default), so anyone who happens to use ~
(or whatever we go for; $
and *
could also work) could swap it out.
This would be a great feature. Is there an actual path to RFC here?
potentially. :thinking: the least hacky thing we'd need for this is to have some for he framework to let us know that rendering after a transition has "settled" (even keeping in mind that pages could spin up intervals and all that, which keep us from normal settled state)
The re-working of the routing layer may be a prereq for this tho, as the existing routing layer is opt-in to everything, which is kind of annoying to work with (QPs, no hashes at all, etc). We'd have to add in hash support to RouteInfo, etc, where keeping that information should just be default.
I wonder if the new Polaris router ideas would resolve this.
I saw this comment in another thread:
I got feedback from a framework team member early this year that it is unlikely to land any RFC changing existing routing behavior currently. It sounded as framework team wants to have a clear vision for a Polaris router before touching existing stuff. Mainly to avoid unnecessary churn. I paused all activities on this topic due to that feedback.
— Jelhan (https://github.com/emberjs/rfcs/issues/787#issuecomment-1195685756)
@sandstrom I was just on a core team meeting where the router stuff was being discussed. We want to be clear that active progress is being made here and very soon we should have some more public information and be able to help rope the community in a bit more!
@wagenet did things ever get to a place where you could share more publicly?
if supported, maybe hash / anchor / id navigation would look like this in user-land:
(and then letting the actual router (router_js) handle
#
navigations. atm, the navigation look like:It just drops the hash