- bootstrap Tab 기능 구현해 보기.
- Tab기능을 C#코드로 구현해 보기.
- blazor에서 bootStrap에서 가져온 소스가 Tab기능이 작동 하지 않음.
일반 .html페이지에서는 구동 되지만 blazor프로젝트에서는 구동 되지 않아
3번째 소재목3. scroll기능 해결방법
에 해결 방법 기재.
- TabDemo.razor 페이지 생성.
- 네비게이션에서 호스팅 설정.
@page "/Samples/TabDemo"
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="profile-tab" data-bs-toggle="tab" href="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Contact</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">tab1</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">tab2</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">tab3</div>
</div>
<hr />
<ul class="nav nav-tabs" id="myTab2" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link @tab1Active" @onclick=@(() => Clicked(1) )>Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link @tab2Active" @onclick=@(() => Clicked(2))>Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link @tab3Active" @onclick=@(() => Clicked(3))>Contact</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade @tabPanle1Active" id="home" role="tabpanel" aria-labelledby="home-tab">tab1</div>
<div class="tab-pane fade @tabPanle2Active" id="profile" role="tabpanel" aria-labelledby="profile-tab">tab2</div>
<div class="tab-pane fade @tabPanle3Active" id="contact" role="tabpanel" aria-labelledby="contact-tab">tab3</div>
</div>
@code {
string tab1Active = "active";
string tab2Active = "";
string tab3Active = "";
string tabPanle1Active = "show active";
string tabPanle2Active = "";
string tabPanle3Active = "";
public void Clicked(int i )
{
switch(i)
{
case 1:
tab1Active = "active";
tab2Active = "";
tab3Active = "";
tabPanle1Active = "show active";
tabPanle2Active = "";
tabPanle3Active = "";
break;
case 2:
tab1Active = "";
tab2Active = "active";
tab3Active = "";
tabPanle1Active = "";
tabPanle2Active = "show active";
tabPanle3Active = "";
break;
case 3:
tab1Active = "";
tab2Active = "";
tab3Active = "active";
tabPanle1Active = "";
tabPanle2Active = "";
tabPanle3Active = "show active";
break;
}
}
}
<!--<div id="collapseDemo" class="collapse" aria-labelledby="headingPages" 에서 id를 변경하지 않고 그대로 사용 하면 기존 메뉴와 동시에 동작됨.-->
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseDemo" @* <!--변경--> *@ aria-expanded="true"
aria-controls="collapseDemo">
@* <!--변경--> *@
<i class="fas fa-fw fa-folder"></i>
<span>Samples@* <!--변경--> *@</span>
</a>
<div id="collapseDemo" @* <!--변경--> *@ class="collapse" aria-labelledby="headingPages"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">LECTURE SAMPLES:</h6>
<a class="collapse-item" href="/Samples/TodoListInMemory">TodoListInMemory</a>@* <!--변경--> *@
<a class="collapse-item" href="/Samples/TabDemo">Tab</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="/Samples/Test">404 Page</a>
<a class="collapse-item" href="/Pages/BlankPage">Blank Page</a>
</div>
</div>
</li>
<a class="collapse-item" href="/Samples/TabDemo">Tab</a>
코드 추가.
- 아래방법이 최선의 방법인지는 모르겠지만 아래와 같은 방법으로 진행시 해결됨.
- 참조사이트
- 혹시 사이트가 사라질 경우를 대비 해 해당내용 스크랩.
<script>
function BlazorScrollToId(id) {
const element = document.getElementById(id);
if (element instanceof HTMLElement) {
element.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest"
});
}
}
</script>
- OnLocationChanged을 컴포넌트 인스턴스시 구독을 시킴.
- OnLocationChanged은 로케이션 체인지가 될때 발생하는 이벤트.
- 페이지 이동이 일어날때 ScrollToFragment메소드를 실행 시켜서 _layout에 추가시킨 BlazorScrollToId 함수를 사용하여 스크롤 기능 구현.
@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
@implements IDisposable
@code {
protected override void OnInitialized()
{
NavigationManager.LocationChanged += OnLocationChanged;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await ScrollToFragment();
}
public void Dispose()
{
NavigationManager.LocationChanged -= OnLocationChanged;
}
private async void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
await ScrollToFragment();
}
private async Task ScrollToFragment()
{
var uri = new Uri(NavigationManager.Uri, UriKind.Absolute);
var fragment = uri.Fragment;
if (fragment.StartsWith('#'))
{
// Handle text fragment (https://example.org/#test:~:text=foo)
// https://github.com/WICG/scroll-to-text-fragment/
var elementId = fragment.Substring(1);
var index = elementId.IndexOf(":~:", StringComparison.Ordinal);
if (index > 0)
{
elementId = elementId.Substring(0, index);
}
if (!string.IsNullOrEmpty(elementId))
{
await JSRuntime.InvokeVoidAsync("BlazorScrollToId", elementId);
}
}
}
}
- 참조 사이트에서는
GetHref
에서 #만을 앞에 붙여 동작된다고 되어 있지만
현재 시점으로 테스트 했을때 그럴경우 index페이지로 이동됨.- #앞에 현재 페이지의 라우팅 경로를 넣어주면 정상동작 확인 됨.
@page "/Samples/Test"
<strong>Table of Contents</strong>
<ul>
@for (int i = 0; i < 10; i++)
{
<li><a href="@GetHref(i)">Header @i</a></li>
}
</ul>
@for (int i = 0; i < 10; i++)
{
<h1 id="@GetId(i)">Header @i</h1>
@LoremNET.Lorem.Paragraph(wordCount: 30, sentenceCount: 10)
}
@* 👇 Integrate the component *@
<AnchorNavigation />
@code {
string routingPath = "/Samples/Test";
string GetId(int i) => "header-" + i;
string GetHref(int i) => $"{routingPath}#" + GetId(i);
}
유익한 자료 감사합니다.