Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

How can I render the plaintext first before the image in Blazor?

$
0
0

Originally, the plaintext and images were defined in a single data model class, but the issue is that it fetches everything before it renders on the client-side.

Therefore, I decided to separate the plaintext from the images, meaning I have two data models for the two instances of the data sets.

The concept is that I needed to improve the UX of my Blazor web app, where the plaintext should be rendered first before the images. But even if I implemented a separation for these two data sets, it still renders both at the same time.


Backend

data model class:

[Keyless]public class PlainTextModel{  [Required]  [Column("id")]  public string? ID { get; set; }  [Column("role")]  public string? Role { get; set; }  [Column("p_stat")]  public bool PStat { get; set; }  [Column("v_stat")]  public bool VStat { get; set; }  [Column("name")]  public string? Name { get; set; }  [Column("remarks")]  public string? Remarks { get; set; }  [Column("dt_registered")]  public string? DtRegistered { get; set; }  [Column("dt_modified")]  public string? DtModified { get; set; }  [Column("verified_by")]  public string? VerifiedBy { get; set; }}[Keyless]public class ImageModel{  [Column("img1")]  public byte[]? Image1 { get; set; }  [Column("img2")]  public byte[]? Image2 { get; set; }  [Column("img3")]  public byte[]? Image3 { get; set; }}

DBContext configurations:

using Microsoft.EntityFrameworkCore;namespace MyProject.Data.SQLServer{    public class SQLServerContext(DbContextOptions<SQLServerContext> options) : DbContext(options)    {        public DbSet<Models.SQLServer.PlainTextModel> PlainTextModel { get; set; } = default!;        public DbSet<Models.SQLServer.ImageModel> ImageModel { get; set; } = default!;        protected override void OnModelCreating(ModelBuilder modelBuilder)        {            modelBuilder.Entity<Models.SQLServer.PlainTextModel>()            .HasNoKey();            modelBuilder.Entity<Models.SQLServer.ImageModel>()            .HasNoKey().ToView(null);        }    }}

Method for fetching of plaintext data:

public async Task<PlainTextModel?> PlainTextAsync(string spName, Dictionary<string, object?> parameters){  var paramDefs = SQLServerInnerHelper.GlobalMethodSPParam();  SqlParameter[] sqlParameter = MinimalDbSettings.SPArrayOfTuplesAndDict(paramDefs, parameters);  var sqlParam = MinimalDbSettings.SQLParamLessDynamic(spName, sqlParameter);  var result = await _context.PlainTextModel      .FromSql(sqlParam)      .ToListAsync();  return result.FirstOrDefault();}

Method for fetching of images data:

public async Task<ImageModel?> ImageAsync(string spName, Dictionary<string, object?> parameters){  var paramDefs = SQLServerInnerHelper.GlobalMethodSPParam();  SqlParameter[] sqlParameter = MinimalDbSettings.SPArrayOfTuplesAndDict(paramDefs, parameters);  var sqlParam = MinimalDbSettings.SQLParamLessDynamic(spName, sqlParameter);  var result = await _context.ImageModel      .FromSql(sqlParam)      .ToListAsync();  return result.FirstOrDefault();}

Global method for parameter definition (for flexible parameter fetching from a Razor page):

public static Dictionary<string, object?> GlobalMethodRazorPageParam(  object? id = null,  object? key = null,  object? spOutput = null) // for OUTPUT parameter, but I am not using it at the moment.{  var pageParam = new Dictionary<string, object?>  {    ["id"] = id,    ["key"] = key,    ["sp_output"] = spOutput  };  return pageParam;}

Global method for parameter definition (for flexible SQL stored procedure parameters):

public static (string Name, SqlDbType Type, int? Size)[] GlobalMethodSPParam(){  var paramDefs = new (string Name, SqlDbType Type, int? Size)[]  {      ("id", SqlDbType.VarChar, 50),      ("key", SqlDbType.VarChar, 100),      ("sp_output", SqlDbType.NVarChar, 100),  };  return paramDefs;}

Global method for SqlParameter[] definition:

public static SqlParameter[] SPArrayOfTuplesAndDict((string Name, SqlDbType Type, int? Size)[] paramDefs, Dictionary<string, object?> parameters){  var paramUpdatedValues = parameters.Values.ToList();  return [.. paramDefs    .Select((def, i) =>    {      var param = def.Size is null      ? new SqlParameter(def.Name, def.Type)      : new SqlParameter(def.Name, def.Type, def.Size.Value);      if (def.Name == parameters.Keys.ToList()[i]) {        param.Value = paramUpdatedValues[i] ?? DBNull.Value;      } else {        throw new ArgumentException("Parameters misconfiguration found.");      }      return param;    })];}

Global method for FormattableString definition:

public static FormattableString SQLParamLessDynamic(string spName, SqlParameter[] sqlParameters){  return sqlParameters.Length switch  {    // 0 => $"EXEC {storedProcedure}", // this isn't allowed here.    1 => $"EXEC {spName} {sqlParameters[0]}",    2 => $"EXEC {spName} {sqlParameters[0]}, {sqlParameters[1]}",    3 => $"EXEC {spName} {sqlParameters[0]}, {sqlParameters[1]}, {sqlParameters[2]}",    _ => throw new ArgumentException("Too many parameters provided."),  };}

Backend/Frontend

Razor page:

@page "/users/review-user"@page "/users/review/{Id}/user"@rendermode InteractiveServer@using Microsoft.EntityFrameworkCore@using MyProject.Models.SQLServer@using MyProject.Data.SQLServer@implements IAsyncDisposable@inject IDbContextFactory<MyProject.Data.SQLServer.SQLServerContext> DbFactory@inject NavigationManager NavigationManager<PageTitle>Details</PageTitle><h3>Review User</h3><div><hr />  @if (plainTextModel is null)  {<div class="position-absolute top-50 start-50 translate-middle"><div class="spinner-grow text-danger spinner-grow-xxl" role="status"><span class="visually-hidden">Loading...</span></div></div>  }  else  {<div class="container-fluid overflow-x-auto mw-40"><div class="row py-1 border rounded border-secondary-subtle text-center my-1"><!-- Left side: user info --><div class="col-6 d-flex flex-column justify-content-center align-items-center"><dl class="row m-0"><dt class="col-sm-3 text-start p-0">#</dt><dd class="col-sm-9">@rowNum</dd><dt class="col-sm-3 text-start p-0">Role</dt><dd class="col-sm-9">@plainTextModel.Role</dd><dt class="col-sm-3 text-start p-0">Display Name</dt><dd class="col-sm-9">@plainTextModel.Name</dd><dt class="col-sm-3 text-start p-0">Remarks</dt><dd class="col-sm-9">@plainTextModel.Remarks</dd><dt class="col-sm-3 text-start p-0">Date Registered</dt><dd class="col-sm-9">@plainTextModel.DtRegistered</dd><dt class="col-sm-3 text-start p-0">Date Modified</dt><dd class="col-sm-9">@plainTextModel.DtModified</dd><dt class="col-sm-3 text-start p-0">Verified By</dt><dd class="col-sm-9">@plainTextModel.VerifiedBy</dd></dl></div><!-- Right side: actions --><div class="col-6 d-flex flex-column justify-content-center align-items-center gap-3 py-3">          @* other code here... *@</div></div>      @if (imageModel is null)      {<div class="position-absolute top-50 start-50 translate-middle"><div class="spinner-grow text-danger spinner-grow-xxl" role="status"><span class="visually-hidden">Loading...</span></div></div>      }      else      {<div class="container-fluid p-0"><div class="row gap-2"><div class="col"><div class="row py-1 border rounded border-secondary-subtle text-center my-1"><dl class="row d-flex justify-content-center gap-2"><dt class="col-sm-1 text-start">Image 1</dt><dd class="col-sm-10 m-0">                    @if (image1 is not null)                    {<a href="@image1" target="_blank"><img src="@image1" class="img-thumbnail my-3 p-0 w-50 h-auto" alt="Front ID" /></a>                    }                    else                    {<span class="text-muted fw-bold">-</span>                    }</dd></dl></div></div><div class="col"><div class="row py-1 border rounded border-secondary-subtle text-center my-1"><dl class="row d-flex justify-content-center gap-2"><dt class="col-sm-1 text-start">Image 2</dt><dd class="col-sm-10 m-0">                    @if (image2 is not null)                    {<a href="@image2" target="_blank"><img src="@image2" class="img-thumbnail my-3 p-0 w-50 h-auto" alt="Back ID" /></a>                    }                    else                    {<span class="text-muted fw-bold">-</span>                    }</dd></dl></div></div><div class="col"><div class="row py-1 border rounded border-secondary-subtle text-center my-1"><dl class="row d-flex justify-content-center gap-2"><dt class="col-sm-1 text-start">Image 3</dt><dd class="col-sm-10 m-0">                    @if (image3 is not null)                    {<a href="@image3" target="_blank"><img src="@image3" class="img-thumbnail my-3 p-0 w-50 h-auto" alt="Selfie" /></a>                    }                    else                    {<span class="text-muted fw-bold">-</span>                    }</dd></dl></div></div></div></div>      }</div>  }</div>@code {  private PlainTextModel? plainTextModel = new();  private ImageModel? imageModel = new();  private SQLServerContext context = default!;  [SupplyParameterFromQuery(Name = "row")]  private long rowNum { get; set; }  [Parameter]  public string? Id { get; set; }  private string? image1;  private string? image2;  private string? image3;  protected override async Task OnInitializedAsync()  {    context = DbFactory.CreateDbContext();    await LoadPlainText();    await LoadImages();  }  private async Task LoadPlainText()  {    var sQLServerHelper = new SQLServerHelper(context);    var spParamPlainText = SQLServerInnerHelper.GlobalMethodRazorPageParam(id: Id, key:"REVIEW_USER_PLAINTEXT");    plainTextModel = await sQLServerHelper.PlainTextAsync("myStoredProcedure", spParamPlainText);    // TODO: Let this load first.    if (plainTextModel is null)    {      NavigationManager.NavigateTo("notfound");    }  }  private async Task LoadImages()  {    var sQLServerHelper = new SQLServerHelper(context);    var spParamImage = SQLServerInnerHelper.GlobalMethodRazorPageParam(id: Id, key:"REVIEW_USER_IMAGES");    imageModel = await sQLServerHelper.ImageAsync("myStoredProcedure",    spParamImage);    if (imageModel is null)    {      NavigationManager.NavigateTo("notfound");    }    image1 = dbDataToImg(imageModel?.Image1);    image2 = dbDataToImg(imageModel?.Image2);    image3 = dbDataToImg(imageModel?.Image3);  }  private string? dbDataToImg(byte[]? imgBytes)  {    if (imgBytes is null || imgBytes.Length == 0)    {      return null;    }    else    {      return $"data:image/png;base64,{Convert.ToBase64String(imgBytes)}";    }  }  public async ValueTask DisposeAsync() // this is important  {    await context.DisposeAsync();  }}

I was expecting the plaintext to be rendered first before the images, but it wasn't.


Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>