angular - কৌণিক 2 রুট পরিবর্তনতে শীর্ষে স্ক্রোল করুন



typescript angular2-routing (14)

আইফোন / আইওএস সাফারির জন্য আপনি একটি সেটটাইমআউট দিয়ে মোড়ানো করতে পারেন

 import { Component, OnInit } from '@angular/core';
    import { Router, NavigationEnd } from '@angular/router';

    @Component({
        selector: 'my-app',
        template: '<ng-content></ng-content>',
    })
    export class MyAppComponent implements OnInit {
        constructor(private router: Router) { }

        ngOnInit() {
            this.router.events.subscribe((evt) => {
                if (!(evt instanceof NavigationEnd)) {
                    return;
                }
                window.scrollTo(0, 0)
            });
        }
    }

আমার কৌনিক 2 অ্যাপে যখন আমি কোনও পৃষ্ঠা নীচে স্ক্রোল করি এবং পৃষ্ঠার নীচে লিঙ্কটি ক্লিক করি তখন এটি রুট পরিবর্তন করে এবং আমাকে পরবর্তী পৃষ্ঠায় নিয়ে যায় তবে এটি পৃষ্ঠার শীর্ষে স্ক্রোল করে না। ফলস্বরূপ, যদি প্রথম পৃষ্ঠাটি দীর্ঘ হয় এবং ২ য় পৃষ্ঠায় কয়েকটি বিষয়বস্তু থাকে তবে এটি এমন একটি ধারণা দেয় যে ২ য় পৃষ্ঠায় বিষয়বস্তুর অভাব রয়েছে। যেহেতু বিষয়বস্তুগুলি কেবলমাত্র পৃষ্ঠার শীর্ষে স্ক্রোল করা থাকলে তা দৃশ্যমান।

আমি উপাদানটির এনজিআইনেটে পৃষ্ঠার শীর্ষে উইন্ডোটি স্ক্রোল করতে পারি তবে, এর চেয়ে আরও ভাল কোনও সমাধান আছে যা আমার অ্যাপ্লিকেশনটিতে সমস্ত রুট স্বয়ংক্রিয়ভাবে পরিচালনা করতে পারে?


Answer #1

আপনার যদি কেবল শীর্ষে পৃষ্ঠায় স্ক্রোলের প্রয়োজন হয় তবে আপনি এটি করতে পারেন (সেরা সমাধান নয়, তবে দ্রুত)

imports: [
  RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled'
  }),
  ...
]

Answer #2

আপনি আপনার উপাদানগুলিতে AfterViewInit লাইফসাইকেল হুক যুক্ত করতে পারেন।

ngAfterViewInit() {
   window.scrollTo(0, 0);
}

Answer #3

আপনি আপনার মূল উপাদানটিতে একটি রুট পরিবর্তন শ্রোতার নিবন্ধন করতে পারেন এবং রুট পরিবর্তনের শীর্ষে স্ক্রোল করতে পারেন।

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {
    constructor(private router: Router) { }

    ngOnInit() {
        this.router.events.subscribe((evt) => {
            if (!(evt instanceof NavigationEnd)) {
                return;
            }
            window.scrollTo(0, 0)
        });
    }
}

Answer #4

এই কোডের পিছনে মূল ধারণাটি হ'ল সমস্ত পরিদর্শন করা url বরাবর একটি অ্যারেতে সম্পর্কিত স্ক্রোলওয়াই ডেটা সহ। প্রতিবার কোনও ব্যবহারকারী কোনও পৃষ্ঠা (নেভিগেশনস্টার্ট) ত্যাগ করলে এই অ্যারেটি আপডেট হয়। যখনই কোনও ব্যবহারকারী কোনও নতুন পৃষ্ঠাতে প্রবেশ করতে পারে (নেভিগেশনএন্ড), আমরা ওয়াই অবস্থানটি পুনরুদ্ধার করার সিদ্ধান্ত নিয়েছি বা আমরা কীভাবে এই পৃষ্ঠায় পাব তার উপর নির্ভর করে না। যদি কোনও পৃষ্ঠায় একটি রেফারেন্স ব্যবহার করা হয় তবে আমরা 0 এ স্ক্রোল করি browser আমার ইংরেজীর জন্য দুঃখিত :)

