I am trying to output the results in my #helpers code and the code looks like this
#helpers listfiles(String ID, String CNumber,){
foreach(Loopitem I in GetLoop("items")){
if(I.GetValue("userId") == ID){
<li>#I.GetValue("name")</li>
}else{
If(I.GetValue("userId") != ID){
<li>#I.GetValue("name")</li>
}
}
}
}
As a result I get all li elements but what I want is that if the statement is true it should wrap all the li elements in ul element and for the else statement it should wrap all the li in new UL element. Please help
One possible way by using two foreach, one for each user ID group :
#helpers listfiles(String ID, String CNumber,){
<ul>
foreach(Loopitem I in GetLoop("items").Where(o => o.GetValue("userId") == ID)){
<li>#I.GetValue("name")</li>
}
</ul>
<ul>
foreach(Loopitem I in GetLoop("items").Where(o => o.GetValue("userId") != ID)){
<li>#I.GetValue("name")</li>
}
</ul>
}
You mean something like this:
#helpers listfiles(String ID, String CNumber,){
var lstTrue = new List<>();
var lstFalse = new List<>();
foreach(Loopitem I in GetLoop("items")){
if(I.GetValue("userId") == ID)
lstTrue.Add(I);
else
lstFalse.Add(I);
}
if(lstTrue.Count()>0)
{
<ul> foreach(var I in lstTrue){<li>#I.GetValue("name")</li>}</ul>
}
if(lstFalse.Count()>0)
{
<ul> foreach(var I in lstTrue){<li>#I.GetValue("name")</li>}</ul>
}
}
Or you can make use of Lambda expression to reduce lines of code.
Related
<div class="validation-summary-errors">
<span>Please check the following entries:</span>
<ul>
<li>Please select a client account</li>
<li>Please select a beneficiary account</li>
</ul>
</div>
public virtual T VerifyAmountValidationMessages()
{
HtmlDiv error = new HtmlDiv(_browserWindow);
error.SearchProperties[HtmlDiv.PropertyNames.Class] = "validation-summary-errors";
var errors = error.FindMatchingControls();
var errorLi = error.GetChildren()[0];
foreach (var item in errors)
{
Assert.IsTrue(item.GetProperty("InnerText").ToString().Contains("Please check the following entries:\r\nPlease select a client account\r\nPlease select a beneficiary account"));
}
return (T)this;
}
How can I iterate all the lis and assert the inner text of each Li, with the getChildren I can access the span element individually but I want to access the Li individually? Right Now I am asserting the whole text which is not the correct approach at all.
The ul element would be errors.GetChildren()[0]; you would them loop over its children.
<div class="validation-summary-errors">
<span>Please check the following entries:</span>
<ul>
<li>Please select a client account</li>
<li>Please select a beneficiary account</li>
</ul>
</div>
public virtual T VerifyAmountValidationMessages()
{
HtmlDiv error = new HtmlDiv(_browserWindow);
error.SearchProperties[HtmlDiv.PropertyNames.Class] = "validation-summary-errors";
var errors = error.FindMatchingControls();
var errorul = error.GetChildren()[1];
foreach (var item in errors
{
// check individual li items
}
return (T)this;
}
This would seem to be a brittle test though, consider if any changes are made to how errors are displayed, you'll have to rewrite the test.
My question would be complicated but I will try to ask clearly.
I want to keep tags in a data at SQL, as using the comma in a cell. Then, try to call two different way on my MVC 4 project. One way (basic one) is working. But another one is hard to run. I will give my codes one by one.
SQL Table:
Controller:
public ActionResult Portfolio()
{
return View(db.Portfolios.ToList());
}
View:
#model IEnumerable<emirhanozkan.Models.Portfolio>
#{
foreach (var pot in Model)
{
<p>#pot.Tags.Split(',')[0]</p>
<p>#pot.Tags.Split(',')[1]</p>
<p>#pot.Tags.Split(',')[2]</p>
}
}
In same View one more foraech is running:
#foreach (var po in Model)
{
<li class="item #po.Tags.ToLower().Trim().Replace(",","")">
<img src="#po.Image" />
#po.Title
</li>
}
So, What I want to do with Split method:
<p>AngularJS</p>
<p>MVC</p>
<p>C#</p>
<p>Wordpress</p>
<p>MVC</p>
I guess my #pot.Tags.Split(',')[0], #pot.Tags.Split(',')[1] and #pot.Tags.Split(',')[2] code is wrong to list them but my brain not working anymore than that one. Please help me get them like my dream. Also, if you now to get just one from repeat words like <p>MVC</p> <p>MVC</p>, to just <p>MVC</p> please add to new code.
You can just loop on the array returned by Split() method and then render the tags:
foreach (var pot in Model)
{
var tags = #pot.Tags.Split(',');
foreach(var tag in tags)
{
<p>#tag</p>
}
}
sorry for errors, I write without compile:
List<Portfolio> Model = new List<Portfolio>();
StringBuilder finaltags= new StringBuilder();
foreach (var pot in Model)
{
finaltags.AppendLine("<p>" + #pot.Tags.Split(',') + "</p>");
}
#Html.Raw(finaltags.ToString());
foreach (var pot in Model)
{
var tags = #pot.Tags.Split(new []{','}, StringSplitOptions.RemoveEmptyEntries);
foreach(var tag in tags)
{
<p>#tag</p>
}
}
foreach (var pot in Model)
{
<li>
<img src="#po.Image" />
<a href="#po.Url" target="_blank" class="md-button md-primary">
#po.Title</a>
</li>
}
Thank you for your suggestions. But I found the answer to my question:
#{
foreach (var pot in Model)
{
string str = pot.Tags;
string[] strT = str.Split(',');
foreach (var poo in strT) {
<p>#poo</p>
}
}
}
I am working on a combined EDIT / New item page and want to check a list for items and then call HTML.Action() on a default value if .Count > 0 or loop through the list calling the same HTML.Action() to return the same partial view with different data.
Code so far that is not working:
#{
var list = #Model.MyList.FindAll(x=>x.somval == someotherval);
if (list.Count == 0)
{
#Html.Action("MyFunc", "MyController", new { MyData = Default.Value });
}
else
{
foreach(var Item in #Model.MyList)
{
#Html.Action("MyFunc", "MyController", new { MyData = Item.Data });
}
}
}
The issue is that the closing } for the first #Html.Action() is causing a compile error (expected ','). There has to be something simple that i am missing but I cannot seem to find the issue through googling.
EDIT Added full code.
EDIT: Thanks to Ashley Medway answer (posted before I edited to include the full code) I now have the following that is working
#{var list = #Model.MyList.FindAll(x=>x.somval == someotherval); }
#if (list.Count == 0)
{
Html.Action("MyFunc", "MyController", new { MyData = Default.Value });
}
else
{
foreach(var Item in list)
{
Html.Action("MyFunc", "MyController", new { MyData = Item.Data });
}
}
Thanks for your help.
You need to use # before if statment and remove # before foreach.
#if (Model.MyList.Count == 0)
{
#Html.Action("MyFunc", "MyController", new { MyData = Default.Value })
}
else
{
foreach (var Item in Model.MyList)
{
#Html.Action("MyFunc", "MyController", new { MyData = Item.Data })
}
}
The code that I would expect to work would look like this:
#if (Model.MyList.Count == 0)
{
#Html.Action("MyFunc", "MyController", new { MyData = Default.Value })
}
else
{
foreach(var Item in Model.MyList)
{
#Html.Action("MyFunc", "MyController", new { MyData = Item.Data })
}
}
FIX 1
An if statement in a razor view needs to start with an #, assuming that the if statement is not wrapped an another code block.
Change if (Model.MyList.Count == 0) to #if (Model.MyList.Count == 0)
FIX 2
Remove # from inside the foreach loop. As we are already inside a code block we do not need the # to access the model.
Change foreach(var Item in #Model.MyList) to foreach(var Item in Model.MyList)
FIX 3
Removing ; from the end of #Html.Action(...). Semicolons are not needed to terminate a line in the razor view. When using HTML helpers, it would still be needed in a some scenarios but the compiler will let you know :)
Leaving the semicolon ; in will not actually break your view but it will result in semicolons being added to your rendered HTML.
I have a panel that is created and filled via a vacancy page I have created. Im doing it as follows:
#{
var root = CurrentPage.AncestorOrSelf(1);
var newsNode = root.Descendants("News").First();
var vacanciesNode = root.Descendants("Vacancies").First();
string shortenedSummary = string.Empty;
}
<ul>
#foreach (var vacancyItem in vacanciesNode.Descendants("Vacancy").Take(3).OrderBy("postDate desc"))
{
<p>here we are 2</p>
#vacanciesNode.Count().ToString()
<li>
<h4>#vacancyItem.jobTitle</h4> <span>Posted on #vacancyItem.postDate.ToString("dd/MM/yyyy")</span>
<p>
#if (vacancyItem.jobSummary.Length <= 182)
{
#vacancyItem.jobSummary
}
else
{
shortenedSummary = vacancyItem.jobSummary.Substring(0, 182) + "...";
#shortenedSummary
}
</p>
Read More..
</li>
}
</ul>
However, when there are no vacancy items, my list is empty. Should this be the case, I'm wanting it to read "sorry no vacancies just now" but I don't know how to check if my vacanciesNode has any items in it.
Could someone show me how I could achieve this?
Since the .Descendants() method returns a DynamicContentList (a collection) you can simply do a .Count() on the collection and check whether it's more than or equal to 1.
If there's more than 0 items in the collection, it's not empty.
So, what you need to do is surround your #foreach with an #if statement which checks on this, and an else statement after that prints whatever html you want to show if there's no vacancies
#if( vacanciesNode.Descendants("Vacancy").Take(3).OrderBy("postDate desc").Count() > 0) {
//Do foreach
}
else
{
//Write message about missing vacancies
}
After I run my query I have got the result into a dataTable as the following (this is only a simplified resultset):
food_cat food
-----------------------
vegit carrot
vegit onion
vegit tomato
fruit cherry
fruit banana
fruit orange
I want to list that result grouped by food_cat in an unordered list.
<h3> Vegit </h3>
<ul>
<li>carrot</li>
<li>onion</li>
<li>tomato</ti>
</ul>
<h3>fruit</h3>
<ul>
<li>cherry</li>
<li>banana</li>
<li>orange</li>
</ul>
I have tried some for, if, while controls but could not find a good solution.
since you don't provide table names etc. i will try to give the answer in general way.
string previous_food_cat = '';
bool firstEntrance = true
while(trace resultSet until no elements left)
{
if resultSet.food_cat != previous_food_cat //check if food_cat value changed
{
if (!firstEntrance) //if not first entrance close the <ul> tag before opening new one
{
print </ul>
}
print <h3> resultSet.food_cat </h3> //open new <h3> tag
print <ul> //open new <ul> tag
previous_food_cat = resultSet.food_cat //update previous_food_cat for new food_cat value
firstEntrance = false //set firstEntrance false so that ul tqags should be closed
}
print <li> resultSet.food </li>
}
Thank you #zibidyum, your technic obtained me to reach a solution. But final solution is here:
public bool firstcat; // defined at before Page_Load method
public int temp_cat; // defined at before Page_Load method
for (int i = 0; i < dt.Rows.Count; i++)
{
if (temp_cat != Convert.ToInt32(dt.Rows[i]["food_cat"]))
{
if (i > 0 && !firstcat)
content.InnerHtml += "</ul>"; //solution's most critic point is here
content.InnerHtml += "<ul>"
}
content.InnerHtml += String.Format("<li>{0}</li>", dt.Rows[i]["food"].ToString());
temp_cat = Convert.ToInt32(dt.Rows[i]["food_cat"]);
}
Any better solutions, suggestions and/or ideas are welcome.