Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 06:47
    jasonleewilson starred angular/angular
  • 06:41
    petebacondarwin commented #33777
  • 06:18
    AndrewKushnir closed #33785
  • 06:18
    AndrewKushnir commented #33785
  • 06:07
    gcontini starred angular/angular
  • 05:53
    sincy123 commented #33785
  • 05:53
    sincy123 reopened #33785
  • 05:53
    sincy123 closed #33785
  • 05:53
    sincy123 opened #33785
  • 05:42
    googlebot labeled #33705
  • 05:42
    kara assigned #33705
  • 05:42
    kara labeled #33705
  • 05:35
    ngbot[bot] milestoned #33783
  • 05:35
    kara labeled #33783
  • 05:35
    kara commented #33514
  • 05:35
    AbhishekMurumkar starred angular/angular
  • 05:35
    kara closed #33779
  • 05:35

    kara on 9.0.x

    refactor(language-service): Col… (compare)

  • 05:34

    kara on master

    fix(ivy): ComponentFactory.crea… (compare)

  • 05:34
    kara closed #33487
Damien Retzinger
@damienwebdev
@Injectable({
  providedIn: 'root',
  useFactory: (document, window, handler: ErrorHandler) => new ShopScrollerService(
    document, 
    document.querySelector('.mat-sidenav-content'), 
    handler
  ),
  deps: [DOCUMENT, ErrorHandler]
})
export class ShopScrollerService implements ViewportScroller {

  private offset: () => [number, number] = () => [0, 0];

  constructor(private document: Document, private window: any, private errorHandler: ErrorHandler) {
    setTimeout(() => {
      this.window = document.querySelector('.mat-sidenav-content');
    }, 1000)
  }

  /**
   * Configures the top offset used when scrolling to an anchor.
   * @param offset A position in screen coordinates (a tuple with x and y values)
   * or a function that returns the top offset position.
   *
   */
  setOffset(offset: [number, number]|(() => [number, number])): void {
    if (Array.isArray(offset)) {
      this.offset = () => offset;
    } else {
      this.offset = offset;
    }
  }

  /**
   * Retrieves the current scroll position.
   * @returns The position in screen coordinates.
   */
  getScrollPosition(): [number, number] {
    if (this.supportScrollRestoration() && this.window instanceof Window) {
      return [this.window.scrollX, this.window.scrollY];
    } 
    else if(this.supportScrollRestoration() && this.window instanceof HTMLElement){
      return [this.window.scrollLeft, this.window.scrollTop]
    }
    else {
      return [0, 0];
    }
  }

  /**
   * Sets the scroll position.
   * @param position The new position in screen coordinates.
   */
  scrollToPosition(position: [number, number]): void {
    if (this.supportScrollRestoration()) {
      this.window.scrollTo(position[0], position[1]);
    }
  }