this.router.events.subscribe((evt) => {
   if (evt instanceof NavigationEnd) {
      document.body.scrollTop = 0;
   }
});

Answer #5

এই দ্রষ্টব্যটি @ ফার্নান্দোএচেভারিয়ার এবং @ গিলহেরেমিরিলেসের সমাধানের উপর ভিত্তি করে তৈরি করা হয়েছে তবে এটি আরও সংক্ষিপ্ত এবং অ্যাঙ্গুলার রাউটার সরবরাহকারী পপস্টেট প্রক্রিয়াগুলির সাথে কাজ করে। এটি একাধিক পরপর নেভিগেশনের স্ক্রোল স্তর সংরক্ষণ এবং পুনরুদ্ধার করার অনুমতি দেয়।

আমরা প্রতিটি নেভিগেশন রাষ্ট্রের জন্য একটি মানচিত্রের scrollLevels স্ক্রোল অবস্থানগুলি সঞ্চয় scrollLevels । একবার যখন কোনও পপস্টেট ইভেন্ট হয়, তখন যে রাষ্ট্রটি পুনরুদ্ধার করতে চলেছে তার আইডি কৌণিক রাউটার দ্বারা সরবরাহ করা হয়: event.restoredState.navigationId । এটি তখন scrollLevels থেকে সেই রাজ্যের শেষ স্ক্রোল স্তরটি পেতে ব্যবহার করা হয়।

যদি এই রুটের জন্য কোনও সঞ্চিত স্ক্রোল স্তর না থাকে তবে এটি আপনার প্রত্যাশা অনুযায়ী শীর্ষে স্ক্রোল করবে।

import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart, NavigationEnd } from '@angular/router';

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class AppComponent implements OnInit {

  constructor(private router: Router) { }

  ngOnInit() {
    const scrollLevels: { [navigationId: number]: number } = {};
    let lastId = 0;
    let restoredId: number;

    this.router.events.subscribe((event: Event) => {

      if (event instanceof NavigationStart) {
        scrollLevels[lastId] = window.scrollY;
        lastId = event.id;
        restoredId = event.restoredState ? event.restoredState.navigationId : undefined;
      }

      if (event instanceof NavigationEnd) {
        if (restoredId) {
          // Optional: Wrap a timeout around the next line to wait for
          // the component to finish loading
          window.scrollTo(0, scrollLevels[restoredId] || 0);
        } else {
          window.scrollTo(0, 0);
        }
      }

    });
  }

}

Answer #6

এটি হ্যাশ নেভিগেশন সহ সমস্ত নেভিগেশন পরিবর্তনের জন্য আমার পক্ষে সবচেয়ে ভাল কাজ করেছে

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Location, PopStateEvent } from '@angular/common';
import { Router, Route, RouterLink, NavigationStart, NavigationEnd, 
    RouterEvent } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';

