Conditionally change CSS class in Razor view - c#

I need to change the CSS class of the <div> tag with the 'forumChild' class. It has to change every 3 loops of the foreach loop.
Is there a way to do this from within the control?
<div class="Forum">
<p>The Forum</p>
#foreach (var item in Model)
{
<div class="ForumChild">
<img src="#item.Blog.Image.img_path" alt="Not Found" />
<br />
#foreach (var comment in item.Blog.comment)
{
var db = new ACapture.Models.ACaptureDB();
var Name = from p in db.Profile.AsEnumerable()
where (p.AccountID == comment.AccountID)
select p;
<section>
<div>
<a href="#Url.Action("Index", "Home")">#foreach (var y in Name)
{ #(y.FirstName + " " + y.LastName + ":");
}</a>
</div>
<div>
#comment.Commentation
</div>
</section>
}
</div>
}
</div>
Thanks in advance

#{
int counter=0;
}
#foreach (var item in Model)
{
counter++;
<div class="#(counter<=3 ? "classRed":"classBlue")">
<img src="#item.Blog.Image.img_path" alt="Not Found" />
//other markup also here
</div>
if (counter == 6)
{
counter = 0;
}
}
Where classRed and classBlue are the CSS classes

How we handle this issue:
1) you need to create helper method that will return css class by some code.
string GetDivClass(int code)
{
var classes = new [] {"first", "second", "third"};
return classes[code];
}
2) create counter/index and increment it in the loop each time.
3) invoke helper method like GetDivClass(index % 3) at the div element.
PS
It is only POC, so don't use it in a real application (you need to add a validation logic and move 'classes' initialization to another place).

You can write any code you like into a Razor view, so to do what you're thinking of, you could do something like this (I left out most of the inner stuff):
#{
var className = "ForumChild";
}
<div>
#for (int i = 0; i < Model.Count; i++)
{
var item = Model[i];
if (i % 3 == 0)
className = GetNewClassName(); // Or whatever
<div class="#className">
</div>
}
</div>

