Skip to content

docs(docs-infra): Add query as an url query param to the api reference #57062

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

Closed
wants to merge 1 commit into from

Conversation

mvdluit
Copy link
Contributor

@mvdluit mvdluit commented Jul 20, 2024

add an url query param to to perform a search on api references directly via the url

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.dev application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Currently it's not possible to add a queryParam to https://angular.dev/api to link directly to a specific result set. This is possible on AIO.

Issue Number: N/A

What is the new behavior?

This brings the behavior inline with the old AIO API reference search. It's possible to directly link to a result set (e.g. https://angular.dev/api?query=inject). When searching via the input on the overview page, the search value will also be added to the queryParam.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

@pullapprove pullapprove bot requested a review from atscott July 20, 2024 19:24
@angular-robot angular-robot bot added area: docs Related to the documentation area: docs-infra Angular.dev application and infrastructure labels Jul 20, 2024
@ngbot ngbot bot added this to the Backlog milestone Jul 20, 2024
@mvdluit
Copy link
Contributor Author

mvdluit commented Jul 20, 2024

@JeanMeche As discussed on Discord. I did not yet add the functionality to also add the type queryParam when a type is selected. Please let me know if this is needed and I'd be happy to add it (it's basically a copy/paste of the effect).

@mvdluit mvdluit force-pushed the api-ref-query-param branch from f630316 to 8cc0992 Compare July 20, 2024 19:29
@mvdluit mvdluit force-pushed the api-ref-query-param branch 2 times, most recently from 422c380 to a47abd7 Compare July 21, 2024 00:34
@mvdluit mvdluit force-pushed the api-ref-query-param branch from a47abd7 to a01292b Compare July 21, 2024 00:56
Copy link

github-actions bot commented Jul 21, 2024

Deployed adev-preview for a36ffb925a4cefe8e98290c88cf0ec0e0ac6e596 to: https://ng-dev-previews-fw--pr-angular-angular-57062-adev-prev-l6eqpwhp.web.app

Note: As new commits are pushed to this pull request, this link is updated after the preview is rebuilt.

@mvdluit mvdluit force-pushed the api-ref-query-param branch from a01292b to 07b9e79 Compare July 21, 2024 02:24
@mvdluit
Copy link
Contributor Author

mvdluit commented Jul 21, 2024

@JeanMeche You mentioned the developer preview and experimental references yesterday. The current UI (input and toggle for isDeprecated) was created when the underlying data in manifest.json did not yet include properties for isDeveloperPreview and isExperimental.

While re-thinking the UI is a bit out of scope for this PR, I do wonder if we shouldn't already include a status queryParam (as a temporary step before it is eventually fully included in the UI) that will show these references. It could be useful to be able to directly link from https://angular.dev/reference/releases#developer-preview to a list with current references in developer preview. This status queryParam should initially only be active when used in a direct link scenario (e.g. http://angular.dev/api?status=isdeveloperpreview) to avoid hiding items when people start manually searching. So we would have to reset it when a change to query or type takes place. Related issue: #55336

Just thinking out loud here, curious how you feel about this.

Edit: I just had a look and it might be a bit more involved (existing interfaces, tests need to be updated) to get the status working properly, so probably better to make a seperate PR for it.

@mvdluit mvdluit marked this pull request as draft July 22, 2024 23:30
@mvdluit
Copy link
Contributor Author

mvdluit commented Jul 22, 2024

Changed the PR to draft as I want to extract the updateQueryParam method to a service, so it can be used in other places. (e.g.

this.router.navigate([], {
relativeTo: this.activatedRoute,
queryParams: {v: `${this.from.name}-${this.to.name}`, l: this.level},
queryParamsHandling: 'merge',
});
)

@atscott
Copy link
Contributor

atscott commented Jul 22, 2024

