I am trying to achieve something like the following with MVC4 Razor Syntax. Here is the Code I am trying to write:
#{
int counter = 1;
#foreach (var item in Model)
{
#if (counter == 1)
{
<div class="section show">
}
else
{
<div class="section">
}
<span>#counter <text> .</text> #Html.DisplayFor(ab => item.Title)</span>
<div class="section-content">
#Html.DisplayFor(ab => item.Description)
</div>
</div>
counter++;
}
}
The above Code doesn't give any Compilation Error. But it causes Run time error. It says the Closing Tag is missing. Is it somehow possible to make the C# Code and HTML Code work together to achieve the result that I am trying to achieve here?
I am trying to get the C# Code and make them work based on Condition. For example, in the if Statement, if Counter is 1, the first div class will be selected and in rest of the times, the second div class will be selected.
Thanks. (I have updated the Question)
Don't use the if to create the div. Use it to determine the value of the class attribute:
#{
int counter = 1;
foreach (var item in Model)
{
result = "section";
if (counter == 1)
{
result = "section show";
}
<div class="#result">
<span>#counter <text> .</text> #Html.DisplayFor(ab => item.Title)</span>
<div class="section-content">
#Html.DisplayFor(ab => item.Description)
</div>
</div>
counter++;
}
}
Related
I am trying to create a custom url which is within a loop so that through each loop the produced url is different. The code looks like this:
#foreach (var car in Model)
{
<div class="container">
#{string country = Html.DisplayFor(modelCar => car.Country).ToString()}
#{string mapUrl = "https://maps.googleapis.com/maps/api/staticmap?zoom=14&size=150x120&key=[insertkey]¢er="
+ country}
<img src=#mapUrl />
</div>
}
The problem is the line where I define mapUrlrenders an error. What is the problem with this code?
Thanks in advance.
I think you are simply missing the semi columns for the variables and quotes for the image src tag.
Also i am not sure why you are calling DisplayFor to get the country variable name! DisplayFor returns an MvcHtml string and is usually used to get the encoded html markup to render to browser. Unless you have some crazy overloading of that (why would you do that on DisplayFor ? Use a simply helper method), do not misuse the DisplayFor helper
This should work.
#foreach (var car in Model)
{
<div class="container">
#{ var country = car.Country; } // i assume you just need the Country
#{ var mapUrl = "https://maps.googleapis.com/maps/api/staticmap?zoom=14&size=150x120&key=[insertkey]¢er=" + country; }
<img src="#mapUrl" />
</div>
}
I'm making a newsfeed project in Visual Studios, MVC 3, Razor engine and I'm trying only to display, let's say 10, number of feeds at once.
Currently while I was getting the database going I used this index.cshtml:
#model IEnumerable<NyjiGrunnur.Models.Article>
#{
ViewBag.Title = "NewsFeed";
}
<h2>#ViewBag.Message</h2>
#foreach (var item in Model)
{
<div id="eitt">
<fieldset>
<legend>#Html.ActionLink( item.Name, "Edit", new { id=item.Id } )</legend>
<div>#item.Subject, #item.Created</div>
<p>#Html.Raw(item.Content.Replace(Environment.NewLine, "<br/>"))</p>
</fieldset>
</div>
}
The foreach takes every single item and I was wondering if I could use a for loop or something similar to display only the 10 newest feeds.
Thanks in advance.
You can keep a counter variable and check it before displaying the data
#{
int counter=0;
}
foreach (var item in Model)
{
counter++;
if(counter<=10)
{
<div id="eitt">#item.Name</div>
}
}
But it is better to do this at your Action method and return only 10 items to the view so that you don't need to contaminate your view by adding the if statement. You can use the Take method from LINQ to get the 10 items.
public ActionResult Newsfeed()
{
List<Article> articleList=new List<Article>();
articleLsit=GetListOfItemsFromSomewhere();
//now get only 10. you may apply sorting if needed
articleList=articleList.Take(10);
return View(articleList);
}
it will be better
#foreach (var item in Model.Take(10))
{
<div id="eitt">
<fieldset>
<legend>#Html.ActionLink( item.Name, "Edit", new { id=item.Id } )</legend>
<div>#item.Subject, #item.Created</div>
<p>#Html.Raw(item.Content.Replace(Environment.NewLine, "<br/>"))</p>
</fieldset>
</div>
}
Here is what my view looks like:
#model Affiliate
<div class="box paint color_16">
<div class="title">
<h4><i class="icon-tasks"></i><span>#Model.CompanyName's Commissions</span> </h4>
</div>
<div class="content top ">
<div class="subtitle">
#Html.ActionLink("Void", "DeleteInvoice", new { commList = "??", affId = Model.Id }, new { #class = "btn" })
#Html.ActionLink("Create Invoice", "CreateInvoice", new { commList = "??", affId = Model.Id }, new { #class = "btn" })
#Html.ActionLink("Pay", "PayInvoice", new { commList = "??", affId = Model.Id }, new { #class = "btn" })
</div>
<table class="table table-striped table-hover">
<tr>
<h3>Commissions</h3>
</tr>
<tr>
<td></td>
<td>Amount</td>
<td>Status</td>
<td>Action</td>
</tr>
#foreach (var item in Model.Commissions)
{
<tr>
#if (item.Status == ViewBag.PaymentStatus || ViewBag.PaymentStatus == "All")
{
<td>#Html.CheckBox("commId", new { value = item.Id })</td>
<td>#Html.DisplayFor(x => item.PayoutAmount)</td>
<td>#Html.DisplayFor(x => item.Status)</td>
}
</tr>
}
</table>
</div>
What I want to be able to do is when I hit an actionlink on the top, grab all the items from the table that are checked, and pass that list of id's to the controller logic. I am assuming a viewmodel may be the solution, something like this:
public Affiliate affilite { get; set; }
public List<int> selectedItems { get; set; }
etc.
But how to I get the selected Items into that VM selectedItems container?
Based off your comments, you don't seem to be looking for the most "correct" answer, but rather just a quick and dirty "how would I do this" answer. If you just want to pass the list, you could setup your controller action like this:
public ActionResult MyAction(int[] id)
{
...
}
Or, you seem to indicate it is strongly typed to a view model with a property that contains a List (I would shorten the name of the property, you'll see why in a second).
In javascript, the easiest thing to do would be to use jQuery to bind a click event on your hyperlink that gets the list of items that are checked and appends that to the query string.
$("#myLink").click(function()
{
var url = "site.com/action?";
var ids = $(".table").find("input:checked");
ids.each(function()
{
url += "id=" + $(this).val() + "&"
});
window.location = url;
});
Basically, you want to create one long query string with the action parameter's name repeated over and over, which identifies an array. It looks something like this (id is for int[] id in MyAction):
id=15&id=20&id=25&id=30&....
And then once the query string is built, redirect the user to that url. MVC should then be able to bind that to an array and you're all set.
That's basically the idea, anyway; the syntax and the javascript I wrote could be way off so don't copy my code and expect it to work as is - I wrote that off the top of my head. If your action is bound to a viewmodel, then you need to set the parameter in the query string to the name of the property of your model:
selectedids=1&selectedids=2&selectedids=3...
Or, if the array is a property of an object, which is a property of the model...
model.selectedids=1&model.selectedids=2&model.selectedids=3...
You'll just need to play around with it some.
Use html checks inside form tag ( you could use helpers too) and post the model to a post action.
MVC will serialize the model automatically
I'm using C#.NET MVC3 (Razor) to create a simple form. But in that form i need to print the content of a list in the form of radiobuttons. But i'm not sure how this works:
#using(Html.BeginForm("Method", "Controller", FormMethod.Post))
{
foreach (Items item in Model.Items)
{
<div>
#Html.RadioButtonFor(item->itemId)
#Html.LabelFor(item->description)
</div>
}
}
But this doesn't work.
I can probably use normal html tags to create the radio buttons. But then the data won't be auto saved in the right?
How can i make this work?
I would recommend you using editor templates instead of writing those loops:
#model MyViewModel
#using(Html.BeginForm("Method", "Controller", FormMethod.Post))
{
#Html.EditorFor(x => x.Items)
}
and now define a corresponding editor template which will automatically be rendered for each element of the model (~/Views/Shared/EditorTemplates/ItemViewModel.cshtml):
#model ItemViewModel
<div>
#Html.RadioButtonFor(x => x.itemId, "1")
#Html.LabelFor(x => x.description)
</div>
Notice that you must pass a second argument to the Html.RadioButtonFor helper in addition to the lambda expression that picks the corresponding view model property. This argument represents the value that will be sent to the server and bound to the corresponding property if the user checks this radio button when the form is submitted.
Also notice that this works by convention. If we assume that the Items property in your main view model is of type IEnumerable<ItemViewModel> then the corresponding editor template that you must define and which will be rendered for each element of this collection is ~/Views/Shared/EditorTemplates/ItemViewModel.cshtml or ~/Views/CurrentController/EditorTemplates/ItemViewModel.cshtml if you don't want this template to be shared between multiple controllers.
As you are inside foreach loop. following will work.
foreach (Items item in Model.Items)
{
<div>
#Html.RadioButtonFor(item.itemId)
#Html.LabelFor(item.description)
</div>
}
If you want to save them all you need to implement zero index based solution as follows
#{int i = 0}
foreach (Items item in Model.Items)
{
<div>
#Html.RadioButtonFor(model =>model[i].itemId)
#Html.LabelFor(model =>model[i].description)
</div>
i++;
}
The syntax is a bit different:
#Html.RadioButtonFor(model => item.ItemId)
#Html.LabelFor(model => item.Description)
Everything else looks fine.
[EDIT] Whoa, I must be tired. Yeah, the following looks just fine, but only for display. Check the Darin's answer for editor template.
[EDIT2] It's not quite obvious from the question, but it seems from your comments that the item in the foreach is another Enumerable. Nest the foreach loops then, to display the properties:
#foreach(var itemList in Model.Items)
{
foreach(var item in itemList)
{
<div>
#Html.RadioButtonFor(model => item.ItemId)
#Html.LabelFor(model => item.Description)
<div>
}
}
Is that it? I'm still not sure if I understand it correctly. :)
What's better?
1) If i make 3 ViewBag on server and then Render my View using this ViewBags?
Server
ViewBag.LeftColumnTales = tales.Where((x, i) => i % 3 == 0);
ViewBag.CenterColumnTales = tales.Where((x, i) => i % 3 == 1);
ViewBag.RightColumnTales = tales.Where((x, i) => i % 3 == 2);
View
<div id="left_column">
#foreach (var t in ViewBag.LeftColumnTales)
{
<div class="item">
#t.NameAn <span>(#(new HtmlString(Html.TimeForReadingHtmlResult((int)t.TimeForReading))))</span>
#(new HtmlString(Html.PeopleTaleVoterHtmlResult((int)t.Analit)))
</div>
}
<!--end of div.item-->
</div>
or
2) If i set ViewBag.tales on server and then on View will make Converting from dynamic data to IEnumerable and devide it to 3 columns?
Server
ViewBag.Tales = tales;
View
<div id="left_column">
#foreach (var t in ((IEnumerable<MVCFairyTales3.Models.AuthorTale>)ViewBag.Tales).Where((x, i) => i % 3 == 0))
{
<div class="item">
#t.NameAn <span>(#(new HtmlString(Html.TimeForReadingHtmlResult((int)t.TimeForReading))))</span>
#(new HtmlString(Html.AuthorTaleVoterHtmlResult((int)t.Analit)))
</div>
}
<!--end of div.item-->
</div>
What's better?
To be honest I don't like any of those two. They both use ViewBag and weak typing. I am sorry but personally I get sick when I see ViewBag/ViewData.
Personally I like using view models and strongly typed views:
public class MyViewModel
{
public IEnumerable<Tale> LeftColumnTales { get; set; }
public IEnumerable<Tale> CenterColumnTales { get; set; }
public IEnumerable<Tale> RightColumnTales { get; set; }
}
which you could populate in your action:
public ActionResult Foo()
{
var model = new MyViewModel
{
LeftColumnTales = tales.Where((x, i) => i % 3 == 0),
CenterColumnTales = tales.Where((x, i) => i % 3 == 1),
RightColumnTales = tales.Where((x, i) => i % 3 == 2),
};
return View(model);
}
and in the strongly typed view:
#model MyViewModel
<div id="left_column">
#Html.DisplayFor(x => x.LeftColumnTales)
</div>
and in the corresponding display template which will be rendered for each element of the collection (~/Views/Shared/DisplayTemplates/Tale.cshtml):
#model Tale
<div class="item">
#Html.ActionLink(
Model.NameAn,
Model.RouteNameAn,
Model.AuthorTalesCategory.RouteNameAn
)
<span>
#Html.Raw(Html.TimeForReadingHtmlResult((int)Model.TimeForReading))
</span>
#Html.Raw(Html.AuthorTaleVoterHtmlResult((int)Model.Analit))
</div>
And even better if you have to repeat this all over your pages is to put it in the _Layout using child actions as explained by Phil Haack in his blog post.
I'm not sure how you app is structured/layered, but in general I like to separate out my business/domain logic from my UI code. It sounds like whether it should be in the left/center/right column is strictly UI logic. In that case I would have my business layer retrieve/create the list of all tales, then leave it up to the UI layer to split it up however it is to be displayed.
When I'm trying to figure out if some logic belongs in the UI layer or not, I imagine that I am going to create many many UI's (web, windows, mobile phone, sharepoint webpart, etc) and ask myself if it's likely that logic (e.g. split it into 3 columns) will change between UI's. If the answer is yes, then that logic belongs in the UI layer.