Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions BootstrapBlazor.Extensions.sln
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootstrapBlazor.Html2Pdf.Pl
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootstrapBlazor.JitsiMeet", "src\components\BootstrapBlazor.JitsiMeet\BootstrapBlazor.JitsiMeet.csproj", "{08458CA3-BF81-48E8-870D-9389DC037808}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootstrapBlazor.PdfViewer", "src\components\BootstrapBlazor.PdfViewer\BootstrapBlazor.PdfViewer.csproj", "{4757B038-70E4-40B0-9B73-700EE5632B07}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -510,6 +512,10 @@ Global
{08458CA3-BF81-48E8-870D-9389DC037808}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08458CA3-BF81-48E8-870D-9389DC037808}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08458CA3-BF81-48E8-870D-9389DC037808}.Release|Any CPU.Build.0 = Release|Any CPU
{4757B038-70E4-40B0-9B73-700EE5632B07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4757B038-70E4-40B0-9B73-700EE5632B07}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4757B038-70E4-40B0-9B73-700EE5632B07}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4757B038-70E4-40B0-9B73-700EE5632B07}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -598,6 +604,7 @@ Global
{CED55D86-57CF-CB0D-E880-370C44C0DB1F} = {FF1089BE-C704-4374-B629-C57C08E1798F}
{F3043A78-1942-4524-BDC4-7E88F56DF3D5} = {FF1089BE-C704-4374-B629-C57C08E1798F}
{08458CA3-BF81-48E8-870D-9389DC037808} = {FF1089BE-C704-4374-B629-C57C08E1798F}
{4757B038-70E4-40B0-9B73-700EE5632B07} = {FF1089BE-C704-4374-B629-C57C08E1798F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D5EB1960-6F30-4CE1-B375-EAE1F787D6FF}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>9.0.0-beta01</Version>
</PropertyGroup>

<PropertyGroup>
<PackageTags>Bootstrap Blazor WebAssembly wasm UI Components Pdf Viewer</PackageTags>
<Description>Bootstrap UI components extensions of Pdf Viewer</Description>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="$(BBVersion)" />
</ItemGroup>

<ItemGroup>
<Using Include="BootstrapBlazor.Components" />
<Using Include="Microsoft.JSInterop" />
</ItemGroup>

</Project>
5 changes: 5 additions & 0 deletions src/components/BootstrapBlazor.PdfViewer/PdfViewer.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@namespace BootstrapBlazor.Components
@inherits BootstrapModuleComponentBase
@attribute [JSModuleAutoLoader("./_content/BootstrapBlazor.PdfViewer/PdfViewer.razor.js", JSObjectReference = true, AutoInvokeDispose = false)]

<div @attributes="AdditionalAttributes" id="@Id" data-bb-url="@Url" class="@ClassString" style="@StyleString"></div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Merge user-defined inline styles with component-generated styles

Extract the style attribute from AdditionalAttributes and merge it with StyleString to ensure user-defined styles are preserved.

62 changes: 62 additions & 0 deletions src/components/BootstrapBlazor.PdfViewer/PdfViewer.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

using Microsoft.AspNetCore.Components;

namespace BootstrapBlazor.Components;

/// <summary>
/// PdfViewer component for displaying PDF files in a Blazor application.
/// </summary>
public partial class PdfViewer
{
/// <summary>
/// Gets or sets the url for the PDF file to be displayed.
/// </summary>
[Parameter]
public string? Url { get; set; }

/// <summary>
/// Gets or sets the viewer height. Default is null.
/// </summary>
[Parameter]
public string? Height { get; set; }

private string? ClassString => CssBuilder.Default("bb-pdf-viewer-container")
.AddClassFromAttributes(AdditionalAttributes)
.Build();

private string? StyleString => CssBuilder.Default()
.AddClass($"--bb-pdf-viewer-height: {Height};", !string.IsNullOrEmpty(Height))
.Build();

private string? _url;

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
/// <returns></returns>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);

if (firstRender)
{
_url = Url;
}

if (_url != Url)
{
_url = Url;
await InvokeVoidAsync("loadPdf", Id, _url);
}
}

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Implement disposal to clean up resources

Override DisposeAsync to remove the injected CSS link, clear the container, and delete the entry from Data to prevent memory leaks.

Suggested implementation:

    /// <summary>
    /// <inheritdoc/>
    /// </summary>
    /// <returns></returns>
    protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id);

    /// <inheritdoc/>
    public override async ValueTask DisposeAsync()
    {
        // Remove the injected CSS link
        await InvokeVoidAsync("removePdfViewerCss", Id);

        // Clear the container
        await InvokeVoidAsync("clearPdfViewerContainer", Id);

        // Remove the entry from Data to prevent memory leaks
        Data.Remove(Id);

        await base.DisposeAsync();
    }
}
  • You must implement the corresponding JavaScript functions removePdfViewerCss and clearPdfViewerContainer if they do not already exist.
  • Ensure that Data is accessible and is the correct dictionary holding component state; adjust the removal logic if needed.
  • If the base class does not have an async Dispose pattern, adjust to match the correct disposal pattern for your component base.

}
34 changes: 34 additions & 0 deletions src/components/BootstrapBlazor.PdfViewer/PdfViewer.razor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { addLink } from "../BootstrapBlazor/modules/utility.js"
import Data from "../BootstrapBlazor/modules/data.js"

export async function init(id) {
await addLink("./_content/BootstrapBlazor.PdfViewer/pdf-viewer.css");

const el = document.getElementById(id);
const pdfViewer = { el };
Data.set(id, pdfViewer);

const url = el.getAttribute('data-bb-url');
loadPdf(id, url);
}

export function loadPdf(id, url) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Guard against missing pdfViewer in Data

Check if pdfViewer is defined before destructuring to avoid runtime errors.

const pdfViewer = Data.get(id);
const { el } = pdfViewer;
if (url) {
const { frame } = pdfViewer;
const viewer = frame || createFrame(el);
viewer.src = url;
Comment on lines +20 to +21
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Cache the iframe reference in pdfViewer

Assign the new iframe to pdfViewer.frame to avoid creating multiple iframes when updating the URL.

}
else {
delete pdfViewer.frame;
el.innerHTML = '';
}
}

const createFrame = el => {
const frame = document.createElement('iframe');
frame.classList.add('bb-pdf-viewer');
el.appendChild(frame);
return frame;
}
2 changes: 2 additions & 0 deletions src/components/BootstrapBlazor.PdfViewer/_Imports.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@using BootstrapBlazor.Components;
@using Microsoft.AspNetCore.Components.Web
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.bb-pdf-viewer-container {
width: 100%;
height: var(--bb-pdf-viewer-height, 500px);
}

.bb-pdf-viewer {
width: 100%;
height: 100%;
Comment on lines +6 to +8
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider adding border: none; to iframe CSS

This will prevent default borders from appearing in some browsers, ensuring a consistent, borderless PDF viewer.

}