पेज एंकर के लिए हैशटैग के साथ Angular2 रूटिंग


120

मैं अपने Angular2 पेज पर कुछ लिंक जोड़ना चाहता हूं, जब क्लिक करें, तो उस पृष्ठ के भीतर विशिष्ट पदों पर पहुंच जाएंगे , जैसे सामान्य हैशटैग। तो लिंक कुछ इस तरह होगा

/users/123#userInfo
/users/123#userPhoto
/users/123#userLikes

आदि।

मुझे नहीं लगता कि मुझे HashLocationStrategy की जरूरत है, क्योंकि मैं सामान्य Angular2 तरीके से ठीक हूं, लेकिन अगर मैं सीधे जोड़ दूं, तो लिंक वास्तव में रूट पर कूद जाएगा, न कि उसी पेज पर। किसी भी दिशा की सराहना की जाती है, धन्यवाद।

जवाबों:


130

अपडेट करें

यह अब समर्थित है

<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});

स्क्रॉल करने के लिए अपने घटक में नीचे कोड जोड़ें

  import {ActivatedRoute} from '@angular/router'; // <-- do not forget to import

  private fragment: string;

  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
  }

  ngAfterViewInit(): void {
    try {
      document.querySelector('#' + this.fragment).scrollIntoView();
    } catch (e) { }
  }

मूल

यह एक ज्ञात समस्या है और इसे https://github.com/angular/angular/issues/6595 पर ट्रैक किया गया है


1
@invot एक स्ट्रिंग के साथ एक चर (उदाहरण के 123लिए सवाल में क्या है) यह मानते हुए कि मार्ग पथ एक पैरामीटर की अपेक्षा करता है जैसे{ path: 'users/:id', ....}
गुंटर ज़ोचबॉयर

2
यदि आप एंकर को स्क्रॉल करना चाहते हैं तो इस पोस्ट को देखें: github.com/angular/angular/issues/6595
Pere Pages

12
नोट: यह अभी भी स्क्रॉल नहीं करता है
Martin Coll

2
हाँ, यह सेटटाइमआउट के साथ काम करता है, अगर मुझे बेहतर समाधान मिला तो मैं आपको बता दूंगा
अमृत ​​इब्राहिम

1
नंबर-जैसे आईडी, मन, 01या जो 100सीएसएस चयनकर्ता मान्य नहीं हैं , को स्क्रॉल करने के लिए संघर्ष करने वालों के लिए । आप इसे वैध चयनकर्ता बनाने के लिए एक पत्र या कुछ जोड़ना चाह सकते हैं। तो आप अभी भी 01एक टुकड़ा के रूप में पारित करेंगे, लेकिन idकुछ d01इस तरह की आवश्यकता होगी और इस तरह document.querySelector('#d'+id)मैच होगा।
पॉप

52

हालांकि गुंटर का जवाब सही है, यह लंगर टैग भाग के लिए "कूद" को कवर नहीं करता है

इसलिए, इसके अतिरिक्त:

<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});

... घटक (माता-पिता) में जहां आपको "कूद" व्यवहार की आवश्यकता होती है, जोड़ें:

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

class MyAppComponent {
  constructor(router: Router) {

    router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        const tree = router.parseUrl(router.url);
        if (tree.fragment) {
          const element = document.querySelector("#" + tree.fragment);
          if (element) { element.scrollIntoView(true); }
        }
      }
    });

  }
}

कृपया ध्यान दें कि यह एक वर्कअराउंड है ! भविष्य के अपडेट के लिए इस github मुद्दे का पालन करें । समाधान प्रदान करने के लिए विक्टर सैक्विन को श्रेय !


नमस्ते, मैं एक FAQ पृष्ठ बना रहा हूँ जहाँ आप पृष्ठ के शीर्ष पर एक सूची में परिभाषित प्रश्न पर क्लिक करके उत्तर पर जा सकते हैं। तो उपयोगकर्ता पहले से ही वर्तमान पृष्ठ पर है जब वह लंगर में कूदता है। अगर मैं राउटरलिंक की विशेषता को काम करना चाहता हूं तो मुझे "['../faq']"मूल्य के रूप में देना होगा वरना यह / faq / faq / # एंकर, / faq / # एंकर के कूदने की कोशिश करेगा। क्या यह करने का सही तरीका है या राउटरलिंक में वर्तमान पृष्ठ को संदर्भित करने का एक और अधिक सुरुचिपूर्ण तरीका है? इसके अलावा, document.querySelector("#" + tree.fragment);मुझे एक वैध चयनकर्ता त्रुटि नहीं देता है। क्या आपको यकीन है कि यह सही है? धन्यवाद
मौरिस