@Component({
  selector: 'my-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {

  private _subscription: Subscription;
  private _scrollHistory: { url: string, y: number }[] = [];
  private _useHistory = false;

  constructor(
    private _router: Router,
    private _location: Location) {
  }

  public ngOnInit() {

    this._subscription = this._router.events.subscribe((event: any) => 
    {
      if (event instanceof NavigationStart) {
        const currentUrl = (this._location.path() !== '') 
           this._location.path() : '/';
        const item = this._scrollHistory.find(x => x.url === currentUrl);
        if (item) {
          item.y = window.scrollY;
        } else {
          this._scrollHistory.push({ url: currentUrl, y: window.scrollY });
        }
        return;
      }
      if (event instanceof NavigationEnd) {
        if (this._useHistory) {
          this._useHistory = false;
          window.scrollTo(0, this._scrollHistory.find(x => x.url === 
          event.url).y);
        } else {
          window.scrollTo(0, 0);
        }
      }
    });

    this._subscription.add(this._location.subscribe((event: PopStateEvent) 
      => { this._useHistory = true;
    }));
  }

  public ngOnDestroy(): void {
    this._subscription.unsubscribe();
  }
}

Answer #7

কৌণিক extraOptions থেকে আপনি এখন ঝামেলা এড়াতে পারবেন এবং extraOptions আপনার RouterModule.forRoot() দ্বিতীয় প্যারামিটার হিসাবে পাস করতে পারবেন এবং scrollPositionRestoration: enabled করতে পারবেন scrollPositionRestoration: enabled যখনই রুট পরিবর্তন হবে তখন scrollPositionRestoration: enabled শীর্ষে স্ক্রোল করতে বলতে scrollPositionRestoration: enabled

ডিফল্টরূপে আপনি এটি app-routing.module.ts :

const routes: Routes = [
  {
    path: '...'
    component: ...
  },
  ...
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollPositionRestoration: 'enabled', // Add options right here
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

কৌণিক অফিসিয়াল ডক্স


Answer #8

কৌণিক ইদানীং একটি নতুন বৈশিষ্ট্য প্রবর্তন করেছে, কৌণিক রাউটিং মডিউলটির নীচের মত পরিবর্তন করা হয়েছে

 public routerActivate(event,outlet){
    outlet.scrollTop = 0;
 }`

Answer #9

ক্লিক অ্যাকশন দিয়ে কেবল এটি সহজ করুন

আপনার মূল উপাদানটিতে এইচটিএমএল রেফারেন্স করুন # স্ক্রোলকন্টেইনার

<div class="main-container" #scrollContainer>
    <router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
</div>

প্রধান উপাদান .ts

onActivate(e, scrollContainer) {
    scrollContainer.scrollTop = 0;
}

Answer #10

পছন্দ করুন তবে এই কোডটি হ্যাশ রাউটার বা অলস রাউটারে কাজ করে না। কারণ তারা অবস্থান পরিবর্তনগুলি ট্রিগার করে না। এটি চেষ্টা করতে পারেন:

import {Directive, HostListener} from '@angular/core';

@Directive({
    selector: '[linkToTop]'
})
export class LinkToTopDirective {

    @HostListener('click')
    onClick(): void {
        window.scrollTo(0, 0);
    }
}


Answer #11

সেরা উত্তরটি কৌণিক গিটহাব আলোচনায় থাকে ( রুট পরিবর্তন করা নতুন পৃষ্ঠায় শীর্ষে যায় না )।

সম্ভবত আপনি কেবল রুট রাউটার পরিবর্তনে শীর্ষে যেতে চান (বাচ্চাদের মধ্যে নয়, কারণ আপনি কোনও ট্যাবসেটে অলস লোড দিয়ে রুটগুলি লোড করতে পারেন)

app.component.html

<router-outlet (deactivate)="onDeactivate()"></router-outlet>

app.component.ts

onDeactivate() {
  document.body.scrollTop = 0;
  // Alternatively, you can scroll to top by using this other call:
  // window.scrollTo(0, 0)
}

JoniJnm সম্পূর্ণ ক্রেডিট ( মূল পোস্ট )


Answer #12

Router নিজেই ব্যবহার করা এমন সমস্যাগুলির কারণ হবে যা আপনি ব্রাউজারের ধারাবাহিক অভিজ্ঞতা বজায় রাখতে সম্পূর্ণরূপে কাটিয়ে উঠতে পারবেন না। আমার মতে সর্বোত্তম পদ্ধতিটি হ'ল কেবল একটি কাস্টম directive ব্যবহার করা এবং এটি ক্লিক করে স্ক্রোলটি পুনরায় সেট করা দিন। এই সম্পর্কে ভাল কথাটি হ'ল আপনি যদি ক্লিক করেছেন সেই একই url তবে পৃষ্ঠাটি শীর্ষেও ফিরে যাবে। এটি সাধারণ ওয়েবসাইটগুলির সাথে সামঞ্জস্যপূর্ণ। প্রাথমিক directive এরকম কিছু দেখতে পারে:

<a routerLink="/" linkToTop></a>

নিম্নলিখিত ব্যবহারের সাথে:

@Directive({
  selector: '[linkToTop]'
})
export class LinkToTopDirective implements OnInit, OnDestroy {

  @Input()
  set linkToTop(active: string | boolean) {
    this.active = typeof active === 'string' ? active.length === 0 : active;
  }

  private active: boolean = true;

  private onClick: EventListener = (event: MouseEvent) => {
    if (this.active) {
      window.scrollTo(0, 0);
    }
  };

  constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
              private readonly elementRef: ElementRef,
              private readonly ngZone: NgZone
  ) {}

  ngOnDestroy(): void {
    if (isPlatformBrowser(this.platformId)) {
      this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
    }
  }

  ngOnInit(): void {
    if (isPlatformBrowser(this.platformId)) {
      this.ngZone.runOutsideAngular(() => 
        this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
      );
    }
  }
}

এটি বেশিরভাগ ব্যবহারের ক্ষেত্রে যথেষ্ট হবে তবে আমি কয়েকটি বিষয় কল্পনা করতে পারি যা এ থেকে উদ্ভূত হতে পারে:

  • window ব্যবহারের কারণে universal উপর কাজ করে না
  • পরিবর্তন সনাক্তকরণের উপর ছোট গতির প্রভাব, কারণ এটি প্রতিটি ক্লিকের মাধ্যমে ট্রিগার হয়
  • এই নির্দেশকে অক্ষম করার কোনও উপায় নেই

আসলে এই বিষয়গুলি পরাস্ত করা বেশ সহজ:

<a routerLink="/" linkToTop></a> <!-- always active -->
<a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->

এটি সক্রিয় / নিষ্ক্রিয় করার সুবিধার্থে মৌলিক ক্ষেত্রে একই ব্যবহার সহ বেশিরভাগ ব্যবহারের ক্ষেত্রে বিবেচনা করে:

@Directive({
    selector: '[linkToTop]'
})
export class LinkToTopDirective {

    @Input()
    set linkToTop(active: string|boolean) {
        this.active = typeof active === 'string' ? active.length === 0 : active;
    }

    private active: boolean = true;

    @HostListener('click.pnb')
    onClick(): void {
      if (this.active) {
        window.scrollTo(0, 0);
      }        
    }
}

বিজ্ঞাপন, আপনি বিজ্ঞাপন হতে চান না পড়ুন

ব্রাউজারটি passive ইভেন্টগুলিকে সমর্থন করে কি না তা পরীক্ষা করার জন্য আরেকটি উন্নতি করা যেতে পারে। এটি কোডটিকে আরও কিছুটা জটিল করে তুলবে এবং আপনি যদি নিজের কাস্টম দিকনির্দেশনা / টেম্পলেটগুলিতে এই সমস্ত প্রয়োগ করতে চান তবে কিছুটা অস্পষ্ট is এই কারণেই আমি একটি ছোট library লিখেছিলাম যা আপনি এই সমস্যাগুলি সমাধান করতে ব্যবহার করতে পারেন। উপরের মতো একই কার্যকারিতা এবং যুক্ত passive ইভেন্টের সাথে, আপনি যদি ng-event-options লাইব্রেরি ব্যবহার করেন তবে আপনি আপনার নির্দেশকে এটিতে পরিবর্তন করতে পারেন। যুক্তিটি click.pnb ভিতরে click.pnb শ্রোতা:

constructor(private route: ActivatedRoute) {}

ngOnInit() {
  this._sub = this.route.fragment.subscribe((hash: string) => {
    if (hash) {
      const cmp = document.getElementById(hash);
      if (cmp) {
        cmp.scrollIntoView();
      }
    } else {
      window.scrollTo(0, 0);
    }
  });
}

Answer #13

window.scrollTo() আমার জন্য কৌনিক 5 তে কাজ করে না, তাই আমি document.body.scrollTop শীর্ষে ব্যবহার করেছি,

 this.router.events.subscribe((evt) => { if (evt instanceof NavigationEnd) { document.body.scrollTop = 0; } }); 




angular2-directives