You can add a counter variable to will start with 1 and increment in loop. Check with if statement is true by % and change the class name
#{ int counter = 1;}
#foreach (var item in Model)
{
if( (counter % 3) ==0 )
{
<div class="ChangedName">
}
else
{
<div class="ForumChild">
}
i++;

Related

How to fix this simple ElementNotFoundException in Blazor?

I am unit testing a blazor app. I get a ElementNotFoundException. I think the cause for this is an if statement in the the index.razor page. see code below:
<div class="row">
<div class="col-12">
#if ((challenges != null) && (challenges.Count > 0))
{
<MultiStepComponent Id="MultiStepContainer" Challenges="#challenges">
<div class="row p-3">
<div class="col-6" id="challengeContainer">
#foreach(var c in challenges)
{
<MultiStepNavigation Name="#c.Title">
<h1>#c.Title</h1>
<img class="float-left" src="#c.ImagePath" width="200" />
#foreach(var sentence in c.Description)
{
<p>#sentence</p>
}
</MultiStepNavigation>
}
</div>
<div class="col-6">
<textarea rows="26" cols="120" #bind="input" id="input"></textarea>
<button class="btn" id="runBtn" #onclick="RunAsync">Run</button>
<br />
<textarea rows="10" cols="120" id="output" readonly>#((MarkupString)Output)</textarea>
</div>
</div>
</MultiStepComponent>
}
</div>
</div>
The code behind of this page (index.razor.cs) has the following initialization code:
protected override async Task OnInitializedAsync()
{
jsonRepository = new JSONChallengeRepository();
challenges = await jsonRepository.GetChallengesAsync();
}
The test for this page is here:
[Test]
public async Task Compile_code_Success()
{
_codingChallengeService.Setup(c => c.SendInputToCompilerAsync("50+50")).ReturnsAsync("100");
_testContext.Services.AddScoped(x => _codingChallengeService.Object);
var razorComponent = _testContext.RenderComponent<Index>();
razorComponent.Instance.challenges = GetChallenges();
if ((razorComponent.Instance.challenges != null) && (razorComponent.Instance.challenges.Count > 0))
{
var runBtn = razorComponent.FindAll("button").FirstOrDefault(b => b.OuterHtml.Contains("Run"));
var input = razorComponent.Find("#input");
input.Change("50+50");
runBtn.Click();
var outputArea = razorComponent.Find("#output");
var outputAreaText = outputArea.TextContent;
Assert.AreEqual("100", outputAreaText);
}
Assert.IsNotNull(razorComponent.Instance.challenges);
}
The #input is missing..Why??
Thanks in advance!
I am guessing the problem is that you do not cause the component under test to re-render when you assign razorComponent.Instance.challenges property/field, and if the component does not re-render, then the markup inside #if ((challenges != null) && (challenges.Count > 0)) block in the component is not displayed.
In general, dont mutate properties (parameters) of components through the razorComponent.Instance. If you really have to do so, make sure to trigger a render after.
Instead, pass parameters to the component through the RenderComponent or SetParametersAndRender methods, or through services injected into components. That will cause the component to go through its normal render life-cycle methods.

Entity Framework and Table Relationship Error Out

I am new to Entity Framework and having a hard time figuring out what I am doing wrong.
Using ASP.Net MVC, C# and EF6 on a normal SQL database.
Here is my controller code.
using (var context = new MyEntities())
{
var result = context.Streamers.OrderBy(x => x.AddedDate);
foreach (var item in result)
{
var linkResult = context.Links.Where(x => x.StreamerId == item.Id);
item.Links = linkResult.ToList();
}
return View(result.ToList());
}
Here is my View
#{int i = 0;}
#foreach (var streamer in Model)
{
var className = i % 2 == 0 ? "col-lg-6 order-lg-2" : "col-lg-6";
var className2 = i % 2 == 0 ? "col-lg-6 order-lg-1" : "col-lg-6";
i++;
<section>
<div class="container">
<div class="row align-items-center">
<div class="#className">
<div class="p-5">
<a href="#streamer.StreamerUrl" target="_blank">
<img class="img-fluid rounded-circle" src="#streamer.StreamerImage" alt="#streamer.StreamerName">
</a>
</div>
</div>
<div class="#className2">
<div class="p-5">
<a href="#streamer.StreamerUrl" target="_blank">
<h2 class="display-4">#streamer.StreamerName</h2>
</a>
<p>#streamer.StreamerDescription</p>
<ul>
#foreach (var link in streamer.Links)
{
<li>#link.LinkName</li>
}
</ul>
</div>
</div>
</div>
</div>
</section>
}
The code is erroring out on the for each for streamer.Links
System.ObjectDisposedException: 'The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.'
Can anyone help me figure out what I am doing wrong here? Is there a much simpler way to be doing this?
Thanks in advance
Your DbContext is likely disposed. When for loop hits, Link is not attached to the context and cannot load the navigational property with the address. Load your link addresses when querying the links:
context.Links.Include(c => c.LinkAddress).Where(x => x.StreamerId == item.Id);
Try this if you don't want to change Html:
using (var context = new MyEntities())
{
result = context.Streamers.Include(c => c.Links)
.OrderBy(c=> c.AddedDate).ToList();
}
Try to use this code:
List<Streamer> result;
using (var context = new MyEntities())
{
result = context.Streamers.OrderBy(x => x.AddedDate).ToList();
foreach (var item in result)
{
item.Links = = context.Links.Where(x => x.StreamerId == item.Id).ToList();
}
}
return View(result);
but since you are not filtering streamers you can try this:
using (var context = new MyEntities())
{
result = context.Streamers.Include("Links").OrderBy(x => x.AddedDate).ToList();
}

How can I create a row for every 3rd column in Razor mvc5?

I am currently trying to add a new row for each 3rd column with razor. However, with the current code, only the first three columns get wrapped in a row, and the rest get skipped. I have been looking around for a fix, but none of it seems to work with my code. Does anyone have a solution for this?
#model IEnumerable<Byporten.createpost>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_LayoutClient.cshtml";
}
<div class="container">
#{
var itemCount = 0;
}
#while (itemCount < 3)
{
foreach (var item in Model.Reverse().Take(9))
{
if(itemCount == 0 )
{
#:<div class="row">
}
<div class="col-lg-4 col-md-6 col-sm-6">
<div class="image-section">
<img src="~/images/uploads/#Html.DisplayFor(modelItem => item.ImageURL)"/>
</div>
<div class="title-section">
<h5><span class="fa fa-pencil"></span> #Html.DisplayFor(modelItem => item.Title)</h5>
#Html.ActionLink("Les mer", "viewArticle", new { id = item.Id })
</div>
</div>
itemCount++;
if ((itemCount % 3) == 0)
{
#:</div>
}
}
}
#{itemCount = 0;}
</div>
None of these worked for me, but the following did:
#foreach (var item in Model.Items)
{
var itemCount = 0;
foreach (var listItem in ((ListViewModel)item).ListItemViewModel.Items)
{
if (itemCount == 0)
{
#:<div class="row">
}
<div class="col-md-4">
<span class="organogram-outter-ring"></span>#listItem.Fields.Title
<div style="display:none;" class="sf-list-content">
#Html.Raw(listItem.Fields.Content)
</div>
<div class="organogram-outter-ring"></div>
</div>
if (itemCount == 2)
{
itemCount = 0;
#:</div>
}
else
{
itemCount++;
}
}
}
It's going to result in invalid markup because itemCount == 0 will be true only once. Replace if (itemCount == 0) with if (itemCount % 3 == 0 || itemCount % 3 == 3).
I would also get rid of the while loop and the itemCount reset at the bottom.
Use Html.Raw() method to avoid compilation problems with conditional closing tag, and temp variable insertRow to avoid repeating in row condition:
<div class="container">
#{
var itemCount = 0;
}
#{
foreach (var item in Model.Reverse().Take(9))
{
var insertRow = itemCount % 3 == 0;
if(insertRow)
{
#Html.Raw("<div class="row">")
}
<div class="col-lg-4 col-md-6 col-sm-6">
<div class="image-section">
<img src="~/images/uploads/#Html.DisplayFor(modelItem => item.ImageURL)"/>
</div>
<div class="title-section">
<h5><span class="fa fa-pencil"></span> #Html.DisplayFor(modelItem => item.Title)</h5>
#Html.ActionLink("Les mer", "viewArticle", new { id = item.Id })
</div>
</div>
if (insertRow)
{
#Html.Raw("</div>")
}
itemCount++;
}
}
</div>
And also while (itemCount < 3) loop is look strange and unnecessary for your task.
So, I know I am a little late to the game and there is an accepted answer, however, I want to add my rendition because it requires no duplicate if statements and no code compilation squigglies.
My approach uses an inner for loop based on the number of columns you want to have before creating a new row:
<table>
<thead>
<tr>
<td><b>My List Data:</b></td>
</tr>
</thead>
<tbody>
#{
var items = Model.MyList;
const int colCount = 2;
}
#for (var i = 0; i < items.Count(); i += colCount)
{
<tr>
#for (var c = 0; c < colCount && i + c < items.Count(); c++)
{
<td>#(items[i + c].Display):</td>
}
</tr>
}
</tbody>
</table>
The premise is to determine what your column count is, that is show above using const int colCount =2;
Then, loop, using a for loop, on your list but instead of incrementing by 1, as is traditional, increment by your colCount value.
Then, have your row tag. This means a row will be created every n+colCount items.
Within that row tag, have another for loop that increments by 1 until you either reach your colCount OR your parent iterator plus your colCount iterator equals or exceeds the total items in your list.
Within that for loop, simply create a cell that is at the index of i (outer iterator) + c (colCount) iterator.
This gives you a nice left to right, top to bottom table structure from a flat list without extra if statements and compilation warnings.