2
जब आप फिर से उसी लिंक पर क्लिक करते हैं तो यह काम नहीं करता है। क्या किसी ने यह काम किया अगर उपयोगकर्ता उसी एंकर लिंक पर क्लिक करें <a [routerLink]="['/faq']" fragment="section6">?
14

@JuniorM क्या आपने कभी इसका पता लगाया? मैं एक ही मुद्दे में चल रहा हूँ।
मफिन मैन

@Muffin, कुछ इस तरह से एक कोशिश है github.com/juniormayhe/Mailing/blob/master/Mailing.SPA/src/app/...
जूनियर Mayhé

1
इसके लिए अधिक एक्सपोजर की जरूरत है। यह एक बेहतर जवाब है IMO। ज्यादातर लोग सेक्शन में कूदना चाहेंगे।
आईमित्रविस्वाव

44

थोड़ा देर से जवाब देने के लिए क्षमा करें; एंगुलर रूटिंग डॉक्यूमेंटेशन में एक पूर्व-परिभाषित फंक्शन है, जो हमें हैशटैग के साथ पेज एंकर यानी लंगर डालने में मदद करता है।

चरण -1: - पहले App.module.ts फ़ाइल में RouterModule आयात करें : -

imports:[ 
    BrowserModule, 
    FormsModule,
    RouterModule.forRoot(routes,{
      anchorScrolling: 'enabled'
    })
  ],

चरण -2: - एचटीएमएल पेज पर जाएं, नेविगेशन बनाएं और संबंधित महत्वपूर्ण आईडी [राउटरलिंक] और संबंधित डिव आईडी के मिलान के लिए टुकड़ा जोड़ें : -

<ul>
    <li> <a [routerLink] = "['/']"  fragment="home"> Home </a></li>
    <li> <a [routerLink] = "['/']"  fragment="about"> About Us </a></li>
  <li> <a [routerLink] = "['/']"  fragment="contact"> Contact Us </a></li>
</ul>

चरण -3: - मेल द्वारा एक वर्ग / div बनाएं आईडी नाम के साथ टुकड़ा : -

<section id="home" class="home-section">
      <h2>  HOME SECTION </h2>
</section>

<section id="about" class="about-section">
        <h2>  ABOUT US SECTION </h2>
</section>

<section id="contact" class="contact-section">
        <h2>  CONTACT US SECTION </h2>
</section>

आपके संदर्भ के लिए, मैंने एक छोटा डेमो बनाकर नीचे दिए गए उदाहरण को जोड़ा है जो आपकी समस्या को हल करने में मदद करता है।

डेमो: https://rout-hashtag-page-anchors.stackblitz.io/


इसके लिए बहुत - बहुत धन्यवाद। साफ, संक्षिप्त और यह काम करता है!
बेलमिरिस

2
हाँ, धन्यवाद, कोणीय 7 के साथ पृष्ठ लोड पर ऑटो स्क्रॉल के लिए, बस जोड़ने के लिए scrollPositionRestoration: 'enabled',anchorScrolling विकल्प के अंतर्गत :)
Mickaël

यह मेरे url के अंत में हैश को ठीक से जोड़ देता है, लेकिन यह उसी नाम के साथ div को एंकर नहीं करता है। मुझे यकीन नहीं है कि मैं क्या याद कर रहा हूँ। मैंने ऊपर के तीन चरणों का पालन किया।
ओकलैंड्रिची

@oaklandrichie: क्या आप यहां jsfiddle / stackblitz कोड साझा कर सकते हैं। मैं आपकी मदद कर सकता हूं
नाहिद शरीफ

यह उत्तर निश्चित रूप से स्वीकार किया जाना चाहिए, आकर्षण की तरह काम करता है!
कोपपनी चुंबन

25

थोड़ा देर से लेकिन यहाँ एक जवाब मुझे मिला है जो काम करता है:

<a [routerLink]="['/path']" fragment="test" (click)="onAnchorClick()">Anchor</a>

और घटक में:

constructor( private route: ActivatedRoute, private router: Router ) {}

  onAnchorClick ( ) {
    this.route.fragment.subscribe ( f => {
      const element = document.querySelector ( "#" + f )
      if ( element ) element.scrollIntoView ( element )
    });
  }

यदि आप पहले से ही एक लंगर के साथ एक पृष्ठ पर उतरते हैं, तो उपरोक्त स्वचालित रूप से दृश्य पर स्क्रॉल नहीं करता है, इसलिए मैंने ऊपर दिए गए समाधान का उपयोग अपने ngInit में किया ताकि यह उसी के साथ काम कर सके:

ngOnInit() {
    this.router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        const tree = this.router.parseUrl(this.router.url);
        if (tree.fragment) {
          const element = document.querySelector("#" + tree.fragment);
          if (element) { element.scrollIntoView(element); }
        }
      }
    });
  }

अपने कंपोनेंट की शुरुआत में राउटर, एक्टिनेटेडरूट और नेवीगेशन को इंपोर्ट करना सुनिश्चित करें और यह सब जाने के लिए अच्छा होना चाहिए।

स्रोत


4
मेरे लिये कार्य करता है! यदि आप उसी पृष्ठ के भीतर नेविगेट करना चाहते हैं जिस पर आप पहले से ही हैं, तो [राऊटरलिंक] = "['' 'का उपयोग करें"
Raoul

1
क्या आप आगे बता सकते हैं? यह हिस्सा document.querySelector ( "#" + f )मुझे एक त्रुटि देता है क्योंकि यह एक चयनकर्ता की अपेक्षा करता है, न कि एक स्ट्रिंग की।
मौरिस

1
@ मेरे लिए यह काम करता है: element.scrollIntoView()( elementफंक्शन में पास हुए बिना )। इसे सुचारू बनाने के लिए, इसका उपयोग करें element.scrollIntoView({block: "end", behavior: "smooth"}):।
श्री बी।

IntelliSense यहाँ से पता चलता है कि भीतर onAnchorClick(), हम scrollIntoView करने के लिए एक बूलियन से गुजरना होगा: if (element) { element.scrollIntoView(true); }। अब मैं एक ही लिंक पर दो बार क्लिक कर सकता हूं और स्क्रॉल काम कर सकता हूं
जूनियर मेहे

18

पिछले उत्तरों में से किसी ने भी मेरे लिए काम नहीं किया। एक आखिरी खाई में, मैंने अपने खाके में कोशिश की:

<a (click)="onClick()">From Here</a>
<div id='foobar'>To Here</div>

इसके साथ मेरे .ts में:

onClick(){
    let x = document.querySelector("#foobar");
    if (x){
        x.scrollIntoView();
    }
}

और यह आंतरिक लिंक की अपेक्षा के अनुसार काम करता है। यह वास्तव में एंकर टैग का उपयोग नहीं करता है इसलिए यह URL को बिल्कुल भी नहीं छूएगा।


1
सरल और आसान
वासिफ

6

ऊपर समाधान मेरे लिए काम नहीं किया ... यह एक किया:

सबसे पहले, ngAfterViewChecked ()MyAppComponent में स्वचालित स्क्रॉलिंग के लिए तैयार करें ...

import { Component, OnInit, AfterViewChecked } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';

@Component( {
   [...]
} )
export class MyAppComponent implements OnInit, AfterViewChecked {

  private scrollExecuted: boolean = false;

  constructor( private activatedRoute: ActivatedRoute ) {}

  ngAfterViewChecked() {

    if ( !this.scrollExecuted ) {
      let routeFragmentSubscription: Subscription;

      // Automatic scroll
      routeFragmentSubscription =
        this.activatedRoute.fragment
          .subscribe( fragment => {
            if ( fragment ) {
              let element = document.getElementById( fragment );
              if ( element ) {
                element.scrollIntoView();

                this.scrollExecuted = true;

                // Free resources
                setTimeout(
                  () => {
                    console.log( 'routeFragmentSubscription unsubscribe' );
                    routeFragmentSubscription.unsubscribe();
                }, 1000 );

              }
            }
          } );
    }

  }

}

फिर, हैशटैग my-app-routeभेजने के लिए नेविगेट करेंprodID

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

@Component( {
   [...]
} )
export class MyOtherComponent {

  constructor( private router: Router ) {}

  gotoHashtag( prodID: string ) {
    this.router.navigate( [ '/my-app-route' ], { fragment: prodID } );
  }

}

टिप्पणियों या स्पष्टीकरण के बिना मतदान करना ... यह एक अच्छा अभ्यास नहीं है ...
जेवियरफ्यून्स

यह मेरे लिए काम किया! हालांकि ngAit के बजाय ngAfterViewChecked का उपयोग क्यों करें?
एंटोनी बोइशियर-मिखौद

आपके सकारात्मक फीड-बैक के लिए @ AntoineBoisier-Michaud को धन्यवाद। ngInit में हमेशा फायर नहीं होता है, मुझे अपनी परियोजना की आवश्यकता होती है ... ngAfterViewChecked करता है। क्या आप कृपया इस समाधान को बढ़ा सकते हैं? धन्यवाद।
JavierFuentes

6

अन्य सभी उत्तर कोणीय संस्करण <6.1 पर काम करेंगे। लेकिन अगर आपको नवीनतम संस्करण मिल गया है तो आपको इन बदसूरत हैक्स को करने की आवश्यकता नहीं होगी क्योंकि एंगुलर ने इस मुद्दे को ठीक कर दिया है।

यहाँ जारी करने के लिए लिंक है

आपको scrollOffsetकेवल RouterModule.forRootविधि के दूसरे तर्क के विकल्प के साथ सेट करना होगा ।

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollPositionRestoration: 'enabled',
      anchorScrolling: 'enabled',
      scrollOffset: [0, 64] // [x, y]
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

2
क्या यह बाहरी लिंक के लिए काम करेगा? एक अन्य वेबसाइट से कहना है कि मैं www.abc.com # sectionToScrollTo पर क्लिक करता हूं
सागर

एंकरस्क्रोलिंग काम नहीं कर रहा है, अगर आप * ngIf का व्यापक उपयोग करते हैं, क्योंकि यह जल्दी कूदता है :-(
Jojo.Lechelt

केवल समस्या जो मुझे इस समय है, वह है - यह लंगर में कूदने से पहले कुछ तत्व की स्टाइल पूरी तरह से प्रस्तुत करने के लिए आ गई है, जिससे स्थिति बंद हो जाएगी। अच्छा होगा यदि आप एक देरी जोड़ सकते हैं :)
चार

5

राउटर मॉड्यूल के लिए इसका उपयोग करें app-routing.module.ts:

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    useHash: true,
    scrollPositionRestoration: 'enabled',
    anchorScrolling: 'enabled',
    scrollOffset: [0, 64]
  })],
  exports: [RouterModule]
})

यह आपके HTML में होगा:

<a href="#/users/123#userInfo">

4

Html फ़ाइल में:

<a [fragment]="test1" [routerLink]="['./']">Go to Test 1 section</a>

<section id="test1">...</section>
<section id="test2">...</section>

Ts फ़ाइल में:

export class PageComponent implements AfterViewInit, OnDestroy {

  private destroy$$ = new Subject();
  private fragment$$ = new BehaviorSubject<string | null>(null);
  private fragment$ = this.fragment$$.asObservable();

  constructor(private route: ActivatedRoute) {
    this.route.fragment.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
      this.fragment$$.next(fragment);
    });
  }

  public ngAfterViewInit(): void {
    this.fragment$.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
      if (!!fragment) {
        document.querySelector('#' + fragment).scrollIntoView();
      }
    });
  }

  public ngOnDestroy(): void {
    this.destroy$$.next();
    this.destroy$$.complete();
  }
}

क्वेरीसेलर को आसानी से स्क्रॉलल्टो नामक निर्देश में रखा जा सकता है। Url होगा <a scrollTo="test1" [routerLinkkes="I'.//thing"> परीक्षण 1 अनुभाग पर जाएं </a>
जॉन पीटर्स

3

चूंकि टुकड़े की संपत्ति अभी भी लंगर स्क्रॉलिंग प्रदान नहीं करती है, इसलिए इस समाधान ने मेरे लिए चाल चली:

<div [routerLink]="['somepath']" fragment="Test">
  <a href="#Test">Jump to 'Test' anchor </a>
</div>

3

कल्याणॉय के उत्तर को जोड़ते हुए , यह सदस्यता राउटर से जुड़ी होती है और तब तक जीवित रहेगी जब तक पेज पूरी तरह से ताज़ा नहीं हो जाता। जब एक घटक में राउटर घटनाओं की सदस्यता लेते हैं, तो ngOnDestroy में सदस्यता समाप्त करना सुनिश्चित करें:

import { OnDestroy } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { Subscription } from "rxjs/Rx";

class MyAppComponent implements OnDestroy {

  private subscription: Subscription;

  constructor(router: Router) {
    this.subscription = router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        const tree = router.parseUrl(router.url);
        if (tree.fragment) {
          const element = document.querySelector("#" + tree.fragment);
          if (element) { element.scrollIntoView(element); }
        }
      }
    });
  }

  public ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

