hi
I have page which is action "create" for order.
I want to be able dynamically to add multiple boxes and submit all the items as one request.
I know how to add one a time and save as ajax request but not all at once
Any Ideas how to do that?
public class oder{
public int Id{get;set;}
public string Recipient{get;set;}
public List<Box> Boxes{get;set;}
}
public class Box{
public int Id{get;set;}
public string
}
I have simplified the html code
<% html.SubmitForm(){ %>
<div><%: html.textboxfor(model=>model.Recipient) %></div>
<div class="Action">Add Box</div>
<fieldset>
<legend>Boxes</legend>
</fieldset>
<%}%>
You may find the following blog post useful.
Related
I am using Razor Pages with model binding. When my form posts, the values remain in there when the page reloads after posting. I have tried using ModelState.Clear() but this doesn't seem to do anything.
Specifically, I have an HTML form like this:
<form method="post">
<textarea asp-for="Input.Text" class="form-control" placeholder="No data"></textarea>
<button type="submit" asp-route-param="Submit">Submit</button>
</form>
and the following controller:
public class TestFormModel : PageModel
{
[BindProperty]
public InputModel Input { get; set; }
public IActionResult OnPost()
{
ModelState.Clear();
return Page();
}
}
public class InputModel
{
public string Text {get;set;}
}
On submission, the form remembers the text submitted - I want it to be cleared.
I can do this with jQuery on the client side, but I wondered if there's a RazorPages trick. ModelState.Clear() doesn't seem to do what I want.
Many thanks
Rather than return Page(), redirect to it instead:
public IActionResult OnPost()
{
return RedirectToPage("/TestForm");
}
That will force a new GET request.
Having said that, the usual pattern is to redirect to a different page if the form submission is successful rather than presenting the form again.
I addition to clearing the model state you need to also clear the bound property. like this:
public IActionResult OnPost()
{
ModelState.Clear();
Input.Text = string.Empty;
return Page();
}
I have an Object CreateProjectFormModel as follows (I am using Spring 4).
public class CreateProjectFormModel {
private Project project;
private List<DUser> users;
public CreateProjectFormModel() {
this.project = new Project();
this.users = new ArrayList<DUser>();
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
public List<DUser> getUsers() {
return users;
}
public void setUsers(List<DUser> users) {
this.users = users;
}
}
I am not able to figure out how to create Controller and a corresponding form so that multiple DUser can be submitted at once - can do it if the object does not consist of a collection?
Read this, but I don't know how may users will be added to the project in advance, so cannot fix the users size.
I read through thymeleaf tutorial, but would be interested to know if can do without use of thymeleaf.
Thanks.
The link you posted in the question List<Foo> as form backing object using spring 3 mvc, correct syntax? should provide a solution for you, what is discussed in the comments
I assume that this solution requires having a fixed amount of input
fields, is that correct? What if you have a dynamic number of input
fields?
does not concern the number of users, which doesn't have to be fixed, rather it concerns the fact that that the properties of the object is differing, which I don't believe is your case. So, if your DUser has a property userName, and e.g. your Project has a property name. Your controller method could simply be,
#RequestMapping(value = "/test", method=RequestMethod.POST)
public String processSubmit(CreateProjectFormModel createProjectFormModel) {
...
}
and your form
<form:form action="/form/test" method="post">
<div class="single">
<input type="text" name="project.name"/>
<input type="text" name="users[0].userName"/>
add another user
<input type="submit" value="Save">
</div>
</form:form>
where you will have to provide some effort is to create a javascript function addNewUserInputSection that will add new set of input fields for the users property with an incremented index, e.g.
<form:form action="/form/test" method="post">
<div class="single">
<input type="text" name="project.name"/>
<input type="text" name="users[0].userName"/>
<input type="text" name="users[1].userName"/>
add another user
<input type="submit" value="Save">
</div>
</form:form>
the examples are basic, but should be enough to have you resolve your issue
Although the above answer works, here's an alternate that does not require you to create a wrapper class/ form class.
Model And Controller
public class Foo {
private String name;
private List<Foo> fooList;
public Foo() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFooList() {
return fooList;
}
public void setFooList(String fooList) {
this.fooList = fooList;
}
}
#Controller("/")
public class FooController{
//returns the ModelAttribute fooListWrapper with the view fooForm
#RequestMapping(value = "/FOO", method = RequestMethod.GET)
public String getFooForm(Model model) {
List<Foo> fooList = service.getFooList();
model.addAttribute("fooList", fooList);
return "list_foo"; //name of the view
}
#RequestMapping(value = "/FOO", method = RequestMethod.POST)
public String postFooList(#ModelAttribute("foo")Foo foo, Model model) {
List<Foo> list = foo.getFooList(); // **This is your desired object.
//If you debug this code, you can easily find this is the list of
//all the foo objects that you wanted, provided you pass them properly.
//Check the jsp file to see one of the ways of passing such a list of objects**
//Rest of the code
}
}
JSP View
<form:form id="form" action="<paste-target-url-here>" method="POST" modelAttribute="fooList">
<c:forEach items="${fooList}" varStatus="i">
<form:input path="fooList[${i.index}].name" type="text"/>
<!-- Here you are setting the data in the appropriate index which will be caught in the controller -->
</c:forEach>
<button>submit</button>
</form:form>
I have a strongly typed mvc page which I wont to bind a unorder list to a list of objects. So in mvc view it might look something like
<% foreach (var item in Model.WhatYouDoL) { %>
<li><%: Html.Encode(item.Text) %><input type="hidden" name="WhatYouDoL[0].Reference" /></li>
<% } %>
My view model might look something like
public class ViewModelQuoteWhatYouDoInMotorTrade
{
public List<WhatYouDo> WhatYouDoL { get; set; }
}
and my list contains object like
public struct WhatYouDo
{
public decimal Percent { get; set; }
public string Reference { get; set; }
public string Text { get; set; }
}
This binds ok providing I use WhatYouDoL[0].Reference with the index ([0]) which when loading I can set with an index. The problem is I want to add and remove from this list on the client side. So I might have some js which adds and extra list item and removes the current. This means I have to somehow manage the indexes in the name and keep them in order and non duplicate on the client side. Does anyone know if there is a way to get around using the index in the name.
Thanks in advance.
There is, probably, a mistake:
<% foreach (var item in Model.WhatYouDoL) { %>
<li><%: Html.Encode(item.Text) %><input type="hidden" name="WhatYouDoL[0].Reference" /></li>
<% } %>
Maybe it should be:
<% foreach (var item in Model.WhatYouDoL) { %>
<li><%: item.Text %><input type="hidden" name="<%: item.Reference %>" /></li>
<% } %>
You don't need to encode as long as you use <: proof
Is it possible in MVC2 to create an anchor tag that contains values from ViewData?
e.g.
Send Email
This code above doesn't render and just throws an exception?
Yes it is.
Moreover the default template will render that field exactly as you wrote if you use the Display Html extensions and an associated ViewModel. Just decorate the field in the model with the right DataType attribute
[DataType(DataType.EmailAddress)]
public string EmailAddress { get; set; }
Please see this post series for further informations.
EDIT:
Suppose you have the following ViewModel
public class CustomerModel {
public string CustomerName { get; set; }
[DataType(DataType.EmailAddress)]
public string EmailAddress { get; set; }
}
and inside your Controller the following Action
[HttpGet]
public ActionResult ViewCustomer( int id ) {
CustomerModel cm = LoadCustomerByID( id );
return View( cm );
}
you can have a view named Viewcustomer.aspx that is strong typed to an instance of CustomerModel and just have this code in the view
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyApp.CustomerModel>" %>
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<%= Html.DisplayForModel() %>
</asp:Content>
Please take a coffe and get time to read that article series. It's very easy and can address more than what I am trying to write in this small post. ;)
Hope it helps!
The answer here is not as complicated as many would think.. it's simply a Quote (") problem:
Try changing your outer quotes to single quotes.. It terminates the string when you use " quotes in your markup aswell as in the ["Email"]... :)
<a href='mailto:<%: ViewData["Email"] %>'>Send Email</a>
I am playing with MVC2 in VS 2010 and am really getting to like it. In a sandbox application that I've started from scratch, my database is represented in an ADO.NET entity data model and have done much of the validation for fields in my data model using Scott Guthrie's "buddy class" approach which has worked very well.
However, in a user registration form that I have designed and am experimenting with, I'd like to add a 'confirm email address' or a 'confirm password' field. Since these fields obviously wouldn't exist in my data model, how would I validate these fields client side and server side?
I would like to implement something like 'Html.ValidationMessageFor', but these fields don't exist in the data model. Any help would be greatly appreciated.
I use view models. I don't create the data model instance to persist until the view model is valid.
Below is a simple example. Notice that some of the properties are data models, but the validation properties only exist on this view model.(the base isn't pertinent here)
public class ProblemAddToDepartmentProductView : ViewModel
{
public Problem Problem { get; set; }
public IList<Product> AllProducts { get; set; }
public IList<Department> AllDepartments { get; set; }
public string ProblemId { get; set; }
public string ProblemName { get; set; }
[DisplayName("Choose the product:")]
[Required(ErrorMessage = "Select the Product.")]
public string SelectedProduct { get; set; }
public SelectList GetProducts()
{
var selectList = new SelectList(AllProducts, "Id", "Name");
return selectList;
}
[DisplayName("Choose the department using this problem for that product:")]
[Required(ErrorMessage = "Select the Department.")]
public string SelectedDepartment { get; set; }
public SelectList GetDepartments()
{
var selectList = new SelectList(AllDepartments, "Id", "Name");
return selectList;
}
internal class ProductSelect
{
public Guid Id { get; set; }
public string Name { get; set; }
}
}
It will also help to see it wired on the page:
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%= Html.LabelFor(x => x.SelectedProduct) %>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(x => x.SelectedProduct, Model.GetProducts(),"--Select One--") %>
<%= Html.ValidationMessageFor(x => x.SelectedProduct)%>
</div>
<div class="editor-label">
<%= Html.LabelFor(x => x.SelectedDepartment) %>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(x => x.SelectedDepartment, Model.GetDepartments(),"--Select One--") %>
<%= Html.ValidationMessageFor(x => x.SelectedDepartment)%>
</div>
<p>
<input type="submit" value="Add Selected" />
</p>
</fieldset>
I also do this so the model will have these values if the validation fails, to pull back in the needed data for the drop downs:
p.ProblemId) %>
<%= Html.HiddenFor(p => p.ProblemName) %>
Client-Side:
Using Javascript Validation
and/or
Server-Side:
Validate in Controller (Using FormCollection) - or
Create "CustomViewModel" Class that encapsulates all validation strongly type your view - or
You could add two string properties to your Model. Doing so will allow you to populate an instance of your model in a Controller and validate appropriately in your Model/s...