انگولار - مسیریابی پویا با تبها در انگولار ۲ و ۴


امروز با مشکل مسیریابی مواجه شدم که نیاز به کمک شما دارم،

در واقع، من یک نوار کناری دارم که در آن ناوبریهای درختی پویا مانند زیر دارم و در سمت راست، ۴ تب دارم که تب پیشفرض، تب ۱، انتخاب خواهد شد و در آن دادههای لینک فعال را نمایش میدهم

Link1
--sublink1
--sublink2
----sub2link1
------sub3link1
Link2
Link3
--sublink1
----sub2link1

مانند بالا، من N زیرمنو دارم، برای این، من یک مسیر ایجاد کردهام

{ path: '**', component: tab1}

وقتی من لینک "link1/sublink2/sub2link1" را بازدید میکنم، به طور پیشفرض یک کامپوننت tab1 خواهد بود

حالا سوال من این است که اگر بخواهم به کامپوننت tab2 با همان لینک بروم، پس آدرس مسیر من باید چگونه باشد.

پاسخ شماره ۱

من به سوال خودم پاسخ میدهم، آن را با استفاده از پارامتر پرس و جو حل کردم، روش من در زیر آمده است:

ماژول مسیریابی من خواهد بود:

const routes: Routes = [
{
  path: 'parent',
  component: parentComponent,
  children: [
    { path: '', component: allChildComponent},
    { path: '**', component: allChildComponent}
  ]
}
];

پس این تا N تعداد مسیر درختی مانند /parent/child/sub_child1/sub_child2/../../.... برای ناوبری را میپذیرد، برای ناوبری کافی است استفاده کنید

this.router.navigate(['/parent/child/sub_child1/sub_child2/../../....']);

حالا اگر بخواهیم پارامترها را به مسیر ** منتقل کنیم، باید از پارامتر پرسوجو استفاده کنید که هنگام مسیریابی به شکل زیر خواهد بود

this.router.navigate(
   ['/parent/child/sub_child1/sub_child2/../../....'],
   {queryParams: 
       {param1: 'value1', param2: 'value2'}
   }
);

و در نهایت، شما میتوانید این پارامتر را در کامپوننت به صورت زیر بخوانید

constructor(private route: ActivatedRoute) { }

ngOnInit() {
  this.sub = this.route.queryParams
    .subscribe(params => {
      console.log(params);
    });
}

پاسخ شماره ۲

شما نمیتوانید این را با یک مسیر همگانی مثل آن بدون نوشتن منطق سفارشی برای ذخیرهسازی وضعیت انجام دهید.

دو راه وجود دارد که میتوانید به آنچه میخواهید برسید (هر دو مثال در زیر نشان داده شده است).

  1. از مسیرهای منحصر به فرد استفاده کنید. به این ترتیب میتوانید از routerLink استفاده کنید و به راحتی تعیین کنید که کدام مسیر بر اساس تنظیمات مسیر فعال است. با این روش، نمیتوانید از مسیرهای catchall ** استفاده کنید، زیرا این وابسته به مسیر است.
  2. از نوعی حالت استفاده کنید، همراه با ترکیبی از Observables به طوری که بتوانید نوار کناری را از هر جایی تغییر دهید و مسیر فعال را به هر شکلی تعیین کنید. با این روش، میتوانید از مسیر catchall ** استفاده کنید، زیرا این به روتر وابسته نیست.

من دو مثال را در زیر نشان خواهم داد، اما قبل از آن باید یک هشدار بدهم. این پاسخ بر اساس هیچ دانشی از منطق کسب و کار شما نیست.

منظورم از این این است که اگر نوار کناری شما مبتنی بر داده باشد، میتواند نحوه انجام کارها را تغییر دهد. به عنوان مثال، من یک نوار کناری با نمای درختی مشابه مثال شما در برنامه خود دارم، اما نوار کناری من مبتنی بر پایگاه داده است، به این معنی که هر آیتم دارای یک شناسه منحصر به فرد است. با آن شناسه، من میتوانم به راحتی از مسیرهایی مانند /topic/:topicId/subtopic/:subtopicId استفاده کنم و به سادگی لینک فعال در نوار کناری خود را فقط با گوش دادن به رویدادهای مسیریاب و تنظیم لینک فعال اگر topicId فعلی در URL برابر با یک topicId خاص در لینک نوار کناری باشد، فعال کنم و غیره. این کار را بسیار ساده میکند.