मुझे लगा कि रूट इवेंट्स के लिए सब्स्क्रिप्शन स्वचालित रूप से फाड़ दिया गया।

3

मुझे बस अपनी वेबसाइट पर यह काम करना था, इसलिए मुझे लगा कि यह मेरे समाधान को यहां पोस्ट करने लायक होगा।

<a [routerLink]="baseUrlGoesHere" fragment="nameOfYourAnchorGoesHere">Link Text!</a>

<a name="nameOfYourAnchorGoesHere"></a>
<div>They're trying to anchor to me!</div>

और फिर अपने घटक में, सुनिश्चित करें कि आप इसे शामिल करते हैं:

 import { ActivatedRoute } from '@angular/router';

 constructor(private route: ActivatedRoute) { 
     this.route.fragment.subscribe ( f => {
         const element = document.querySelector ( "#" + f )
         if ( element ) element.scrollIntoView ( element )
     });
 }

मुझे लगता है कि सिर्फ element.scrollIntoView()या तो लिखना बेहतर है element.scrollIntoView(true)। आपके संस्करण ने मेरे लिए संकलन नहीं किया (हो सकता है कि सख़्त ननक्लचर के कारण?)।
डेविड एल।

3

सभी समाधानों को पढ़ने के बाद, मैंने एक घटक की तलाश की और मुझे एक ऐसा मिला जो वास्तव में मूल प्रश्न के लिए पूछा गया था: लंगर लिंक पर स्क्रॉल करना। https://www.npmjs.com/package/ng2-scroll-to

जब आप इसे स्थापित करते हैं, तो आप सिंटैक्स का उपयोग करते हैं:

// app.awesome.component.ts
@Component({
   ...
   template: `...
        <a scrollTo href="#main-section">Scroll to main section</a>
        <button scrollTo scrollTargetSelector="#test-section">Scroll to test section</a>
        <button scrollTo scrollableElementSelector="#container" scrollYTarget="0">Go top</a>
        <!-- Further content here -->
        <div id="container">
            <section id="main-section">Bla bla bla</section>
            <section id="test-section">Bla bla bla</section>
        <div>
   ...`,
})
export class AwesomeComponent {
}

इसने मेरे लिए वास्तव में अच्छा काम किया है।


पहिया का उपयोग करें, इसे फिर से आविष्कार न करें;)
योजन राय

क्या आपने उस घटक के पीछे के कोड को देखा है? यह बहुत नाजुक लग रहा है - परियोजना में 14 खुले मुद्दे भी हैं - जिसमें तत्व की मौजूद नहीं है, लक्ष्य को शून्य, तत्व को स्क्रॉल नहीं करना, ब्राउज़र समर्थन मुद्दों जैसी चीजें शामिल हैं।
17

माता-पिता के घटक में जब आपके पास बच्चा होता है (बच्चा लंगर वाली संस्थाएं और / या लंगर नाम रखता है) काम नहीं करता है, यह सिर्फ पृष्ठ को ताज़ा करता है
साशा बॉन्ड

3

एक सरल समाधान जो बिना किसी क्वेरी पैरामीटर के पृष्ठों के लिए काम करता है, वह है ब्राउज़र बैक / फॉरवर्ड, राउटर और डीप-लिंकिंग कंप्लेंट।

<a (click)="jumpToId('anchor1')">Go To Anchor 1</a>


ngOnInit() {

    // If your page is dynamic
    this.yourService.getWhatever()
        .then(
            data => {
            this.componentData = data;
            setTimeout(() => this.jumpToId( window.location.hash.substr(1) ), 100);
        }
    );

    // If your page is static
    // this.jumpToId( window.location.hash.substr(1) )
}