Filling Data For Partial View MVC

We're developing news website we're confused with some concept of usage. I'd like to ask and know better if possible. We've a homepage which may contain a lot of models at once so we're separating our homepage to partial views and we're planning to feed them with the appropriate models.
In one partial we're enumerating in categories that are not marked as deleted and we've two types of categories. One of them displays the latest post and the other displays 4 posts at once. We've achieved this actually but as i've mentioned we would like to know if there is a better way or if we're doing anything wrong because right now we're keeping the connection to the context open until the partial is rendered.
Here is the code for views
Partial View Code (CategoryRepeater.cshtml)
#using SosyalGundem.WebUI.DatabaseContext;
#{
var categoryList = new List<PostCategories>();
var db = new SosyalGundemDb();
categoryList = db.PostCategories.Include("Posts").Where(x => !x.IsDeleted).ToList();
}
#for (int i = 0; i < categoryList.Count; i++)
{
if (i % 3 == 0 || i == 0)
{
#Html.Raw("<div class=\"row-fluid spacer\">")
}
var category = categoryList[i];
if (category.PostCategoryType == 1)
{
<div class="span4">
<h3 class="title"><span>#category.PostCategoryName</span></h3>
#{
var article = category.Posts.FirstOrDefault();
if (article != null)
{
<article class="post">
<div class="entry clearfix">
<div class="span6">
<a href="#" title="Permalink to Suspen disse auctor dapibus neque pulvinar urna leo" rel="bookmark">
<img width="225" height="136" src="#Url.Content("~/Content/uploadedimages/" + article.Media.ToList()[0].MediaContent )" alt="shutterstock_70184773" />
</a>
</div>
<div class="span6">
<h4 class="smallnewstitle">#article.PostTitle</h4>
<p>#(article.PostSummary.Length > 100 ? article.PostSummary.Substring(0, 100) : article.PostSummary)</p>
<div class="meta">
<span class="date">#article.PostDate.ToString("MMMM dd, yyyy")</span>
</div>
</div>
</div>
</article>
}
}
</div>
}
else
{
<div class="video-box widget span4">
<h3 class="title"><span>#category.PostCategoryName</span></h3>
#{
int cati = 0;
var firstPost = category.Posts.OrderByDescending(x => x.PostDate).FirstOrDefault();
}
#if (firstPost != null)
{
<h4 class="smallnewstitle">#firstPost.PostTitle</h4>
<p>#(firstPost.PostSummary.Length > 100 ? firstPost.PostSummary.Substring(0, 100) : firstPost.PostSummary) </p>
<ul>
#foreach (var item in category.Posts.OrderByDescending(x => x.PostDate))
{
if (cati <= 3)
{
<li>
<a href="#" title="#item.PostTitle" rel="bookmark">
<img width="225" height="136" src="#Url.Content("~/Content/images/dummy/shutterstock_134257640-225x136.jpg")" alt="shutterstock_134257640" />
</a>
</li>
}
else
{
break;
}
cati++;
}
</ul>
}
</div>
}
if (i % 3 == 0 && i != 0)
{
#Html.Raw("</div>")
}
}
#{
db.Dispose();
}
Separate your concerns. You can see this project for start: http://www.codeproject.com/Tips/617361/Partial-View-in-ASP-NET-MVC
Controller
#using SosyalGundem.WebUI.DatabaseContext;
public ActionResult SomeAction()
{
var model = new CategoriesModel
{
NotDeletedCategories = db.PostCategories.Include("Posts").Where(x => !x.IsDeleted).ToList(),
DeletedCategories = db.PostCategories.Include("Posts").Where(x => x.IsDeleted).ToList()
};
return View(model);
}
Model
public class CategoriesModel
{
public List<PostCategories> NotDeletedCategories {get;set;}
public List<PostCategories> DeletedCategories {get;set;}
};
View
#model CategoriesModel
#Html.RenderPartial("DeletedCategories", Model.DeletedCategories)
#Html.RenderPartial("NotDeletedCategories", Model.NotDeletedCategories)
Hi Jinava,
I would suggest bind Model to the View,
Like,
public ActionResult CategoryRepeater()
{
var multiViewModel = new MultiViewModelModel
{
ModelForParialView1= new XYZ(),
ModelForParialView2= new PQR()
};
return View(model);
}
For the View
#model MultiViewModelModel
And then PAss the views with the MultiViewModelModel.ModelForParialView1 and MultiViewModelModel.ModelForParialView2
You can perform all the model operations on the view.
And at the controller level perform all the database operations and release the database connection there itself no need to get that on the view.
Hope this explanation helps you.

Umbraco pagination

First time Umbraco user.
I'm looking to add pagination to the following basic loop:
#foreach (var example in CurrentPage.Children.OrderBy("createDate descending").Take(8)){
//Do Stuff//
}
Any ideas? Thanks
After a good amount of work and research, here is my final code for pagination in umbraco. Replace the examples with your stuff, and pageSize is the amount of posts shown on each page.
#{
var pageSize = 8;
if(Model.Content.HasValue("numberOfItemsPerPage")){
pageSize = Model.Content.GetPropertyValue<int>("numberOfItemsPerPage");}
var page = 1; int.TryParse(Request.QueryString["page"], out page);
var items = Umbraco.TypedContent(Model.Content.Id).Children.Where(x => x.DocumentTypeAlias == "exampleAlias" && x.IsVisible());
var totalPages = (int)Math.Ceiling((double)items.Count() / (double)pageSize);
if (page > totalPages)
{
page = totalPages;
}
else if (page < 1)
{
page = 1;
}
foreach (var item in items.Skip((page - 1) * pageSize).Take(pageSize).OrderBy("createDate descending"))
{
<div class="example-div">
<h2>#item.GetPropertyValue("example")</h2>
</div>
}
if (totalPages > 1)
{
<div class="pagination">
<ul>
#if (page > 1)
{
<li>Prev</li>
}
#for (int p = 1; p < totalPages + 1; p++)
{
<li class="#(p == page ? "active" : string.Empty)">
#p
</li>
}
#if (page < totalPages)
{
<li>Next</li>
}
</ul>
</div>
}
}
Hope this stops a headache for someone.
Phil's answer is great, but I would recommend putting the order on the items variable rather than the foreach - that way if any more complicated sorting is necessary it's being done before the pagination is implemented.
The updated code snippets would be:
#{
var pageSize = 8;
if(Model.Content.HasValue("numberOfItemsPerPage")){
pageSize = Model.Content.GetPropertyValue<int>("numberOfItemsPerPage");}
var page = 1; int.TryParse(Request.QueryString["page"], out page);
var items = Umbraco.TypedContent(Model.Content.Id).Children.Where(x => x.DocumentTypeAlias == "exampleAlias" && x.IsVisible()).OrderByDescending(x => x.CreateDate);
var totalPages = (int)Math.Ceiling((double)items.Count() / (double)pageSize);
if (page > totalPages)
{
page = totalPages;
}
else if (page < 1)
{
page = 1;
}
foreach (var item in items.Skip((page - 1) * pageSize).Take(pageSize)
{
<div class="example-div">
<h2>#item.GetPropertyValue("example")</h2>
</div>
}
if (totalPages > 1)
{
<div class="pagination">
<ul>
#if (page > 1)
{
<li>Prev</li>
}
#for (int p = 1; p < totalPages + 1; p++)
{
<li class="#(p == page ? "active" : string.Empty)">
#p
</li>
}
#if (page < totalPages)
{
<li>Next</li>
}
</ul>
</div>
}
}
My 50 cents
Jeroen Breuer created a github project called Hybrid Framework in which he has added some route hijacking to an umbraco side to do paging and have strongly typed models. Take a look at it and i'm sure you will like it. It also uses caching i believe.
There was also a video about this i saw but i could not find it anymore.
Hope this helps people trying to implement Paging and some other nice stuff to you Umbraco projects.
UPDATE: found the video on GitHub in readme
These are all great answers, especially the pointer to Jeroen Breuer's library, but just in the name of being thorough and talking about all options -- if you are using jquery in your project and if you have relatively small result sets you could also go with a simple front end only solution.
You'd just bind the entire results list and then use a library like JPList (http://jplist.com ) as I have done here. Go to http://www.charterpublic.org/find-a-school/ and type in city Denver for example. You'll see there are 50+ results. I bind the entire results list then use jplist to make it sortable/pageable etc.
#if (results.Any())
{
<div class="list">
#foreach (var result in results.OrderByDescending(r => r.Name))
{
<div class="list-item">
//build your item
</div>
}
</div>
}
<div class="jplist-panel">
<!-- bootstrap pagination control -->
<ul class="pagination text-center jplist-pagination"
data-control-type="boot-pagination"
data-control-name="paging"
data-control-action="paging"
data-range="4"
data-mode="google-like"></ul>
<!-- items per page dropdown -->
<div class="hidden dropdown pull-left jplist-items-per-page"
data-control-type="boot-items-per-page-dropdown"
data-control-name="paging"
data-control-action="paging">
<button class="btn btn-primary dropdown-toggle"
type="button"
data-toggle="dropdown"
id="dropdown-menu-1"
aria-expanded="true">
<span data-type="selected-text">Items per Page</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdown-menu-1">
<li role="presentation">
<a role="menuitem" tabindex="-1" href="#" data-number="3">3 per page</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="#" data-number="5">5 per page</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="#" data-number="10" data-default="true">10 per page</a>
</li>
<li role="presentation" class="divider"></li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="#" data-number="all">View All</a>
</li>
</ul>
</div>
</div>
Then at the bottom of your view...
<script type="text/javascript">
$(document).ready(function () {
$('#demo').jplist({
itemsBox: '.list',
itemPath: '.list-item',
panelPath: '.jplist-panel'
});
});
</script>
There are other front end libraries that do this, but I found JPList the easiest to use for me.
The downside is it's not lazy loaded so it's a little heavier, but with smallish lists like mine here this was a great and simple solution.
I know that this is old , I used the Phil code recomendations and works very good.
But all the pages when incresing the pagination buttons works as infinite regeneration, what I mean is how can I do this as example:
Prev 123456789...Next and when is selected the page 5 for example shows like this:
Prev 5 6 7 8 9 10 11 12 13 ... Next and in the inverse or last page like this:
Prev ... 47 48 49 50 51 52 53 54 55
What I mean guys is to have just a 9 pages on click in the pagination buttons, but I need to implement with the same code that Phil Share :
#{
var pageSize = 8;
if(Model.Content.HasValue("numberOfItemsPerPage")){
pageSize = Model.Content.GetPropertyValue<int>("numberOfItemsPerPage");}
var page = 1; int.TryParse(Request.QueryString["page"], out page);
var items = Umbraco.TypedContent(Model.Content.Id).Children.Where(x => x.DocumentTypeAlias == "exampleAlias" && x.IsVisible());
var totalPages = (int)Math.Ceiling((double)items.Count() / (double)pageSize);
if (page > totalPages)
{
page = totalPages;
}
else if (page < 1)
{
page = 1;
}
foreach (var item in items.Skip((page - 1) * pageSize).Take(pageSize).OrderBy("createDate descending"))
{
<div class="example-div">
<h2>#item.GetPropertyValue("example")</h2>
</div>
}
if (totalPages > 1)
{
<div class="pagination">
<ul>
#if (page > 1)
{
<li>Prev</li>
}
#for (int p = 1; p < totalPages + 1; p++)
{
<li class="#(p == page ? "active" : string.Empty)">
#p
</li>
}
#if (page < totalPages)
{
<li>Next</li>
}
</ul>
</div>
}
}
Just to have a limit of 9 pages with the (...) according the page position.
Help!

Categories