I'm studying ASP MVC, and developping SportsStore (Create/Edit feature). When Create a product, Create action will view a Edit view, but when press Sudmit, it call action Create (Post), althrough I will set it call Edit action:
<% using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype="multipart/form-data" }))
{%>
<%--<%= Html.ValidationSummary() %>--%>
<%--<%= Html.Hidden("ProductID") %>--%>
<p>Name: <%= Html.TextBox("Name")%>
<div><%= Html.ValidationMessage("Name")%></div>
</p>
<p>Description: <%= Html.TextArea("Description", null, 4, 20, null)%>
<div><%= Html.ValidationMessage("Description")%></div>
</p>
<p>Price: <%= Html.TextBox("Price")%>
<div><%= Html.ValidationMessage("Price")%></div>
</p>
<p>Category: <%= Html.TextBox("Category")%>
<div><%= Html.ValidationMessage("Category")%></div>
</p>
<p>
Image:
<% if (Model.ImageData == null)
{ %>
None
<% }
else
{ %>
<img src= "<%= Url.Action("GetImage", "Products", new {Model.ProductID}) %>" />
<% } %>
<div>Upload new image: <input type="file" name="file" id="file" /></div>
</p>
<input type="submit" value="Save" />
<%= Html.ActionLink("Cancel and return to list", "Index")%>
<% } %>
Please help me fix it
The code you have seems reasonable if you want it to post back to the Edit action. Your question is a bit confusing, but I'm going to assume that you want to reuse the view and have it post back to Create when rendered from Create and Edit when rendered from Edit. The easiest way is to simply omit the parameters from the BeginForm call. This will cause the form action to be set to the current controller and action, which would give you what you seem to want. An alternative would be to develop templates (display/editor) for the model but have separate views for Create/Edit that simply render the template Html.EditorFor( m => m, "ProductTemplate" ). This would allow you to customize the view -- perhaps the Create view requires you to upload an image? -- yet still reuse most of the code.
Related
I am building an index for one of my models. Instead of the usual table, I want to have two combo-boxes: one for selecting the object, the other for selecting the method (either edit or destroy). Upon clicking the submit button, I should be redirected to the appropriate method reference (e.g. admin_users/1/edit or admin_users/17/destroy). I have written a helper that constructs the url reference, but for some reason it does not work. when I use button_to I get redirected to the create method, when I use button_tag nothing works. Any ideas?
view code:
<%= form_tag do %>
<p id="notice"><%= flash[:notice] %></p>
<h1>Listing admin_users</h1>
<p><strong>select admin user</strong></p>
<%= select_tag(#req_id, options_from_collection_for_select(#admin_users, :id, :login)) %>
<br/>
<p><strong>select action</strong></p>
<%= select_tag(#oper, options_for_select([['edit'],['destroy']])) %>
<br/>
<%=button_tag 'go go!', get_path(#req_id,#oper) %>
<% end %>
helper code:
module AdminUsersHelper
def get_path(req_id,oper)
a=[req_id, oper].join("/")
["admin_users", a].join("/")
end
end
The default method for a form submit is POST. You'll need to change the method accordingly.
<%= form_tag( '/users/confirm', method: :get ) %>
May I suggest submitting with Javascript? You'll have a more dynamic control over the method of the submission. Take a look Here
so, eventually I went on the javascript solution, just as #Hassanin Ahmed suggested. Thanks for Helping!
<%= form_tag('/admin_users', id: "admin_users_menu") do %>
[...]
<font size=4>
<u>select user:</u>
</font>
<br>
<br>
<select id="admin_user_id" name="admin_user[id]">
<%= options_for_select #admin_users.collect{|user| [user.login, user.id]} %>
</select>
<br>
<br>
<font size=4> <u>select option:</u></font><br><br>
<input type="radio" checked name="select_op" value= "edit" > edit
<br>
<br>
<input type="radio" name="select_op" value= "delete" > delete
<br>
<br>
<%= submit_tag "go" %>
<br>
<br>
<% end %>
<script>
$(function (){
$("#admin_users_menu").submit(function() {return direct_me() })
})
function direct_me(){
//getting the admin_user id
var au_id=$('select').val()
//getting the desired method
var op=$('input[name=select_op]:radio:checked').val()
//making the default url
var u="admin_users/"+au_id
var f=$("form")
if(op=='edit'){
u=u+"/edit"
f.attr("method","GET")
}
else if(op=='delete'){
f.attr("method","POST")
f.append("<input type='hidden' name='_method' value='delete'>");
}
f.attr("action",u)
if(op=='delete') return confirm("Are you sure?")
}
</script>
I created a form in asp.net and now I need to add a validation to it, so if any of the fields has been populated and user will try to leave the page, the pop-up will appear asking "Do you want to exit without saving?". Is there a simple way I can to this?
<% using (Html.BeginForm("Create", "Damages", FormMethod.Post))
{%>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%=Html.LabelFor(model => model.OrderId)%>
</div>
<div class="editor-field">
<%= Model.OrderId%>
</div>
....
<%=Html.HiddenFor(model => model.Id)%>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
You can use the onbeforeunload event:
<script>
window.onbeforeunload = function() {
if( isDirty ) {
return 'Do you want to exit without saving?';
}
}
</script>
Of course you need to keep track of form field changes and set the isDirty flag accordingly.
https://developer.mozilla.org/en-US/docs/Web/API/Window.onbeforeunload
http://msdn.microsoft.com/en-us/library/ie/ms536907%28v=vs.85%29.aspx
Having a little trouble and wondered if anyone could help :-)
I am trying to pass the value that a user enters into a html.Textboxfor to an html.Action link.
As shown below :
<%=Html.TextBoxFor(m => m.OrderQty)%>
<p class="button" >
<%: Html.ActionLink("Add to cart",
"AddToCart",
"ShoppingCart",
new { id = Model.Product.ProductId, Qty = Model.OrderQty }, "")%>
</p>
But when i put a breakpoint in the AddToCart Qty is always 0 :-(
Does anyone have any ideas ?
Thanks
John
I would recommend you using a form instead of an action link. This way the value entered in the textbox will be automatically sent to the server and you don't have to worry about javascript:
<% using (Html.BeginForm("AddToCart", "ShoppingCart",
new { id = Model.Product.ProductId, Qty = Model.OrderQty },
FormMethod.Get)) { %>
<%= Html.TextBoxFor(m => m.OrderQty) %>
<input type="submit" value="Add to cart" />
<% } %>
I am building a .NET MVC app that has a page with a list of delete buttons, one for each item in a list. The problem I'm having is that the foreach variable "item" is not visible inside the LoginView, which results in the following error:
Compiler Error Message: CS0103: The name 'item' does not exist in the current context
Below is a simplified version of the view. The error occurs at the "new {id=item.Id}" in the LoggedInTemplate - the reference to "item" in the ActionLink works fine:
<% foreach (var item in Model) { %>
<%= Html.ActionLink("Item", "Details", new { id = item.Id })%>
<asp:LoginView runat="server">
<LoggedInTemplate>
<% using( Html.BeginForm( "Delete", "Items", new {id=item.Id}, FormMethod.Post))
{ %>
<input type="submit" value="Delete" runat="server" />
<% } %>
</LoggedInTemplate>
</asp:LoginView>
<% } %>
To clarify the problem is not that the Model has not been successfully passed to the View. The Model is visible from both inside and outside the LoginView. The foreach loop as no problem in iterating through the items in the Model (which is a List). The problem is that the iteration variable "item" is not accessible from within the LoginView - though the original Model is.
Is there any way to pass "item" through to the LoginView's templates? Or is building LoginViews within a foreach loops the wrong way of doing things?
Is there a scoping rule that prevents using local variables within controls - perhaps because the control is rendered at a different time to the main page?
With ASP.NET MVC you really shouldn't use user/custom controls, so if you omit the <asp:LoginView/> and write a line of code to check if the user is authenticated, you are good to go.
Instead of your current code:
<asp:LoginView runat="server">
<LoggedInTemplate>
<div>Show this to authenticated users only</div>
</LoggedInTemplate>
</asp:LoginView>
Just use an if-statement and the value of Request.IsAuthenticated:
<% if (Request.IsAuthenticated) { %>
<div>Show this to authenticated users only</div>
<% } %>
Are you passing the Model to the view and are you also inheriting from the model within that view?
So if this is a View then in your C# code you need to return the list of items like return View(listofitems);
If this is a partial view then <% Html.RenderPartial("MyPartial", listofitems) %>
And in the view you need to
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IQueryable<ListOfItems>>" %>
If all that is in place then it should work no probs.
<% foreach (var item in Model) { %>
<%= Html.ActionLink("Item", "Details", new { id = item.Id })%>
<%= if( Request.IsAuthenticated ) {
using( Html.BeginForm( "Delete", "Items", new {id=item.Id}, FormMethod.Post))
{ %>
<input type="submit" value="Delete" runat="server" />
}
} %>
<% } %>
There is no need to use the LoginView, its not really giving you anything. Use something like the above instead.
Alternatively, you can move the decision of whether to show the delete option for the specific item into the controller, so instead of doing if( Request.IsAuthenticated ) you would do if( item.ShowDelete ) ... assuming item's type is a view model. Another option is to use an extension method for the same, item.ShowDelete(). I prefer the earlier, because there might be logic associated to deciding whether to show delete for a given item, so its better to not have it in the controller or a related logic.
I have a view where the user can change some settings, its basically a "edit" page. When the user checks a particular value in a radio group i set a hidden field (its a invisible input type=text field), but when i load the page i want that hidden field set from my code. How to do this? JQuery? or can i "findControl" somehow?
This is the "hidden" field:
<div style="display: none">
<input type="text" name="HiddenImageId" id="HiddenImageId" value="" />
</div>
The above hidden field is set from a jquery that executes when a radio-button is clicked. But when I load in "edit" mode I want myself to set the "hidden" field.
Further down my view i load all the radio-buttons:
<% if (file.Id == imageFile.Id)
{ %>
<input type="radio" checked="checked" name="filename" class="filename" id="<%= file.Id.ToString()%>" />
<% }
else
{ %>
<input type="radio" name="filename" class="filename" id="<%= file.Id.ToString()%>" />
<%} %>
When I set the checked attribute I want to set the value of my hidden fiddle to the files ID.
You would probably benefit a lot from making better use of the [Html Helpers] in ASP.NET MVC.
You could, for example, output your "hidden" text input like this:
<%= Html.TextBox("HiddenImageId", imageFile.Id) %>
If imageFile can be null, you might want to add a check for that - use shorthand if to make it look nice:
<%= Html.TextBox("HiddenImageId", imageFile != null ? imageFile.Id : "") %>
You could also probably improve your code for the radiobuttons significantly by using Html.RadioButton...
just like you are doing
id="<%= file.Id.ToString()%>"
you can do
<input type="text" name="HiddenImageId" id="HiddenImageId" value="<%= file.Id.ToString()%>" />
or whatever the code is to get your value
I'd suggest using the HtmlHelper extensions in both cases.
<div style="display: none">
<%= Html.TextBox( "HiddenImageId",
file.Id == imageFile.Id ? file.Id.ToString() : "" ) %>
</div>
<%= Html.RadioButton( "filename",
"",
file.Id == imageFile.Id,
new { #class = "filename", id = file.Id.ToString() } ) %>
or if you wanted to use a hidden input instead, skip the invisible DIV, and use
<%= Html.Hidden( "HiddenImageId",
file.Id == imageFile.Id ? file.Id.ToString() : "" ) %>