jumpToId( fragment ) {

    // Use the browser to navigate
    window.location.hash = fragment;

    // But also scroll when routing / deep-linking to dynamic page
    // or re-clicking same anchor
    if (fragment) {
        const element = document.querySelector('#' + fragment);
        if (element) element.scrollIntoView();
    }
}

टाइमआउट बस पेज को * एनजीआई द्वारा किसी भी गतिशील डेटा "संरक्षित" को लोड करने की अनुमति देने के लिए है। रूट बदलते समय पृष्ठ के शीर्ष पर स्क्रॉल करने के लिए भी इसका उपयोग किया जा सकता है - बस एक डिफ़ॉल्ट शीर्ष एंकर टैग प्रदान करें।


2

अगर यह उन तत्व आईडी के url से जुड़े होने से कोई फर्क नहीं पड़ता, तो आपको इस लिंक पर एक नज़र डालनी चाहिए:

कोणीय 2 - लंगर वर्तमान पृष्ठ पर तत्व के लिए लिंक

// html
// add (click) event on element
<a (click)="scroll({{any-element-id}})">Scroll</a>

// in ts file, do this
scroll(sectionId) {
let element = document.getElementById(sectionId);

  if(element) {
    element.scrollIntoView(); // scroll to a particular element
  }
 }


1

यहाँ JavierFuentes उत्तर के संदर्भ के साथ एक और समाधान है:

<a [routerLink]="['self-route', id]" fragment="some-element" (click)="gotoHashtag('some-element')">Jump to Element</a>

स्क्रिप्ट में:

import {ActivatedRoute} from "@angular/router";
import {Subscription} from "rxjs/Subscription";

export class Links {
    private scrollExecuted: boolean = false;

    constructor(private route: ActivatedRoute) {} 

    ngAfterViewChecked() {
            if (!this.scrollExecuted) {
              let routeFragmentSubscription: Subscription;
              routeFragmentSubscription = this.route.fragment.subscribe(fragment => {
                if (fragment) {
                  let element = document.getElementById(fragment);
                  if (element) {
                    element.scrollIntoView();
                    this.scrollExecuted = true;
                    // Free resources
                    setTimeout(
                      () => {
                        console.log('routeFragmentSubscription unsubscribe');
                        routeFragmentSubscription.unsubscribe();
                      }, 0);
                  }
                }
              });
            }
          }

        gotoHashtag(fragment: string) {
            const element = document.querySelector("#" + fragment);
            if (element) element.scrollIntoView(element);
        }
}

यह उपयोगकर्ता को सीधे तत्व पर स्क्रॉल करने की अनुमति देता है, अगर उपयोगकर्ता सीधे यूआरएल में हैशटैग वाले पृष्ठ पर भूमि करता है।

लेकिन इस मामले में, मैंने रूट फ़्रैगमेंट को सब्सक्राइब कर लिया है, ngAfterViewCheckedलेकिन ngAfterViewChecked()हर बार लगातार कॉल किया जाता है ngDoCheckऔर यह उपयोगकर्ता को शीर्ष पर वापस स्क्रॉल करने की अनुमति नहीं देता है, इसलिएrouteFragmentSubscription.unsubscribe तत्व को स्क्रॉल करने के बाद 0 मिली के टाइमआउट के बाद कॉल किया जाता है।

gotoHashtagजब उपयोगकर्ता विशेष रूप से एंकर टैग पर क्लिक करता है, तो इसके अलावा विधि को स्क्रॉल करने के लिए परिभाषित किया जाता है।

अपडेट करें:

अगर url में querystrings है, तो [routerLink]="['self-route', id]"अभ्यस्त अभ्रक को संरक्षित नहीं करेगा। मैंने उसी के लिए वर्कअराउंड का अनुसरण करने की कोशिश की:

<a (click)="gotoHashtag('some-element')">Jump to Element</a>

constructor( private route: ActivatedRoute,
              private _router:Router) {
}
...
...

gotoHashtag(fragment: string) {
    let url = '';
    let urlWithSegments = this._router.url.split('#');

    if(urlWithSegments.length){
      url = urlWithSegments[0];
    }

    window.location.hash = fragment;
    const element = document.querySelector("#" + fragment);
    if (element) element.scrollIntoView(element);
}

1

मेरे लिए यह एक काम !! यह ngFor तो यह गतिशील रूप से लंगर टैग, आप उन्हें रेंडर करने के लिए इंतजार करने की जरूरत है

