gpt4 book ai didi

Angular:配置默认的QueryParamsHandling

转载 作者:行者123 更新时间:2023-12-05 03:52:54 24 4
gpt4 key购买 nike

我构建了一个 angular 9 应用程序,并使用 @ngx-translate 添加了本地化。我已配置我的应用程序,使其采用 lang 查询参数并相应地更改语言环境。

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy {
constructor(private route: ActivatedRoute, private translateService: TranslateService) {
this.translateService.setDefaultLang('en');
this.route.queryParamMap.subscribe((params) => {
let lang = params.get('lang');
console.log('language', lang);
if (lang !== null) {
this.translateService.use(lang);
}
});
}
}

然后我在侧边栏上添加了 3 个按钮来更改查询参数(并切换语言)

<div class="p-1 text-center">
<a [routerLink]='[]' [queryParams]="{}">
<app-flag [country]="'en'" [appHoverClass]="'brightness-250'"></app-flag>
</a>
<a [routerLink]='[]' [queryParams]="{'lang':'nl'}">
<app-flag [country]="'nl'" [appHoverClass]="'brightness-250'"></app-flag>
</a>
<a [routerLink]='[]' [queryParams]="{'lang':'fr'}">
<app-flag [country]="'fr'" [appHoverClass]="'brightness-250'"></app-flag>
</a>
</div>

这工作正常。但是当按下普通的 routerLink 时,或者在 router.navigate() 调用时,查询参数再次丢失。

我不想用 [queryParamsHandling]="'preserve'" 指令装饰我的应用程序中的每个 routerLink,因为这是一项乏味的工作并且可怕的做法。这个主题已经有一个 GitHub 问题,但是 Angular 团队几乎没有处理它(已经 4 年了):https://github.com/angular/angular/issues/12664

有没有办法(任何方式)在导航时默认保留查询参数(或只是 lang 查询参数)?

我已经在默认的 Angular 路由器之上创建了一个ExtendedRouter

import { Router, QueryParamsHandling, NavigationExtras, UrlTree } from '@angular/router';

export class ExtendedRouter {
constructor(private router: Router) {
}

private _defaultQueryParamsHandling: QueryParamsHandling = null;
public get defaultQueryParamsHandling() {
return this._defaultQueryParamsHandling;
}
public set defaultQueryParamsHandling(value: QueryParamsHandling) {
this._defaultQueryParamsHandling = value;
}

public navigate(commands: any[], extras?: NavigationExtras) {
return this.router.navigate(commands, {
queryParamsHandling: extras.queryParamsHandling ?? this.defaultQueryParamsHandling ?? '',
fragment: extras.fragment,
preserveFragment: extras.preserveFragment,
queryParams: extras.queryParams,
relativeTo: extras.relativeTo,
replaceUrl: extras.replaceUrl,
skipLocationChange: extras.skipLocationChange
});
}

public navigateByUrl(url: string | UrlTree, extras?: NavigationExtras) {
return this.router.navigateByUrl(url, {
queryParamsHandling: extras.queryParamsHandling ?? this.defaultQueryParamsHandling ?? '',
fragment: extras.fragment,
preserveFragment: extras.preserveFragment,
queryParams: extras.queryParams,
relativeTo: extras.relativeTo,
replaceUrl: extras.replaceUrl,
skipLocationChange: extras.skipLocationChange
});
}

public createUrlTree(commands: any[], extras?: NavigationExtras) {
return this.router.createUrlTree(commands, extras);
}

public serializeUrl(url: UrlTree) {
return this.router.serializeUrl(url);
}
}

但这并不涉及[routerLink] 指令。我也尝试创建一个,但我需要的所有字段都限定为 private

import { Directive, Renderer2, ElementRef, Attribute, Input } from '@angular/core';
import { RouterLink, Router, ActivatedRoute } from '@angular/router';
import { ExtendedRouter } from '../../helpers/extended-router';

@Directive({
selector: '[extendedRouterLink]'
})
export class ExtendedRouterLinkDirective extends RouterLink {

private router2: Router;
private route2: ActivatedRoute;
private commands2: any[] = [];
constructor(router: Router, route: ActivatedRoute, @Attribute('tabindex') tabIndex: string, renderer: Renderer2, el: ElementRef<any>, private extendedRouter: ExtendedRouter) {
super(router, route, tabIndex, renderer, el);
this.router2 = router;
this.route2 = route;
}

@Input()
set extendedRouterLink(commands: any[] | string | null | undefined) {
if (commands != null) {
this.commands2 = Array.isArray(commands) ? commands : [commands];
} else {
this.commands2 = [];
}
super.commands = commands;
}

get urlTree() {
return this.router2.createUrlTree(this.commands, {
relativeTo: this.route2,
queryParams: this.queryParams,
fragment: this.fragment,
queryParamsHandling: this.queryParamsHandling,
preserveFragment: this.attrBoolValue(this.preserveFragment),
});
}

private attrBoolValue = (s: any) => {
return s === '' || !!s;
}

}

有人知道如何解决这个问题而不必在每个 [routerLink] 上定义一个 [queryParamsHandling] 吗?

最佳答案

这种方法有一个小问题:


@Directive({
selector: 'a[routerLink]'
})
export class QueryParamsHandlingDirective extends RouterLinkWithHref {
queryParamsHandling: QueryParamsHandling = 'merge';
}

问题是它扩展了RouterLinkWithHref , 意思是 <a routerLink="">将附加 2 个指令(一个扩展另一个)。

this is what happens里面RouterLinkWithHrefclick处理程序:

@HostListener('click')
onClick(): boolean {
const extras = {
skipLocationChange: attrBoolValue(this.skipLocationChange),
replaceUrl: attrBoolValue(this.replaceUrl),
state: this.state,
};
this.router.navigateByUrl(this.urlTree, extras);
return true;
}

更重要的是它在发送到浏览器时的外观:

 RouterLinkWithHref.prototype.onClick = function (button, ctrlKey, metaKey, shiftKey) {
if (button !== 0 || ctrlKey || metaKey || shiftKey) {
return true;
}
if (typeof this.target === 'string' && this.target != '_self') {
return true;
}
var extras = {
skipLocationChange: attrBoolValue(this.skipLocationChange),
replaceUrl: attrBoolValue(this.replaceUrl),
state: this.state
};
this.router.navigateByUrl(this.urlTree, extras);
return false;
};

这意味着当您点击 <a>标记,QueryParamsHandlingDirective.onClick将被调用,然后 RouterLinkWithHref.onClick .但是因为 RouterLinkWithHref.onClick最后调用,它不会有 queryParamsHandling设置为 merge .


解决方案是稍微修改自定义指令,使其不继承任何东西,而只是设置一个属性:

@Directive({
selector: 'a[routerLink]'
})
export class QueryParamsHandlingDirective {
constructor (routerLink: RouterLinkWithHref) {
routerLink.queryParamsHandling = 'merge';
}
}

StackBlitz .

关于Angular:配置默认的QueryParamsHandling,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61988093/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com