Html.LabelFor inside a loop - asp.net-mvc-2

I have the following code:
<% foreach (var orderDetail in Model.OrderDetails) { %>
<div><%= Html.LabelFor( x => orderDetail.DateOfBirth)%></div>
<div><%= Html.TextBoxFor(x => orderDetail.DateOfBirth) %></div>
<% } %>
The info is being displayed, however, I can't click on the label and go to the text box because the ID attribute is being repeated due to the foreach loop.
<label for="orderDetail_DateOfBirth">DateOfBirth</label>
<input type="text" value="" name="orderDetail.DateOfBirth" id="orderDetail_DateOfBirth">
Does anyone know how to fix this?
UPDATE:
I ended up doing it this way since UpdateModel() didn't work either, any thoughts?
<%
int i = 0;
foreach (var orderDetail in Model.OrderDetails) { %>
<div><label for="DateOfBirth_<%=i %>_">Date of Birth</label></div>
<div><%= Html.TextBox("DateOfBirth[" + i + "]", orderDetail.DateOfBirth) %></div>
<% i++
} %>

have a look at this post from phil haack
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
near the bottom of the article it talks about looping controls and using array indexes and whatnot.
Here's the basic syntax taken from there and adjusted to fit your senario.
<% for (int i = 0; i < Model.OrderDetails.count; i++) { %>
<%: Html.LabelForm(m => Model.OrderDetails[i].DateOfBirth) %>
<%: Html.TextBoxFor(m => Model.OrderDetails[i].DateOfBirth) %>
<% } %>
for the model binder to handle this properly it has to have sequential indexes. But other then that, this should work.

You can create custom id inside of the loop
i would use htmlAttributes to define the id.
Such as:
<%
int i = 0;
foreach (var orderDetail in Model.OrderDetails) {
%>
<div><%= Html.LabelFor( x => orderDetail.DateOfBirth)%></div>
<div><%= Html.TextBoxFor(x => orderDetail.DateOfBirth, new { id = "orderDetailDateOfBirth_" + i++ })%></div>
<% } %>
Or you can use :
jquery to identify object that you had clicked on using $(this)

Related

gmaps4rails repeating partials for markers

I am having difficulty with gmaps4rails infowindow. I have an app which successfully displays multiple markers using json data stored in activerecord. I created a partial to select additional info to display in the infowindow, but the same data from the first instance of PoliceAlert class is being repeated in each marker:
Controller:
class StaticPagesController < ApplicationController
def main
#police_alerts = PoliceAlert.all
#police_hash = Gmaps4rails.build_markers(#police_alerts) do |police_alert, marker|
marker.lat(police_alert.latitude)
marker.lng(police_alert.longitude)
marker.json({:id => police_alert.id })
marker.picture({
"url" => view_context.image_path('/assets/police.png'),
"width" => 32,
"height" => 37
})
marker.infowindow render_to_string(:partial => '/layouts/police_alerts_infowindow', :locals => { :police_alert => police_alert } )
end
end
Partial:
<% PoliceAlert.find do |police_alert| %>
<%= police_alert.hundred_block_location %>
<br><%= police_alert.event_clearance_description %></br>
<%= police_alert.event_clearance_date %>
<% end %>
How do I get markers to display info for each police_alert? Thanks so much in advance?
Not sure to understand but replace your partial with:
<%= police_alert.hundred_block_location %>
<br/>
<%= police_alert.event_clearance_description %>
<br/>
<%= police_alert.event_clearance_date %>

Simple foreach loop in MVC

<% foreach (var car in Model.AvailableCars)
{ %>
<label><%car.Text; %></label>
<% } %>
The above code throws the error
Only assignment, call, increment, decrement, and new object expressions can be used as a statement.
I know I can do it with html helpers, but why won't the above code work?
<label><%car.Text; %></label>
should read
<label><%= car.Text; %></label>
^
or you can use
<label><%: car.Text; %></label>
^
which will automatically HTML.Encode the value for you.
Add a colon to the car.Text tag to write it to the document, such as:
<label><%: car.Text %></label>
Here's a good explanation of <%: versus <%= asp.net mvc tags: <%: %> vs. <%= %>

Why isn't Template Toolkit aggregating my counter?

I'm working on a simple Dancer app to log books a person has read, but in my template to show how many books a person has read, I'm stumbling into an error. I'm trying to go through ever row in the table of reading instances and add 1 to a counter if the reader is the same as the listed person.
Here's the code for the template:
<ul class="people">
<% IF people.size %>
<% FOREACH id IN people.keys.nsort %>
<li><h2 style="display: inline;"><% people.$id.name %></h2><br />
Born <% people.$id.birthday %><br />
<% FOREACH reader IN readings.keys.nsort %>
<% count = 0 %>
<% IF readings.$reader.person_id == people.$id.id %>
<% count = count + 1 %>
<% END %>
<% END %>
<% count %>
<% END %>
<% ELSE %>
<li><em>Unbelievable. No people here so far</em>
<% END %>
</ul>
However, when I display it, count is only 1. Does anybody know what I'm doing wrong, or do you need more code?
Thanks.
Looks like you need to pull the count initialization out of the FOREACH reader loop:
<% FOREACH id IN people.keys.nsort %>
<li><h2 style="display: inline;"><% people.$id.name %></h2><br />
Born <% people.$id.birthday %><br />
<% count = 0 %>
<% FOREACH reader IN readings.keys.nsort %>
<% IF readings.$reader.person_id == people.$id.id %>
<% count = count + 1 %>
<% END %>
<% END %>
<% count %>
<% END %>

How to assign ids for textboxes added using loop in asp.net MVC

I am arranging a dynamic table of textboxes using a loop.
Please review the following code segment in view -
<% foreach (var item in Model.Names) { %>
<% =Html.TextBoxFor(item.Name)%>
<% } %>
The problem here is that i want their unique ids to be generated so that i could access each textbox using JS.
Any help is highly appreciated.
Regards
Irfan
Do this instead:
<div class="editor-field">
<% for (int i = 0; i < Model.Names.Count; i++) { %>
<%: Html.TextBoxFor(m => m.Names[i].Name) %>
<% } %>
</div>

Get object out of List< Tuple < object1, object2 > > and store in ViewModel

[Suggestion: Want to read the answers in a logical manner ?? >> choose TAB [Oldest]
Goal:
Presentation of books with related inventorydetails on homepage
such as Book.Title, InventoryDetail.Quantity etc.
(Join|Book.BookId <=< InventoryDetail.BookId)
Problem 1: How to join
Problem 2: How to use a tuple (list of tuples)
Problem 3: How to store the separated objects (from the list of tuples) into a Strongly Typed ViewModel
Answer 1: An possible approach using Mike Brind's Guidance
Answer 2: Problem 1 and 2 tackled !!
Answer 3: Problem 3 tackled !!
Have fun with it. I'm happy to share!!!
public ActionResult Index()
{
// Return a list of tuples {(WebshopDB.Models.Book, WebshopDB.Models.InventoryDetail)}
// Each tuple containing two items:
// > Item1 {WebshopDB.Models.Book}
// > Item2 {WebshopDB.Models.InventoryDetail}
var tuple_booksinventorydetails = ListOfTuples_BookInventoryDetail(5);
// BEGIN UNDER CONSTRUCTION Setting up ViewModel
// See below the code for the ViewModel
var viewmodel = new HomeIndexViewModel()
{
// Problem // Book = tuple_books.Contains(Book).??,
// Problem // InventoryDetail = tuple_books.Contains(InventoryDetail).??
};
// END
return View( ..... );
}
private List<Tuple<Book, InventoryDetail>> ListOfTuples_BookInventoryDetail(int count)
{
var list_of_tuples = new List<Tuple<Book, InventoryDetail>>();
var showbooks = webshopDB.Books
.Join(webshopDB.InventoryDetails, b => b.BookId, i => i.BookId, (b, i) => new { b = b, i = i })
.Where(o => (o.b.ShowInWebshop == true))
.Where(o => o.b.BookThumbUrl.Contains(".jpg"))
.Take(count);
foreach (var item in showbooks)
{
list_of_tuples.Add( Tuple.Create<Book, InventoryDetail>( (item.b), (item.i) ) );
}
return list_of_tuples;
}
As promised! I did reach my goal!!!
<%-- Index.apsx --%>
<%# Page Title=" <Domain> " Language="C#" MasterPageFile="~/Views/Shared/Store.Master"
Inherits="System.Web.Mvc.ViewPage<HomeTupleIndexViewModel>" %>
<%-- Mandatory 'Import' --%>
<%# Import Namespace="<Domain>.ViewModels" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%--....--%>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%-- Exerecise Tuple --%>
<% Html.RenderPartial("BookPartial", Model.Book); %>
<% Html.RenderPartial("InventoryDetailPartial", Model.InventoryDetail); %>
</asp:Content>
<%-- BookPartial.ascx --%>
<%-- Currently this ViewPartial is a Strongly Typed ViewPartial %> --%>
<%# Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<IEnumerable< <Domain> .Models.Book>>" %>
<%# Import Namespace=" <Domain> .Helpers" %>
<%-- Strongly Typed ViewPages--%>
<ul id="...">
<% foreach (var item in Model) {%>
<li>
<div id="...">
<p>
<a href="<%: Url.Action("Details", "Store", new { id = item.BookId }) %>">
<div id="...">
<h2>
<span><%: item.Genre %></span>
</h2>
</div>
<div id="...">
<img alt="<%: item.Title %>" src="<%: item.BookThumbUrl %>" />
</div>
<div id="...">
<span><%: item.Title %></span>
</div>
</a>
</p>
</div>
</li>
<% } %>
</ul>
<%-- InventoryDetailPartial.ascx --%>
<%# Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<IEnumerable< <Domain> .Models.InventoryDetail>>" %>
<%# Import Namespace=" <Domain> .Helpers" %>
<%-- Strongly Typed ViewPages--%>
<ul id="...">
<% foreach (var item in Model) {%>
<li>
<div id="...">
<p>
<div id="...">
<span>
<% if (item.Quantity == 1)
{ %>
<%: Server.HtmlDecode(Html.Translation("Stock_Amount"))%> <%: item.Quantity %> <%: Server.HtmlDecode(Html.Translation("Copy"))%>
<% }
else if (item.Quantity > 1) %>
<% { %>
<%: Server.HtmlDecode(Html.Translation("Stock_Amount"))%> <%: item.Quantity %> <%: Server.HtmlDecode(Html.Translation("Copies"))%>
<% }
else
{ %>
<%: Server.HtmlDecode(Html.Translation("Sold_Out"))%>
<% } %>
</span>
</div>
</p>
</div>
</li>
<% } %>
</ul>
So, finally I ended up with an Index.aspx calling two separate Partial Views (I prefer to speak about 'controls' instead of 'partials', however, this is just a matter of personal taste).
Compared to Mike Brind's guide (mentioned in my first answer) by using this tuple 'path' guide you'll finally have more 'freedom' to do as you like on the index page. The 'related' objects (!! the 'join' remember !!) are nicely separated in the presentation layer, however still strongly related!
Answer ( Solution for my own posted question! )
// Instantiate new lists needed to add the to be separated objects of the tuple
List<Book> T1 = new List<Book>();
List<InventoryDetail> T2 = new List<InventoryDetail>();
// Iterate through the tuple and add each 'item' of each tuple into the new instantiated lists
for (int i = 0; i < tuple_booksinventorydetails.Count; i++)
{
var tuple = tuple_booksinventorydetails[i];
// Item1
T1.Add(tuple.Item1);
// Item2
T2.Add(tuple.Item2);
}
// Instantiate a new viewmodel to store the separated lists
// ==HomeTupleIndexViewMode Class==
//using System;
//using System.Collections.Generic;
//using <Domain>.Models;
//namespace <Domain>.ViewModels
//{
// public class HomeTupleIndexViewModel
// {
// public List<Book> Book { get; set; }
// public List<InventoryDetail> InventoryDetail { get; set; }
// }
//}
// ==
HomeTupleIndexViewModel tupleviewdata = new HomeTupleIndexViewModel()
{
Book = T1,
InventoryDetail = T2
};
return View(tupleviewdata);