Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8f7d83d

Browse files
committed
refactor(sidebar-nav-link): signal inputs, test
1 parent6d21d97 commit8f7d83d

File tree

3 files changed

+75
-59
lines changed

3 files changed

+75
-59
lines changed

‎projects/coreui-angular/src/lib/sidebar/sidebar-nav/sidebar-nav-link.component.html‎

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,45 @@
1+
@let linkItem = item() ?? {};
2+
13
@switch (linkType) {
24
@case ('disabled') {
3-
<a[cHtmlAttr]="item.attributes ?? {}"[ngClass]="item | cSidebarNavLink">
4-
<ng-container*ngTemplateOutlet="iconTemplate; context: {$implicit:item}"/>
5-
<c-sidebar-nav-link-content[item]="item"/>
6-
@if (item.badge) {
7-
<span[ngClass]="item | cSidebarNavBadge">{{item.badge?.text }}</span>
5+
<a[cHtmlAttr]="linkItem.attributes ?? {}"[ngClass]="linkItem | cSidebarNavLink">
6+
<ng-container*ngTemplateOutlet="iconTemplate; context: {$implicit:linkItem}"/>
7+
<c-sidebar-nav-link-content[item]="linkItem"/>
8+
@if (linkItem.badge) {
9+
<span[ngClass]="linkItem | cSidebarNavBadge">{{linkItem.badge?.text }}</span>
810
}
911
</a>
1012
}
1113
@case ('external') {
12-
<a(click)="linkClicked()"[cHtmlAttr]="item.attributes ?? {}"[href]="href"[ngClass]="item | cSidebarNavLink">
13-
<ng-container*ngTemplateOutlet="iconTemplate; context: {$implicit:item}"/>
14-
<c-sidebar-nav-link-content[item]="item"/>
15-
@if (item.badge) {
16-
<span[ngClass]="item | cSidebarNavBadge">{{item.badge?.text }}</span>
14+
<a(click)="linkClicked()"[cHtmlAttr]="linkItem.attributes ?? {}"[href]="href"[ngClass]="linkItem | cSidebarNavLink">
15+
<ng-container*ngTemplateOutlet="iconTemplate; context: {$implicit:linkItem}"/>
16+
<c-sidebar-nav-link-content[item]="linkItem"/>
17+
@if (linkItem.badge) {
18+
<span[ngClass]="linkItem | cSidebarNavBadge">{{linkItem.badge?.text }}</span>
1719
}
1820
</a>
1921
}
2022
@default {
2123
<a(click)="linkClicked()"
22-
[cHtmlAttr]="item.attributes ?? {}"
23-
[fragment]="item.linkProps?.fragment"
24-
[ngClass]="item | cSidebarNavLink"
25-
[preserveFragment]="item.linkProps?.preserveFragment ?? false"
26-
[queryParamsHandling]="item.linkProps?.queryParamsHandling"
27-
[queryParams]="item.linkProps?.queryParams ?? null"
28-
[replaceUrl]="item.linkProps?.replaceUrl ?? false"
29-
[routerLinkActiveOptions]="item.linkProps?.routerLinkActiveOptions ?? { exact: false }"
30-
[routerLink]="item.url"
31-
[skipLocationChange]="item.linkProps?.skipLocationChange ?? false"
32-
[state]="item.linkProps?.state ?? {}"
33-
[target]="item.attributes?.['target']"
24+
[cHtmlAttr]="linkItem.attributes ?? {}"
25+
[fragment]="linkItem.linkProps?.fragment"
26+
[ngClass]="linkItem | cSidebarNavLink"
27+
[preserveFragment]="linkItem.linkProps?.preserveFragment ?? false"
28+
[queryParamsHandling]="linkItem.linkProps?.queryParamsHandling"
29+
[queryParams]="linkItem.linkProps?.queryParams ?? null"
30+
[replaceUrl]="linkItem.linkProps?.replaceUrl ?? false"
31+
[routerLinkActiveOptions]="linkItem.linkProps?.routerLinkActiveOptions ?? { exact: false }"
32+
[routerLink]="linkItem.url"
33+
[skipLocationChange]="linkItem.linkProps?.skipLocationChange ?? false"
34+
[state]="linkItem.linkProps?.state ?? {}"
35+
[target]="linkItem.attributes?.['target']"
3436
routerLinkActive="active"
3537
>
3638
<!-- [class.active]="linkActive"-->
37-
<ng-container*ngTemplateOutlet="iconTemplate ; context: {$implicit:item}"/>
38-
<c-sidebar-nav-link-content[item]="item"/>
39-
@if (item.badge) {
40-
<span[ngClass]="item | cSidebarNavBadge">{{item.badge?.text }}</span>
39+
<ng-container*ngTemplateOutlet="iconTemplate ; context: {$implicit:linkItem}"/>
40+
<c-sidebar-nav-link-content[item]="linkItem"/>
41+
@if (linkItem.badge) {
42+
<span[ngClass]="linkItem | cSidebarNavBadge">{{linkItem.badge?.text }}</span>
4143
}
4244
</a>
4345
}
Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import{ComponentFixture,TestBed,waitForAsync}from'@angular/core/testing';
2-
import{RouterTestingModule}from'@angular/router/testing';
3-
import{Router}from'@angular/router';
2+
import{provideRouter,Router}from'@angular/router';
43

54
import{SidebarNavLinkComponent}from'./sidebar-nav-link.component';
65
import{HtmlAttributesDirective}from'../../shared';
6+
import{By}from'@angular/platform-browser';
77

88
describe('SidebarNavLinkComponent',()=>{
99
letcomponent:SidebarNavLinkComponent;
@@ -13,12 +13,9 @@ describe('SidebarNavLinkComponent', () => {
1313

1414
beforeEach(waitForAsync(()=>{
1515
TestBed.configureTestingModule({
16-
imports:[RouterTestingModule.withRoutes([]),
17-
HtmlAttributesDirective,
18-
SidebarNavLinkComponent
19-
]
20-
})
21-
.compileComponents();
16+
imports:[HtmlAttributesDirective,SidebarNavLinkComponent],
17+
providers:[provideRouter([])]
18+
}).compileComponents();
2219
}));
2320

2421
beforeEach(()=>{
@@ -31,11 +28,11 @@ describe('SidebarNavLinkComponent', () => {
3128
url:'/dashboard',
3229
icon:'cil-speedometer',
3330
badge:{
34-
variant:'info',
31+
color:'info',
3532
text:'NEW'
3633
}
3734
};
38-
component.item=item;
35+
fixture.componentRef.setInput('item',item);
3936

4037
// router.initialNavigation();
4138
fixture.detectChanges();
@@ -44,4 +41,25 @@ describe('SidebarNavLinkComponent', () => {
4441
it('should create',()=>{
4542
expect(component).toBeTruthy();
4643
});
44+
45+
it('should have item with name "Dashboard"',()=>{
46+
constlink=fixture.debugElement.query(By.css('a')).nativeElement;
47+
expect(link.textContent).toContain('Dashboard');
48+
});
49+
50+
it('should have correct URL',()=>{
51+
constlink=fixture.debugElement.query(By.css('a')).nativeElement;
52+
expect(link.getAttribute('href')).toBe('/dashboard');
53+
});
54+
55+
it('should have correct icon class',()=>{
56+
consticon=fixture.debugElement.query(By.css('.cil-speedometer')).nativeElement;
57+
expect(icon).toBeTruthy();
58+
});
59+
60+
it('should have badge with text "NEW"',()=>{
61+
constbadge=fixture.debugElement.query(By.css('.badge')).nativeElement;
62+
expect(badge.textContent).toContain('NEW');
63+
expect(badge.classList).toContain('bg-info');
64+
});
4765
});

‎projects/coreui-angular/src/lib/sidebar/sidebar-nav/sidebar-nav-link.component.ts‎

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import{NgClass,NgTemplateOutlet}from'@angular/common';
2-
import{Component,inject,Input,OnDestroy,OnInit,output}from'@angular/core';
2+
import{Component,inject,input,OnDestroy,OnInit,output}from'@angular/core';
3+
import{takeUntilDestroyed}from'@angular/core/rxjs-interop';
34
import{NavigationEnd,Router,RouterModule}from'@angular/router';
45
import{Observable,Subscription}from'rxjs';
56
import{filter}from'rxjs/operators';
6-
import{IconDirective}from'@coreui/icons-angular';
77

8+
import{IconDirective}from'@coreui/icons-angular';
89
// import {SidebarService} from '../sidebar.service';
910
import{HtmlAttributesDirective}from'../../shared';
1011
import{SidebarNavHelper}from'./sidebar-nav.service';
@@ -16,16 +17,17 @@ import { SidebarNavIconPipe } from './sidebar-nav-icon.pipe';
1617
@Component({
1718
selector:'c-sidebar-nav-link-content',
1819
template:`
19-
@if (true) {
20-
<ng-container>{{ item?.name ?? '' }}</ng-container>
20+
@let itemLinkContent = item();
21+
@if (itemLinkContent) {
22+
<ng-container>{{ itemLinkContent?.name ?? '' }}</ng-container>
2123
}
2224
`,
2325
providers:[SidebarNavHelper]
2426
})
2527
exportclassSidebarNavLinkContentComponent{
2628
readonlyhelper=inject(SidebarNavHelper);
2729

28-
@Input()item?:INavData;
30+
readonlyitem=input<INavData>({});
2931
}
3032

3133
@Component({
@@ -47,16 +49,7 @@ export class SidebarNavLinkContentComponent {
4749
exportclassSidebarNavLinkComponentimplementsOnInit,OnDestroy{
4850
readonlyrouter=inject(Router);
4951

50-
protected_item:INavData={};
51-
52-
@Input()
53-
setitem(item:INavData){
54-
this._item=JSON.parse(JSON.stringify(item));
55-
}
56-
57-
getitem():INavData{
58-
returnthis._item;
59-
}
52+
readonlyitem=input<INavData>();
6053

6154
readonlylinkClick=output();
6255

@@ -74,17 +67,19 @@ export class SidebarNavLinkComponent implements OnInit, OnDestroy {
7467
this.navigationEndObservable=router.events.pipe(
7568
filter((event)=>{
7669
returneventinstanceofNavigationEnd;
77-
})
70+
}),
71+
takeUntilDestroyed()
7872
)asObservable<NavigationEnd>;
7973
}
8074

8175
ngOnInit():void{
76+
constitem=this.item()??{};
8277
this.url=
83-
typeofthis.item.url==='string'
84-
?this.item.url
85-
:this.router.serializeUrl(this.router.createUrlTree((this.item.urlasany[])??['']));
78+
typeofitem.url==='string'
79+
?item.url
80+
:this.router.serializeUrl(this.router.createUrlTree((item.urlasany[])??['']));
8681
this.linkType=this.getLinkType();
87-
this.href=this.isDisabled() ?'' :this.item.href||this.url;
82+
this.href=this.isDisabled() ?'' :item.href||this.url;
8883
this.linkActive=this.router.url.split(/[?#(;]/)[0]===this.href.split(/[?#(;]/)[0];
8984
this.navSubscription=this.navigationEndObservable.subscribe((event)=>{
9085
constitemUrlArray=this.href.split(/[?#(;]/)[0].split('/');
@@ -102,12 +97,13 @@ export class SidebarNavLinkComponent implements OnInit, OnDestroy {
10297
}
10398

10499
publicisDisabled():boolean{
105-
returnthis.item?.attributes?.['disabled'];
100+
returnthis.item()?.attributes?.['disabled'];
106101
}
107102

108103
publicisExternalLink():boolean{
109-
constlinkPath=Array.isArray(this.item.url) ?this.item.url[0] :this.item.url;
110-
return!!this.item.href||linkPath?.substring(0,4)==='http';
104+
constitem=this.item()??{};
105+
constlinkPath=Array.isArray(item.url) ?item.url[0] :item.url;
106+
return!!item.href||linkPath?.substring(0,4)==='http';
111107
}
112108

113109
linkClicked():void{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp