Convert static html page to Blazor Page - c#

I have build a static website, a long time ago, with Nicepage.
But i want to convert this project into a Blazor project, so i can use some C# code.
To achieve this, i copy/paste the code of a html page, into a razor file, except the script tags (i put them into index.html).
The issue is that elements are not well render.
For example, i have an image that i want to be visible only on desktop, and not on mobile. After i switch the project on Blazor, the image is not visible on desktop and mobile. I saw that nicepage as a global css file, and a specific css file for the html page. So i add them into the razor page
<link rel="stylesheet" href="nicepage.css" media="screen"> <link rel="stylesheet" href="home.css" media="screen">
But nothing happened.
So i would like to know if anyone has managed to create html page with Nicepage, and then use it in a Blazor project?
Thank you.

Blazor can be evil :). It works best with CSS (switching classes according to that field etc.) in my opinion. So if you want to display something on desktop do:
1. code in CSS like
#media (max-width: 992px){
.nameOfClass {
display:none;
}
}
2. Javascript:
Do simple model, inject IJSRuntime, invoke it, create function and use it as property in html part
Model -
public class WindowDimension
{
public int Height { get; set; }
public int Width { get; set; }
}
Inject IJSR -
#inject IJSRuntime JS at top of .razor page
Invoke e.g. in OnInitialize also be aware of naming. I had some issues when I had it like HeightOfWindow etc.
#code{
int Height { get; set; }
int Width { get; set; }
protected override async Task OnInitializedAsync()
{
var dimension = await JS.InvokeAsync<WindowDimension>("getWindowDimensions");
Height = dimension.Height;
Width = dimension.Width;
}
}
Create function in JS (can be only code in some JS file + do not forget to put in index file.
window.getWindowDimensions = function () {
return {
width: window.outerWidth,
height: window.outerHeight
};
};
HTML
<div style:"width: #Height">.....</div>

Related

Blazor RenderFragment to String

I'm developing a code block component using .Net 6 Blazor wasm. I need to display the RenderFragment as string and also render the component in my html.
Here is my code block component,
<pre class="language-html">
<code class="language-html">
#("Some way to get non rendered html from #ChildContent")
</code>
</pre>
#ChildContent
#code
{
[Parameter]
public RenderFragment ChildContent { get; set; }
}
I'm using the above component as,
<CodeBlock>
<Chat></Chat>
</CodeBlock>
Expected Output:
<Chat></Chat>
<!-- This is the input I passed inside as RenderFragment and I need the exact Render Fragement Code;
not the Rendered Html code of the RenderFragment -->
Component gets rendered as expected. But unable to get non rendered html of my RenderFragment
One option is to pass the RenderFragment content as string parameter to CodeBlock component. But this results in duplicate and non readable HTML. Also this becomes difficult to maintain when the ChildContent has multiple lines of code.
<CodeBlock Html="#("<Chat></Chat>")">
<Chat></Chat>
</CodeBlock>
Any hints/suggestions on how to achieve this?
This is kind of a tough question. From what I understand you want to be able to render the ChildContent of your component but also be able to view the ChildContent data as plaintext razor code, or HTML if that's what's in your ChildContent, right?
So an option would be to surround your #ChildContent renderer tag with a <div> and assign that div a unique id when the parent component is initialized. Then you create another variable, let's call it private string RawContent { get; set; }. Then write a javascript function that takes an id value and gets the element by id from the DOM and returns the element's innerHTML.
I created a test project to try it and it works. Here are the snippets that are relevant.
In your Component.razor file:
#inject IJSRuntime JS
<pre class="language-html">
<code class="language-html">
#RawContent
</code>
</pre>
<div id="#ElementId">
#ChildContent
</div>
#code
{
[Parameter]
public RenderFragment ChildContent { get; set; }
private ElementReference DivItem { get; set; }
private string RawContent { get; set; }
private Guid ElementId { get; set; } = Guid.NewGuid();
protected async override Task OnInitializedAsync()
{
base.OnInitializedAsync();
RawContent = await JS.InvokeAsync<string>("GetElementHtmlText", ElementId.ToString());
}
}
Then in your index.html file add this in side of a <script> tag, or to one of your javascript files:
async function GetElementHtmlText(elementID) {
await setTimeout(() => { }, 1);
console.log(elementID);
var element = document.getElementById(elementID);
console.log(element);
var result = element.innerHTML;
console.log(result);
return result;
}
Then anywhere you wish to use this component you will render the HTML markup and have the Raw Text available as well. However this function will return all of the html markup raw text, meaning that you get the razor tags and the empty comment elements that Blazor inserts as well (ie. <!--!-->). But as long as you know that you can work around them.
I didn't do this but you could modify this to call the JSInterop function inside the RawContent's getter instead of just when the component initializes.

Bind a List of object using Razor page

I have razor pages .
I have prepared in a handler a list of(visitorTypes)
I only want to bind them . there is something that i have missed , but i dont know what
Here is my c# code
[ModelBinder(Name ="Visitors")]
public ICollection<VisitorType> VisitorTypes { get; set; }
public IActionResult OnGetListOfVisitorTypeAsync()
{
VisitorTypes = _db.VisitorTypes.ToList();
return RedirectToPagePermanent("/Visitors",VisitorTypes);
}
And here is my razor page
<div class="container">
<form method="get" asp-page-handler="ListOfVisitorType" >
#foreach (var item in Model.VisitorTypes)
{
<label>#item.VisitorTypeName.ToString() </label>
}
</form>
</div>
can someone please explain what im doing wrong
(I have tried to return the list , i have tried to make it a void method , but none of them works with me )
Here Is The modal
private string _VisitorTypeName { get; set; }
public string VisitorTypeName { get {return _VisitorTypeName; } set { _VisitorTypeName = value; } }
ICollection<Visitor> Visitors { get; set; }
What if you generate your data when your View get loaded, something like this:
public IActionResult Visitors()
{
VisitorTypes = _db.VisitorTypes.ToList();
return View(VisitorTypes);
}
You may have passed wrong model with "#model ?" in razor page.
This is pretty Simple
First you need to know how actually MVC works and what it's:
MVC is a architectural pattern , we keep all things loosely coupled in terms of MODEL, View and Controller
So it's doesn't means that cannot write code directly in "Razor View",
For example how we write JavaScript directly in HTML or View. for decoupling purpose we create .JS file to separate script code from View(HTML).
Now comes to actual work
First before accessing List(VisitorTypes) it must be declare and initialize with value in the razorview itself
#{
List<VisitorTypes> listVisitorTypes = _db.VisitorTypes.ToList();
}
And finally render the list:
#foreach (var item in listVisitorTypes )
{
#item.VisitorTypeName.ToString()
}

Get the same display using an ActionLink inside Html.BeginForm and simple <a> tag

In my ASP.NET MVC 5 website I have a menu with two types of files: actual pages returned from the controllers and pdf files that you can view in the navigator. Since my menu is created dynamically (it varies according to Active Directory rights) I have to distinguish which type is which (Document or Page), and this means that according to the file type you click, it will not result in the same action.
To show you, imagine there is a List<DocumentModel> documents and the following to treat the information:
<ul>
#foreach (var document in documents)
{
<li>
#if (document.type.Equals("Document"))
{
using (Html.BeginForm("DisplayPDF", "Navigation", new { pdfName = document.link }, FormMethod.Post))
{
#Html.ActionLink(document.docName, "DisplayPDF", null, new {id="linkStyle", #class = "saveButton", onclick = "return false;" })
}
}
else
{
//This link is different then the one above visually
<span class="glyphicon glyphicon-file"></span>#document.docName
}
</li>
</ul>
<!--This script allows to submit the form, and treat the action of DisplayPDF-->
<script>
$(document).ready(function () {
$('.saveButton').click(function () {
$(this).closest('form')[0].submit();
});
});
</script>
DocumentModel is as follows:
public class DocumentModel
{
public long idDocument { get; set; }
public long idCategory { get; set; }
public string docName { get; set; }
public string link { get; set; }
public string type { get; set; }
}
Finally my DisplayPDF method is the following:
public FileContentResult DisplayPDF(string pdfName)
{
var fullPathToFile = #"Your\Path\Here" + pdfName;
var mimeType = "application/pdf";
var fileContents = System.IO.File.ReadAllBytes(fullPathToFile);
return new FileContentResult(fileContents, mimeType);
}
Now as you can see in the Razor view I displayed, there are two types of clickable links. One is only a controller redirection, whereas the second calls the DisplayPDF method and then returns a PDF page. The problem I'm having is that these links are displayed differently, and I don't know how to have the same display for both.
To synthesize my question : how to display the same using #Html.ActionLink() and 'a' tag, knowing that currently, the 'a' tag has the proper display?
Update I modified some code as to give IDs to <a> tag and #Html.ActionLink, then I added this css in stylesheet:
#linkStyle {
margin-left: 25px;
color: antiquewhite;
}
But I still have a different display
UPDATE 2 I think that the problem of display come from the BeginForm method, any ideas to fix this?

Is there a better way to convert a WebControl that uses nested ITemplates to be used in Razor?

I'm converting old aspx/ascx pages to now use Razor and I've run into a WebControl that can't easily become a helper method or cshtml.
The WebControl has several nested ITemplate properties like this:
[ToolboxData("<{0}:LightBox runat=server></{0}:LightBox>")]
public class Lightbox : WebControl, INamingContainer
{
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Header { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Body { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Footer { get; set; }
}
This is how it is formatted in the aspx/ascx file:
<cc1:Lightbox ID="LightBox1" runat="server">
<Header>Header HTML</Header>
<Body>Body HTML</Body>
<Footer>Footer HTML</Footer>
</cc1:Lightbox>
If a section exists, then the CreateChildControls() method wraps it in a div tag with certain classes. It ends up like this, but more complicated:
<div class="header">
<div class="title">Header HTML</div>
</div>
<div class="body">Body HTML</div>
<div class="footer">Footer HTML</div>
I don't know of a good way to do something like this in Razor. I could turn it into one or more helper methods. However, this means I either need pass HTML as strings or convert each ITemplate section to this "fun" format:
Func<dynamic, object> header = #<text>
<span id="logo">
<img src="#path" />
</span>
</text>;
...
#LightBox(header, body, footer) // This would contain logic from CreateChildControls
Is this the best that is possible with Razor?
The only other thing I can think of is placing the HTML as is on the page and using a JavaScript module to then modify the inner sections with new container divs, but I don't see why this work can't stay on the server side.
The best approach for you is using jQuery. In jquery you could use something like $( "p" ).addClass( "myClass yourClass" );.
If there is "p", it will add related class on that, if not, nothing will happen.
Another option is replacing other controls with lightbox, like bootstrap modal.

C# MVC: Generic / Reusable Pager (for different Grids in different Pages)

Is it possible to create a "generic" pager (ASCX UserControl) which can be used with different grids on different pages to control paging? So that I only need to render it using RenderPartial.
I'm currently working on a "Contacts" grid, which needs paging functionality, but I will have to reuse paging later, so I wondered if I can make this a shared partial control.
One issue I can think of right now though: How do I control the AJAX link when clicking on any of the pager numbers, as that needs to be different if it is another grid?
You could create a PagerViewModel object, with the following properties:
public PagerViewModel
{
public string Controller { get; set; }
public int StartPage { get; set; }
public int EndPage { get; set; }
}
And create a Pager.ascx partial view as follows:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<PagerViewModel>" %>
<% for(int i = Model.StartPage; i <= Model.EndPage; i++) { %>
<%= i %>
<% } %>
I think you can figure out how to use it ;-)
Look at MVCContrib: http://mvccontrib.codeplex.com/Wiki/View.aspx?title=Documentation
Here is example: http://www.c-sharpcorner.com/Blogs/BlogDetail.aspx?BlogId=875 of using generic Pager.

Categories

Resources