specifying two models/arrays in a for each loop? - umbraco

I know a for each loop focuses on one array usually, however I'm new to Umbraco and I'm wondering if this is possible?
My code is as follows:
<div>
<div class="row">
#foreach (var feature in homePage.CSSHomepages.Where("featuredPage"))
{
<div class="3u">
<!-- Feature -->
<section class="is-feature">
<img src="#feature.Image" alt="" />
<h3>#feature.Name</h3>
#Umbraco.Truncate(feature.BodyText, 100)
</section>
<!-- /Feature -->
</div>
}
</div>
</div>
This currently displays one featured page, however I'm trying to also display a featured page from "HTMLHomepages", too.
I've tried the following code to no avail:
<div>
<div class="row">
#foreach (var feature in homePage.CSSHomepages.Where("featuredPage") & homePage.HTMLHomepages.Where("featuredPage"))
{
<div class="3u">
<!-- Feature -->
<section class="is-feature">
<img src="#feature.Image" alt="" />
<h3>#feature.Name</h3>
#Umbraco.Truncate(feature.BodyText, 100)
</section>
<!-- /Feature -->
</div>
}
</div>
</div>
But as I expected, I get runtime errors. Any suggestions?

The runtime error you receive is not umbraco related.
You have a single &-sign. This does not exists in the razor language.
You should at least use && which means AND.
However in this case you don't want to use and AND operator, but an OR operator: ||. This all would be true if you are checking something in an if statement.
Here you are looping through an array. That means that you need to concatenate the two arrarys before looping through them. Normally you get two IEnumerable's from the Umbraco API. To join two IEnumerables together you could use the Concat (see MSDN) function.
What I would do:
#{
var featureList = homePage.CSSHomepages.Where("featuredPage").Concat(homePage.HTMLHomepages.Where("featuredPage"))
}
<div class="row">
#foreach( var feature in featureList) {
// your existing code
}
</div>

Related

Umbraco, displaying images from the media picker in child nodes

I have a products view which should display some products. The ProductItem is a child node of Products and has a property of productImage, which is a media picker. I have two ProductItem and have assigned one image each in the media picker, but I'm having trouble rendering them on the site.
#inherits Umbraco.Web.Mvc.UmbracoViewPage<ContentModels.Products>
#using ContentModels = Umbraco.Web.PublishedModels;
#{
Layout = "Master.cshtml";
var products = Umbraco.Content(Guid.Parse("2740e0b9-caf3-435a-89c5-982ed890e6bd"))
.ChildrenOfType("ProductItem")
.Where(x => x.IsVisible())
.OrderByDescending(x => x.CreateDate);
}
#foreach (var product in products)
{
<section class="page-section">
<div class="container">
<div class="product-item">
<div class="product-item-title d-flex">
<div class="bg-faded p-5 d-flex ml-auto rounded">
<h2 class="section-heading mb-0">
<span class="section-heading-upper">#product.Value("productSubtitle")</span>
<span class="section-heading-lower">#product.Value("productTitle")</span>
</h2>
</div>
</div>
<img class="product-item-img mx-auto d-flex rounded img-fluid mb-3 mb-lg-0" src="" alt="">
<div class="product-item-description d-flex mr-auto">
<div class="bg-faded p-5 rounded">
<p class="mb-0">#product.Value("productContent")</p>
</div>
</div>
</div>
</div>
</section>
}
I can display the other information with no issue. I've read dozens of forum threads and documentation but I can't seem to figure out a simple solution for just displaying each products image inside of my foreach loop. I'm using the latest version of Umbraco.
ProductItem:
Assigned image:
It looks like you forget to render it in your view. The "src"attribute is empty - see attached screenshot.
Feel free to check out the Umbraco doc on how to render an image from the Media Picker at here

How to change Row after every N iteration in Thymeleaf?

My problem is with using thymeleaf iteration and if-else condition together.
Suppose i have 100 products in my mysql database i want to show them on a webpage using cards and there are only 4 cards in a row(I am able to print them in a row), but i want to change the row after every 4 iteration(0-3),so that new four cards will be shown in next row.
My thymeleaf Template Page:-
<div class="container" >
<div class="row">
<div class="col-xl-3" th:each="products : ${ListOfProducts}">
<div class="card" style="width: 15rem;">
<img class="card-img-top" src="..." alt="Card image cap">
<div class="card-body">
<p class="card-title" th:text = "${products.productName}"></p>
<hr>
<p class="card-text" th:text = "${products.productCost}"></p>
AddToCard
</div>
</div>
</div>
</div>
I know we can do it using loops and if-condition but i am new to thymeleaf syntax, so please help me to get out of this rid.
Thanks in advance,Your words are value for me.

Setting Data-Parent and HREF dynamically in a for-loop

Previously to create Accordion controls I used to use this piece of code:
<div class="panel-group" id="accordionMessagesSetup">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordionMessagesSetup" href="#collapseMessagesSetup">
<span class="glyphicon glyphicon-chevron-up"></span>
Message Setup
</a>
</h4>
</div>
<div id="collapseMessagesSetup" class="panel-collapse collapse in">
<div>
<p style="background-color: red"> Someting ELSE in here</p>
<p style="background-color: red"> Someting ELSE2 in here</p>
</div>
</div>
</div>
</div>
or as seen here: Bootplay Live Demo
Now I still want to use my example but in this page I have a for-each loop so I need to create these at run-time.
The items I need to put variables there in order for this to work are
id="accordionMessagesSetup"
data-parent="#accordionMessagesSetup"
href="#collapseMessagesSetup"
id="collapseMessagesSetup"
How can I initialize those in a for-each loop a mode using Razor?
Imagine you have whatever property you like to do it in the model.
The biggest issue you are/will likely run into is Razor parsing. When you try to use a Razor variable in the middle of some bit of text, often Razor cannot determine where the variable name ends. For example, if you were to do something like:
<div id="accordion#Model.IdMessageSetup">
Razor thinks it needs to look for a property on the model named IdMessageSetup, when actually, you just wanted Id. The easiest way to fix this is to wrap the variable in paranthesis:
<div id="accordion#(Model.Id)MessageSetup">
Now, it's clear which part is the variable. As far as adding the # sign goes, I'm not really sure what the confusion is there. You just put it where it needs to go:
<a href="#collapse#(Model.Id)MessagesSetup">
Nothing special required.

ASP.NET MVC site that works for mobile and non-mobile sites?

I am working on a website, using ASP.NET MVC3 with .aspx pages. The web site supports desktop browsers and mobile phones with the same site. The site has a single master page. I want to avoid redirecting to a mobile site, because that would duplicate a lot of html. I still intend to use the user-agent to determine when a mobile device is hitting the site, but instead of redirecting the browser, I set a flag that I use in the master page to control what HTML is generated.
I have run into trouble determining the best way to get the master page to generate the HTML I want. I have two strategies in mind to solve this problem, but I don’t know if this is the best way.
The first strategy is, to use the mobile flag to add, replace, or remove HTML content that is mobile specific.
Pro: Minimize duplication of HTML
Con: Multiple if statements.
Requires a second mobile specific .css to be downloaded. (Because the html has multiple if statements, we really need 2 css files, one for mobile and one for none mobile. We can't easily use specificity rules to deal with this in one css file).
Here is an excerpt from the master page using this strategy:
<% if (isMobile)
{
Html.RenderPartial("MobileSearchControls");
}
else
{ %>
<div id="viewTabs" class="span3">
...
</div>
<% }
%>
<%--body --%>
<div id="bd" class="row-fluid">
<% if (!isMobile)
{ %>
<div id="left-column" class="span3">
<div id='controls-and-preferences'>
<asp:ContentPlaceHolder ID="LeftColumnContent" runat="server" />
</div>
</div><!--left-column -->
<% }
%>
<div id="main" class="span9">
<div id="search-results">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
</div>
<% if (!isMobile)
{ %>
<div class="span2" id='right-column'>
</div>
<% }
%>
The second strategy is divide most of the body in master page into two parts, one for mobile, and one for desktop.
Pro: Avoids downloading an additional .css file. (Because the mobile code can be in a div with id of mobile and use specificity rules in the css).
Con: Greater duplication of code.
The tags must have unique ids, even though they are in mutually exclusive code blocks.
css is more complex for mobile page, because all tags are underneath a mobile tag.
A similar excerpt for the master page using this strategy:
<% if (isMobile)
{
%>
<div id="mobile-search-controls">
<asp:ContentPlaceHolder ID="MobileSearchContent" runat="server" />
</div>
<%--body --%>
<div id="bd" class="row-fluid">
<div id="main" class="span9">
<div id="search-results">
<asp:ContentPlaceHolder ID="MobileMainContent" runat="server" />
</div>
</div>
</div>
<%--body end--%>
</div>
<%
}
else
{ %>
<div id="bd" class="row-fluid">
<div id="left-column" class="span3">
<div id='controls-and-preferences'>
<asp:ContentPlaceHolder ID="LeftColumnContent" runat="server" />
</div>
</div><!--left-column -->
<div id="main" class="span9">
<div id="search-results">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
</div>
<div class="span2" id='right-column'>
</div>
</div>
<%--body end--%>
<% }
%>
Which way should I go? Is there a third better way?
You might want to consider using a framework such as Twitter Bootstrap (http://twitter.github.com/bootstrap/).
They have some examples that work well on devices of any resolution:
http://twitter.github.com/bootstrap/examples/fluid.html
you should be using css 3 media queries for things like this.. have a look at this link it has a demo
http://webdesignerwall.com/demo/adaptive-design/final.html
user277498,
I've used the Mobile Ready HTML5 MVC.NET template for vs:
http://visualstudiogallery.msdn.microsoft.com/9df9c61c-4d90-43e5-9aa1-a58786b7a1e4
to great effect. this basically has a viewengine that allows views to be directed twds mobile and/or normal mvc. it's actually quite 'magic' the way it works. give it a try, I've used in 3 projects now with no hiccups.

PartialViews Messing With Eachother

I have the following _Layout.cshtml page that has a bunch of #Html.Action() calls to several partial views.
<div class="wrapper">
<div class="header">
<a style="text-decoration:none;" href="#Url.Action("Index", "Home")"><div class="logo"><p>fisharwe</p><span class="greenText float-right">:</span></div></a>
<div class="searchBar">
#Html.Action("Search", "Item")
</div>
<div id="hearGreenBar"></div>
</div>
<div class="pageContent">
#RenderBody()
</div>
<div class="rightColumn">
<div id="help">
<div id="allHelpContent">
<span id="helpIcon"></span> <span id="helpTitle">help</span> <span id="helpArrow"></span>
</div>
</div>
<div id="userPanel">
#if(!Request.IsAuthenticated)
{
<div id="loginForm">#Html.Action("Login", "User")</div>
<div id="registerForm">#Html.Action("Register", "User")</div>
<hr class="greyLine" />
<div id="recentlyViewedItems">
<div id="recentItemsTitle">
<span class="recentItemsIcon"></span><span class="theRecentTitle">Recently Viewed</span>
</div>
</div>
}
else
{
<div id="userInfoSummary">#Html.Action("Summary", "User")</div>
}
</div>
</div>
</div>
At the top you can see the #Html.Action("Seach", "Item") call which renders a search bar and allows users to search for items/categories/sub-categories...etc. I got this working now, but it generated a new problem! When the user searches for something, and the results are rendered, the Login and Register partials in the sidebar (userPanel) are displaying validation errors such as "Email cannot be empty". I understand that the View is rendered regardless of what partial posted back but there has to be a way to prevent that from happening... Do I have to get rid of partials and render everything into the _Layout.cshtml page? But in that case I need to make this page typed which will cause yet another issue... So what can be done? I'm open to any suggestions...
Thank you.
Do you have different forms for the search and what is in the "userPanel"?. You may want to make sure your search is doing a get and not a post.
#using (Html.BeginForm("Search", "YourController", FormMethod.Get))

Resources