Changed the PR to draft as I want to extract the updateQueryParam method to a service, so it can be used in other places. (e.g.

Do that in another follow-up refactoring PR if this is approved. Adding more to your current PR will make it more difficult to review and be approved. Using the Location service to hide browser URL updates from the Router should be used sparingly, if ever. I'd not approve the current change without first convincing myself that it's the right thing to do.

@atscott
Copy link
Contributor

atscott commented Jul 22, 2024

Do you have examples of web pages with search that update the query as you're typing in the search input? I'm not convinced that this is a common or good user experience.

@mvdluit
Copy link
Contributor Author

mvdluit commented Jul 22, 2024

Do you have examples of web pages with search that update the query as you're typing in the search input? I'm not convinced that this is a common or good user experience.

It was the default behavior in the AIO API reference: https://v17.angular.io/api

@atscott
Copy link
Contributor

atscott commented Jul 22, 2024

It was the default behavior in the AIO API reference: https://v17.angular.io/api

Right, but that's not on its own a reason to do the same for the new docs site. Only if we decide it's a valuable feature that provides good UX.

What are the scenarios in which you would want to share a link to a filtered API page with the query as opposed to the API you were looking for?

@mvdluit
Copy link
Contributor Author

mvdluit commented Jul 23, 2024

It was the default behavior in the AIO API reference: https://v17.angular.io/api

Right, but that's not on its own a reason to do the same for the new docs site. Only if we decide it's a valuable feature that provides good UX.

Would it be better if the param was only updated once the user was done typing? I would have to convert the signal to an observable and add a debounce maybe?

My use case involves the Angular Community Discord bot. It allows to search API references but it has a limit on how many results it can display. So when there are more than 10 results I want to direct users to https://angular.dev/api?query=
api-command

@mvdluit
Copy link
Contributor Author

mvdluit commented Jul 23, 2024

@atscott This is actually not the first time this feature was discussed. You mentioned here that the url should be replaced: #52979 (comment) and in that PR there's no mention that this feature was not desirable (The actual feature was later removed from that PR due to issues getting it merged and is what lead me to create this PR)

@mvdluit mvdluit marked this pull request as ready for review July 23, 2024 00:42
@atscott
Copy link
Contributor

atscott commented Jul 23, 2024

@atscott This is actually not the first time this feature was discussed. You mentioned here that the url should be replaced: #52979 (comment) and in that PR there's no mention that this feature was not desirable (The actual feature was later removed from that PR due to issues getting it merged and is what lead me to create this PR)

Sure, but that doesn't at all mean I can't ask the question here.

@mvdluit mvdluit force-pushed the api-ref-query-param branch from 07b9e79 to a0e4077 Compare July 23, 2024 21:03
@mvdluit
Copy link
Contributor Author

mvdluit commented Jul 23, 2024

@atscott This is actually not the first time this feature was discussed. You mentioned here that the url should be replaced: #52979 (comment) and in that PR there's no mention that this feature was not desirable (The actual feature was later removed from that PR due to issues getting it merged and is what lead me to create this PR)

Sure, but that doesn't at all mean I can't ask the question here.

Didn't mean to imply that you couldn't/shouldn't ask. Just wanted to provide additional information.

@mvdluit mvdluit force-pushed the api-ref-query-param branch from a0e4077 to fe31e82 Compare July 23, 2024 23:50
@JeanMeche JeanMeche requested review from atscott and removed request for dylhunn, josephperrott, dgp1130 and twerske September 5, 2024 21:32
@JeanMeche JeanMeche added action: review The PR is still awaiting reviews from at least one requested reviewer and removed area: animations area: common Issues related to APIs in the @angular/common package area: router area: core Issues related to the framework runtime area: language-service Issues related to Angular's VS Code language service area: bazel Issues related to the published `@angular/bazel` build rules area: elements Issues related to Angular Elements area: upgrade Issues related to AngularJS → Angular upgrade APIs area: compiler Issues related to `ngc`, Angular's template compiler area: migrations Issues related to `ng update` migrations area: devtools area: docs Related to the documentation action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews labels Sep 5, 2024
@mvdluit
Copy link
Contributor Author

mvdluit commented Sep 5, 2024

Apologies for the mess with the rebase. I'm not sure what went wrong. Thank you @JeanMeche for helping out.

@@ -108,12 +116,23 @@ export class AppComponent implements OnInit {
private focusFirstHeadingOnRouteChange(): void {
this.router.events
.pipe(
filter((e): e is NavigationEnd => e instanceof NavigationEnd),
filter((e): e is RoutesRecognized => e instanceof RoutesRecognized),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't quite right. Guards and resolvers will delay the navigation and the focus will happen before the new route is rendered. On option might be a switchMap to a NavigationEnd after filtering on the condition that's in the subscription

@mvdluit mvdluit force-pushed the api-ref-query-param branch from e06a086 to a36ffb9 Compare September 5, 2024 23:06
@angular-robot angular-robot bot added the area: docs Related to the documentation label Sep 5, 2024
return this.router.events.pipe(
filter((e): e is NavigationEnd => e instanceof NavigationEnd),
// Skip first emission, cause on the initial load we would like to `Skip to main content` popup when it's focused
skip(1),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This skip(1) doesn't belong here actually. It should probably be changed to a skipUntil(router.events.filter(e => e instanceof NavigationEnd)) at the top of this pipe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm struggling to get it to work with skipUntil. Once I add it, the filter that checks same route navigation no longer works. Did I add it in the wrong place, or am I missing something else?

private focusFirstHeadingOnRouteChange(): void {
  this.router.events
    .pipe(
      filter((e): e is RoutesRecognized => e instanceof RoutesRecognized),
      filter((e) => {
        // do not set focus when only fragments or queryParams change
        const tree = createUrlTreeFromSnapshot(e.state.root, []);
        return this.router.isActive(tree, {
          paths: 'exact',
          matrixParams: 'exact',
          fragment: 'ignored',
          queryParams: 'ignored',
        });
      }),
      switchMap(() => {
        return this.router.events.pipe(
          skipUntil(
            this.router.events.pipe(
              filter((e): e is NavigationEnd => e instanceof NavigationEnd),
            ),
          ),
        );
      }),
    )
    .subscribe(() => {
      this.focusFirstHeading();
    });
  }

Also I saw 19a1296. I assume that is a temporary solution and this is still needed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did I add it in the wrong place

Yes, it needs to go at the very top, before RoutesRecognized,

I assume that is a temporary solution and this is still needed?

Yes, it's temporary

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies, i've been distracted with some other things. I've placed the skipUntil on top and it's working as expected now. Is there anything else that needs to be done to land this fix?

cc. @JeanMeche

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've placed the skipUntil on top and it's working as expected now. Is there anything else that needs to be done to land this fix?

Yes, the filter was changed to look for RoutesRecognized but needs to be reverted back to NavigationEnd.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or rather, what the comment in the review says: after filtering, it needs to wait for NavigationEnd still so switchMapping to NavigationEnd should work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I add a switchMap, this.focusFirstHeading(); is always called. If the filter returns false (same route navigation) it correctly ignores the switchMap, but there's still an emission that triggers the method call in the subscribe. This does not happen when I remove the switchMap and I'm not sure what I'm doing wrong.

this.router.events
  .pipe(
    skipUntil(
      this.router.events.pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd)),
    ),
    filter((e): e is RoutesRecognized => e instanceof RoutesRecognized),
    filter((e) => {
      // do not set focus when only fragments or queryParams change
      const tree = createUrlTreeFromSnapshot(e.state.root, []);
      return !this.router.isActive(tree, {
        paths: 'exact',
        matrixParams: 'exact',
        fragment: 'ignored',
        queryParams: 'ignored',
      });
    }),
    switchMap(() => {
      return this.router.events.pipe(
        filter((e): e is NavigationEnd => e instanceof NavigationEnd),
      );
    }),
  )
  .subscribe(() => {
    this.focusFirstHeading();
  });

As an alternative you mentioned that RoutesRecognized should be reverted back to NavigationEnd, but I was only able to get the filter to work correctly with the ActivatedRouteSnapshot available on RoutesRecognized.state.root. Is there another snapshot besides ActivatedRoute that I could use?

e.g. This will never call the this.focusFirstHeading() method, even when there is a route change:

this.router.events
  .pipe(
    skipUntil(
      this.router.events.pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd)),
    ),
    filter((e): e is NavigationEnd => e instanceof NavigationEnd),
    filter(() => {
      // do not set focus when only fragments or queryParams change
      const tree = createUrlTreeFromSnapshot(this.activatedRoute.snapshot, []);
      return !this.router.isActive(tree, {
        paths: 'exact',
        matrixParams: 'exact',
        fragment: 'ignored',
        queryParams: 'ignored',
      });
    }),
  )
  .subscribe(() => {
    this.focusFirstHeading();
  });

…arams changes

setting heading focus when query params change, causes the api overview input to lose focus on every character entered. while staying on the same route, re-setting focus does not make sense
@JeanMeche
Copy link
Member

This is already implemented.
https://angular.dev/api?query=test

@JeanMeche JeanMeche closed this May 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
action: review The PR is still awaiting reviews from at least one requested reviewer adev: preview area: docs Related to the documentation area: docs-infra Angular.dev application and infrastructure target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants