Html.ActionLink does not display anything - asp.net-mvc

I have this simple snippet with an ActionLink that is supposed to display some text as a link, but it's not working.
Here's the code snippet.
<div id = "Div1">
<table id = "Table1">
<% while ((category = SomeNamespace.Helper.GetNextCategory(categoryIndex++)) != null)
{ %>
<tr>
<td class = "catalogCell">
<% Html.ActionLink(category.Name,
"DisplayCategory",
"Catalog"); %>
</td>
</tr>
<% } %>
</table>
</div>

You need an = sign:
<%= Html.ActionLink(category.Name,
"DisplayCategory",
"Catalog") %>

Use the <%: ... %> style and be sure to remove the semi-colon (;) at the end of the statement.

Related

Rails search function rendering page multiple timess

I have a search function in rails that should render a page to display the grants that were picked up by the search. However when you search, the template is rendered multiple times instead of just once, and its rendered on top of itself so it looks like a cluttered mess. I'm not sure where the error is but it must be calling render more than once. Heres my controller method:
def index
if params[:search]
#grants = Grant.search(params[:search]).order("created_at DESC")
else
#grants = Grant.all.order('created_at DESC')
end
end
And the part of my view where I render the template
<% if #grants.present? %>
<%= render #grants %>
<% else %>
<p>There are no grants containing the term(s) <%= params[:search] %>.</p>
<% end %>
<%= yield %>
and the template;
<html>
<body>
<style>div {
margin-left:17%;
padding:1px 16px;
height:1000px;}
</style>
<div>
<center>
<hr style="height:5 px; visibility:hidden;" />
<br>
<font size=6 >
<strong>
US Federal Grants
<br>
<br>
<hr style="height:5 px; visibility:hidden;" />
</strong>
</font>
</center>
<% if #grants != [] && #grants != nil%>
<table border="1" style="width:100%">
<tr>
<td><strong><font size=5>Title</font></strong></td>
<td><strong><font size=5>Award Ceiling</font></strong></td>
<td><strong><font size=5>Description</font></strong></td>
<td><strong><font size=5>Additional Information</font></strong></td>
<td><strong><font size=5>Closing Date</font></strong></td>
</tr>
<% for item in #grants %>
<tr>
<td><%= item.title %></td>
<% if item.ceiling != '$0' && item.ceiling != nil && item.ceiling != '' && item.ceiling != '$1' && item.ceiling != '$2'%>
<td><%= item.ceiling %></td>
<% else %>
<td> See link for more information </td>
<% end %>
<% if item.description == "" %>
<td>See link for more information</td>
<%elsif item.description == nil%>
<td>See link for more information</td>
<% elsif item.description.sub('Description:', '').length > 720 %>
<td>
<%= truncate(item.description.sub('Description:', ''), length: 720) %>
<%= link_to 'Read more', '', class: "read-more-#{item.id}" %>
<script>
$('.read-more-<%= item.id %>').on('click', function(e) {
e.preventDefault()
$(this).parent().html('<%= escape_javascript item.description.sub('Description:', '') %>')
})
</script>
</td>
<%else%>
<td> <%=item.description.sub('Description:', '')%></td>
<%end%>
<td><center> <a href= <%= item.link %>>LINK</a><center></td>
<%unless item.date == nil%>
<td><% newdate = Date.parse item.date %>
<%= newdate.strftime("%D") %>
</td>
<%end%>
</tr>
<% end %>
<% else %>
<center>
<p> There are no Grants available to Entrepreneurs in this category at this time. However this list updates daily based on Grants.gov data, so feel free to check back later. </p>
</center>
<% end %>
</table>
</div>
</body>
</html>
I'm not sure where its happening but it seems to be rendering it about 25 times
You've accidentally encountered Rails collection rendering. You can read more about it here: https://robots.thoughtbot.com/rendering-collections-in-rails
When you do
<%= render #grants %>
Rails interprets this as you wanting to render the grants/_grant.html.erb (I think – or some similar path) partial once for each grant.
If you instead want to render it only once, try
<%= render "grants/grant" %>
(Renaming the partial to something like "_grants.html.erb" and rendering that might also be a good idea, just so it doesn't look like it's intended to render a single grant.)

Using each_slice to produce a table but with sub headings