HTML:

<div #ngForComments *ngFor="let cm of Comments">
    <a id="Comment_{{cm.id}}" fragment="Comment_{{cm.id}}" (click)="jumpToId()">{{cm.namae}} Reply</a> Blah Blah
</div>

मेरी ts फ़ाइल:

private fragment: string;
@ViewChildren('ngForComments') AnchorComments: QueryList<any>;

ngOnInit() {
      this.route.fragment.subscribe(fragment => { this.fragment = fragment; 
   });
}
ngAfterViewInit() {
    this.AnchorComments.changes.subscribe(t => {
      this.ngForRendred();
    })
}

ngForRendred() {
    this.jumpToId()
}

jumpToId() { 
    let x = document.querySelector("#" + this.fragment);
    console.log(x)
    if (x){
        x.scrollIntoView();
    }
}

आयात करने के लिए मत भूलना ViewChildren, QueryListआदि .. और कुछ निर्माता जोड़ने ActivatedRoute!!


1

अन्य उत्तरों के विपरीत मैं अतिरिक्त रूप से भी focus()साथ जोड़ूंगा scrollIntoView()। इसके अलावा मैं setTimeoutइसका उपयोग कर रहा हूं क्योंकि यह URL बदलते समय शीर्ष पर पहुंच जाता है। निश्चित नहीं है कि इसका कारण क्या था लेकिन ऐसा लगता setTimeoutहै कि यह समाधान है।

मूल:

<a [routerLink] fragment="some-id" (click)="scrollIntoView('some-id')">Jump</a>

गंतव्य:

<a id="some-id" tabindex="-1"></a>

टाइपप्रति:

scrollIntoView(anchorHash) {
    setTimeout(() => {
        const anchor = document.getElementById(anchorHash);
        if (anchor) {
            anchor.focus();
            anchor.scrollIntoView();
        }
    });
}

1

मेरी भी यही समस्या थी। समाधान: व्यू पोर्टलाइज़र का उपयोग करके https://angular.io/api/common/ViewportScroller#scrolltoanchor

- app-routing.module.ts कोड:

import { PageComponent } from './page/page.component';

const routes: Routes = [
   path: 'page', component: PageComponent },
   path: 'page/:id', component: PageComponent }
];

- घटक HTML

  <a (click) = "scrollTo('typeExec')">
    <mat-icon>lens</mat-icon>
  </a>

- घटक का कोड:

    import { Component } from '@angular/core';
    import { ViewportScroller } from '@angular/common';


    export class ParametrageComponent {

      constructor(private viewScroller: ViewportScroller) {}

      scrollTo(tag : string)
      {
        this.viewScroller.scrollToAnchor(tag);
      }

    }

0

मैंने सिर्फ nmp में उपलब्ध बहुत उपयोगी प्लगइन का परीक्षण किया है - एनजीएक्स-स्क्रॉल-टू , जो मेरे लिए बहुत अच्छा काम करता है। हालाँकि यह एंगुलर 4+ के लिए डिज़ाइन किया गया है, लेकिन हो सकता है कि किसी को यह उत्तर मददगार लगे।


0

मैंने इनमें से अधिकांश समाधानों की कोशिश की लेकिन समस्याओं में भाग गया और एक और टुकड़े के साथ वापस आ रहा था यह काम नहीं करेगा, इसलिए मैंने कुछ अलग किया जो 100% काम करता है, और URL में बदसूरत हैश से छुटकारा दिलाता है।

tl; यहाँ क्या मैंने अभी तक देखा है की तुलना में एक बेहतर तरीका है।

import { Component, OnInit, AfterViewChecked, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';

@Component({
    selector: 'app-hero',
    templateUrl: './hero.component.html',
    styleUrls: ['./hero.component.scss']
})
export class HeroComponent implements OnInit, AfterViewChecked, OnDestroy {
    private fragment: string;
    fragSub: Subscription;

    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        this.fragSub = this.route.fragment.subscribe( fragment => { this.fragment = fragment; })
    }

    ngAfterViewChecked(): void {
        try {
            document.querySelector('#' + this.fragment).scrollIntoView({behavior: 'smooth'});
            window.location.hash = "";
          } catch (e) { }
    }

    ngOnDestroy() {
        this.fragSub.unsubscribe();
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.