با این حال، این هم برای شما:

روش شماره 1

با لینکهای درختی زیر، میتوانید به لینکهای زیر بروید و لینک مربوطه فعال خواهد شد:

  1. /link1
  2. /link1/sublink1
  3. /link1/sublink1/sub2link1
  4. /link1/sublink2
  5. /link2
  6. /link3

نمونه نوار کناری:

<ul>
    <li>
        <a [routerLink]="['/link1']" [routerLinkActive]="'active'">Link1</a>

        <ul>
            <li>
                <a [routerLink]="['/link1/sublink1']" [routerLinkActive]="'active'">Sublink1</a>

                <ul>
                    <li>
                        <a [routerLink]="['/link1/sublink1/sub2link1']" [routerLinkActive]="'active'">Sub2link1</a>
                    </li>
                </ul>
            </li>
            <li>
                <a [routerLink]="['/link1/sublink2']" [routerLinkActive]="'active'">Sublink2</a>
            </li>
        </ul>
    </li>
    <li>
        <a [routerLink]="['/link2']" [routerLinkActive]="'active'">Link2</a>
    </li>
    <li>
        <a [routerLink]="['/link3']" [routerLinkActive]="'active'">Link3</a>
    </li>
</ul>

روش شماره ۲

با این روش، به جای استفاده از routerLink برای ناوبری، ممکن است مجبور شوید یک تابع تعریفشده در کامپوننت خود یا یک سرویس جایی صدا بزنید، و کاری که آن تابع انجام میدهد این است که قبل از ناوبری، مقداری از حالت را تنظیم کند. زمانی که آن حالت تنظیم شد، سایدبار باید به تغییرات گوش دهد (شاید یک Observable) و سایدبار میتواند فعال بودن لینکهای خاص را بر اساس آن تغییرات تغییر دهد.

در اینجا یک مثال کد شبهنویسی آمده است:

الگو :

<ul>
    <li>
        <a (click)="toggleSidebar('link1')" [class.active]="activeLink === 'link1'">Link1</a>
    </li>
    <li>
        <a (click)="toggleSidebar('link2')" [class.active]="activeLink === 'link2'">Link2</a>

        <ul>
            <li>
                <a (click)="toggleSidebar('link2/sublink1')" [class.active]="activeLink === 'link2/sublink1'">Link2 Sublink1</a>
            </li>
        </ul>
    </li>
</ul>

جزء :

@Component({...})
export class MyComponent implements OnInit {
    activeLink: string;

    constructor(private sidebarService: SideberService) {}

    ngOnInit() {
        this.sidebarService.activeLink$.subscribe((activeLink: string) => {
            this.activeLink = activeLink;
        }));
    }

    toggleSidebar(activeLink: string) {
        this.sidebarService.activeLink.next(activeLink);
    }
}

خدمت :

@Injectable()
export class SidebarService {
    activeLink: ReplaySubject<string> = new ReplaySubject();
    activeLink$: Observable<string> = this.activeLink.asObservable();
}

اکنون هر زمان که مقداری را به جریان sidebarService.activeLink ارسال کنید، کامپوننت سایدبار (که باید به این observable مشترک شود) لینک فعال سایدبار را دریافت خواهد کرد، که سپس میتوانید آن را در قالب خود همانطور که در مثال من نشان داده شده استفاده کنید تا یک لینک خاص سایدبار را تغییر وضعیت دهید.

اگر میخواهید نوار کناری به طور پیشفرض به یک لینک خاص برود، میتوانید از ReplaySubject به BehaviorSubject تغییر دهید و یک مقدار پیشفرض به آن بدهید، مانند link1. به عنوان مثال:

@Injectable()
export class SidebarService {
    activeLink: BehaviorSubject<string> = new BehaviorSubject('link1');
    activeLink$: Observable<string> = this.activeLink.asObservable();
}

به این ترتیب هنگام بارگذاری صفحه، link1 در نوار کناری به طور پیشفرض فعال خواهد بود، زیرا این مقدار اولیه در جریان است.