I am using each_slice to output a two column table.
I would like to insert a title row when an attribute of the elements I am iterating changes.
I have :
all_users = Users.order('category, name asc').all
all_users.each_slice(2) do |two_users|
<tr>
<td style="text-align:right">
<%= two_users[0].category + ' - ' + two_users[0].name %>
</td>
<% if two_users[1].present? %>
<td>
<%= two_users[1].category + ' - ' + two_users[1].name %>
</td>
<td>
<% else %>
<td></td>
<% end %>
</tr>
<% end %>
And would like something like :
current_category = ''
all_users = Users.order('category, name asc').all
all_users.each_slice(2) do |two_users|
<% if two_users[0].category != current_category
current_category = two_users[0].category
%>
<tr><td colspan="2"><%= two_users[0].category %></td></tr>
<% end %>
<tr>
<td style="text-align:right">
<%= two_users[0].name %>
</td>
<% if two_users[1].present? %>
<td>
<%= two_users[1].name %>
</td>
<td>
<% else %>
<td></td>
<% end %>
</tr>
<% end %>
This doesn't work obviously in the case that two_users[1] has a new category.
I am trying to avoid the additional SQL queries of iterating through each category and requesting
the users for each independantly.
all_users.each_slice(2).with_object({cc: nil}) do |two_users, memo|
if category = two_users.detect { |u| u.category != memo[:cc] }
# print additional row or do whatever here
memo[:cc] = category
end
end
Enumerable#detect here returns either changed category or nil if there were no changes.
Sidenote: Try to DRY:
<td>
<%= two_users[1].name if two_users[1].present? %>
</td>

Creating two or more sitemesh decorators in struts 2 app?

i am creatig a struts 2 application using sitemesh 2.4 plugin in which i want to apply multiple decorator acording to requested resource.
decorators.xml
<?xml version="1.0" encoding="UTF-8"?>
<decorators defaultdir="/decorators">
<decorator name="layout1" page="layout1.jsp">
<pattern>/first/*</pattern>
</decorator>
<decorator name="layout" page="layout.jsp">
<pattern>/second/*</pattern>
</decorator>
</decorators>
i have created to two different layout file named layout.jsp and layout1.jsp inside decorators directory and i have create a navigation file which is like this
<%# taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<decorator:usePage id="thePage" />
<html>
<head>
</head>
<body>
<% String selection = thePage.getProperty("meta.selection"); %>
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<% if(selection != null && "index".equals(selection)){ %>
Main
<%System.out.println(""+selection); %>
<% } else { %>
Main
<%System.out.println("index else"+selection); %>
<% } %>
</td>
</tr><tr>
<td>
<% if(selection != null && "page1".equals(selection)){ %>
Page 1
<% } else { %>
Page 1
<% } %>
</td>
</tr>
</table>
welcome page(/first/index.jsp) is displayed with layout1 decorator and when i click on "page 1" link it also display with corresponding(layout) decorator. but problem is that when click on Main link after visiting "page 1" it gives "HTTP Status 404 - /StrutsSitemesh/second/first/index.jsp" it's appending the requested resource with previous resource directory. plz help me to get it working
i am using reqest.getContextPath() method inside every link which return the context path of the application and request the resource with absolute path like this----
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<% if(selection != null && "index".equals(selection)){ %>
<a href="<%=request.getContextPath() %>/first/index.jsp
class="selected">Main</a>
<%System.out.println(""+selection); %>
<% } else { %>
Main
<%System.out.println("index else"+selection); %>
<% } %>
</td>
</tr>
<tr>
<td>
<% if(selection != null && "page1".equals(selection)){ %>
<a href="<%=request.getContextPath() %>/second/page1.jsp"
class="selected">Page 1</a>
<% } else { %>
Page 1
<% } %>
</td>
</tr>
</table>
if you people have much more productive and effective solution please elaborate.

Passing SelectList through ViewData to editor templates - not displayed properly

It's a bit complicated so bear with me.
Let's say I've got an example of a controller edit action defined like:
Node nd = _repo.getNode(id);
List<Category> ac = new List<Category>();
ac.AddRange(_repo.getCategories());
SelectList acl = new SelectList(ac, "category_id", "category_name", ac.Where(cat => cat.category_id == nd.category_id).First());
ViewData["category_id"] = acl;
return View(nd);
The view is templated like so:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Myapp.Models.Node>" %>
<% if (ViewData.TemplateInfo.TemplateDepth > 1)
{ %>
<%= ViewData.ModelMetadata.SimpleDisplayText %>
<% }
else
{ %>
<table cellpadding="0" cellspacing="0" border="0">
<% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm)))
{ %>
<% if (prop.HideSurroundingHtml)
{ %>
<%= Html.Editor(prop.PropertyName) %>
<% }
else
{ %>
<tr>
<td>
<div class="editor-label" style="text-align: right;">
<%= prop.IsRequired ? "*" : ""%>
<%= Html.Label(prop.PropertyName)%>
</div>
</td>
<td>
<div class="editor-field">
<% if (ViewData.Keys.Contains(prop.PropertyName))
{
if ((ViewData[prop.PropertyName]).GetType().Name == "SelectList")
{ %>
<%= Html.DropDownList(prop.PropertyName, (SelectList)ViewData[prop.PropertyName])%>
<% }
else
{ %>
<%= Html.Editor(prop.PropertyName)%>
<% } %>
<% }
else
{ %>
<%= Html.Editor(prop.PropertyName)%>
<% } %>
<%= Html.ValidationMessage(prop.PropertyName, "*")%>
</div>
</td>
</tr>
<% } %>
<% } %>
</table>
<% } %>
So, what the template does is display a dropdown list for every property for which ViewData["property_name"] exists.
I've also defined DisplayName metadata attributes for every property of my Node class.
Now, the dropdown lists display fine and are being populated correctly, but:
The first value from a list is always selected, even though the SelectList selected value predicate is fine and does set a proper value (in the debugger at least).
Html.Label in the template returns a proper DisplayName for properties, but when I define a ViewData for them so as to display the dropdown list, the label resets to normal property name (ie. category_id instead of Category).
What gives? Can you think of any "neater" way to accomplish this functionality?
Allright, no one's answering so there's my answer, maybe it comes in handy for someone:
Do not use your property names for ViewData keys! It messes up with the view model, so your views get confused and start to behave strangely.
Actually, best avoid the magic strings mess entirely, but if you insist, just use something like ex.: ViewData[prop.PropertyName+"_list"]. Your views are going to be fine now.

ajax.beginform inside a for loop

so I am using a foreach loop to iterate through comments. The comment section is wrapped inside "Comments" div. My function DeleteComment fetches comments again once you delete a comment and rebinds it to the control. However, after you delete a comment, anytime you try to delete another comment, the commentId of the very first deleted comment would keep getting passed to DeleteComment function instead of the passing the commentId of the comment you are trying to delete. If you refresh the page, then you can delete ONE comment again, and the same problem if you try to delete another.
<table>
<% foreach (var item in Model) { %>
<tr> <td>item.Comment </td>
<td>
<%if (HttpContext.Current.User.Identity.IsAuthenticated && item.Poster.UserName == HttpContext.Current.User.Identity.Name)
{ %>
<%using (Ajax.BeginForm("DeleteComment", "Home", new AjaxOptions {UpdateTargetId = "Comments"}))
{%>
<%=Html.Hidden("articleId", item.CarrierId) %>
<%=Html.Hidden("num_comments", (int)ViewData["num_comments"]) %>
<%=Html.Hidden("commentId", item.CommentId) %>
<input type = "submit" value = "delete" />
<%} %>
<%} %>
</td>
</tr>
<table>
For example, you delete comment with commentId 1... then you try to delete some other comment, but commentId 1 would keep getting passed. You refresh the page, problem gone... for one comment...
<div id = "Comments">
<%if ((int)ViewData["num_comments"] > 0)
{ %>
<%Html.RenderPartial("CommentsX", Model.Comments, new ViewDataDictionary{{"num_comments", ViewData["num_comments"] }}); %>
<%} %>
</div>
where CommentsX is the ascx control that contains the for loop code I posted above.
Sometimes having multiple elements on the same page with the same ids can cause funky results like you are seeing. Try making the id's unique like below:
<table>
<% int index=1;
foreach (var item in Model) { %>
<tr> <td>item.Comment </td>
<td>
<%if (HttpContext.Current.User.Identity.IsAuthenticated && item.Poster.UserName == HttpContext.Current.User.Identity.Name)
{ %>
<%using (Ajax.BeginForm("DeleteComment", "Home", new AjaxOptions {UpdateTargetId = "Comments"}))
{%>
<%=Html.Hidden("articleId" + index, item.CarrierId) %>
<%=Html.Hidden("num_comments" + index, (int)ViewData["num_comments"]) %>
<%=Html.Hidden("commentId" + index, item.CommentId) %>
<input type = "submit" value = "delete" />
<%} %>
<% index++;
} %>
</td>
</tr>
<table>

Resources