  /**
   * Scrolls to an anchor element.
   * @param anchor The ID of the anchor element.
   */
  scrollToAnchor(anchor: string): void {
    if (this.supportScrollRestoration()) {
      // Escape anything passed to `querySelector` as it can throw errors and stop the application
      // from working if invalid values are passed.
      if (this.window.CSS && this.window.CSS.escape) {
        anchor = this.window.CSS.escape(anchor);
      } else {
        anchor = anchor.replace(/(\"|\'\ |:|\.|\[|\]|,|=)/g, '\\$1');
      }
      try {
        const elSelectedById = this.document.querySelector(`#${anchor}`);
        if (elSelectedById) {
          this.scrollToElement(elSelectedById);
          return;
        }
        const elSelectedByName = this.document.querySelector(`[name='${anchor}']`);
        if (elSelectedByName) {
          this.scrollToElement(elSelectedByName);
          return;
        }
      } catch (e) {
        this.errorHandler.handleError(e);
      }
    }
  }

  /**
   * Disables automatic scroll restoration provided by the browser.
   */
  setHistoryScrollRestoration(scrollRestoration: 'auto'|'manual'): void {
    if (this.supportScrollRestoration()) {
      const history = this.window.history;
      if (history && history.scrollRestoration) {
        history.scrollRestoration = scrollRestoration;
      }
    }
  }

  private scrollToElement(el: any): void {
    const rect = el.getBoundingClientRect();
    const left = rect.left + this.window.pageXOffset;
    const top = rect.top + this.window.pageYOffset;
    const offset = this.offset();
    this.window.scrollTo(left - offset[0], top - offset[1]);
  }

  /**
   * We only support scroll restoration when we can get a hold of window.
   * This means that we do not support this behavior when running in a web worker.
   *
   * Lifting this restriction right now would require more changes in the dom adapter.
   * Since webworkers aren't widely used, we will lift it once RouterScroller is
   * battle-tested.
   */
  private supportScrollRestoration(): boolean {
    try {
      return !!this.window && !!this.window.scrollTo;
    } catch {
      return false;
    }
  }
}
So, obviously, this has problems. I'd need a better way to resolve the scrolling element in question.
But, this would provide a backwards-compatible solution which allows for more than just Window to be scrolled.
I'd need to add a token that could be resolved to the element in question (either Window or MyElement)
Segi
@SegiH
My app uses Angular Router. I've got a data service https://pastebin.com/Aifu8Ga3 and this is my app.module.ts: https://pastebin.com/LNmdCzTn I want to store allRoutes ,which is my router configuration, inside of the data service but I have an issue with importing it inside of app.module. Is there a way to import RouterModule.forRoot in the imports and access the route defined in the data service ?
Damien Retzinger
@damienwebdev
Then all you'd have to do is simply override the key:
providers: [
    { provide: ViewportScrollerRef, useExisting: MyScrollerRef}
  ]
I think that API is fairly clean, I'm just not 100% certain on how exactly to resolve the elementref in question. The setTimeout i laid out above is just a bad hack I threw together.
Because, if I'm not mistaken the router's scroll event triggers after ngAfterViewInit
Eric
@sliceofbytes
Ya other then the setTimeout it looks pretty nice, I'll have some more time to read it over later
@SegiH looks like just a static array, just import it
@damienwebdev I've actually ended up using ng-sidebar for a couple projects just cause of weirdness with the mat-sidebar
Segi
@SegiH
do you mean the allRoutes defined in the service ?
Eric
@sliceofbytes
@SegiH yes
Segi
@SegiH
i dont want to do that
I want that inside of the data service and I want to ideally remove that other defiition
what I'd like to do is have allRoutes be part of the data service
is that possible ?
Eric
@sliceofbytes
not sure why you would want to do that but sure
Segi
@SegiH
how
Eric
@sliceofbytes
just make it a property on dataService
Segi
@SegiH
how
if you put allRoutes in the data service in app.module when you import RouterModule.forRoot you cant access the routes
Eric
@sliceofbytes
@SegiH yes it's possible, you will just have to instantiate an instance of your DataService to access the data
Segi
@SegiH
I cant fingure out how to do that
Like I said doesn't seem like a good idea, but if you have to do it something like that
Segi
@SegiH
thats not what i am trying to do
I know how to make it work if you import the routes in app module using RouterModule.forRoot([
nm
I'll just leave the route object outside of the data service
Irv
@ilennert
Anyone with opinions on this? I'm using GraphQL to talk to the service API. My app also uses NGRX. My mutations all return an object that represents exactly what was added/created through the mutation. I have, at that point, been applying it to the state of the through the effect that started the whole thing off. Now I'm also starting to use the subscriptions, of which I have one for every mutation and it returns the same data
So on the client where the user entered the data I get duplicates in the state
I'm not sure if I should just ignore the return on the mutation and just update the state on the subscriptions or what...
Joe
@foxjazz
is there an example of how to list components horizontally (display : inline) doesn't seem to apply
DrewMoody
@DrewMoody
@foxjazz display: flex defaults to row.
elmarou
@elmarou
Hi everyone, haw can validate complex password using angular _
8
Brad
@bradtaniguchi
@elmarou What do you mean by "complex password" and validate? Like make sure the given password matches creteria (length, includes a none character, etc)
elmarou
@elmarou
@bradtaniguchi how can i verify whether the password contains uppercase lowercase number and a character
Brad
@bradtaniguchi
@elmarou I suggest either using the built-in Pattern validator, or build your own custom validator
Just a friendly reminder, be sure to validate the password on the back-end like any validation, client validation is more for user experience than actual security
Brendan Ingham
@brendan.ingham_gitlab

How can i animate a transition between the same component ( via a router )

the way i have my route set is that we just re-use the same component, and get different data using a route resolver. this is used for a category page, with an unlimited number of sub categories (e.g cat one has 2 subcats, one of the subcats has more ... etc)

the standard page transitions aren't working, because the component isn't being recreated, and a new one is not being created.
Brad
@bradtaniguchi
One ghetto approach is to change the router so it re-creates the component anyways
Brendan Ingham
@brendan.ingham_gitlab
What do you mean, change the router?
I've had enough trouble with aux routes I don't wanna make it cry(or myself) further
Brad
@bradtaniguchi
No, I believe there is a setting on the router to re-render a component if routed to the same route
Brendan Ingham
@brendan.ingham_gitlab
Ohh, yeah I'll do that
Brad
@bradtaniguchi
by default it doesn't (for performance) but if you wanted it to re-render anyways (like for animations, clearing state, etc) you can change that behavior