I have a view where user can enter some data. But problem is this:
Let's say you have 3 text box on view. Every time user can fill multiple times this 3 text boxes. To clarify, let's say user fills this 3 text boxes and press button which adds on form again these 3 text boxes. Now when user clicks submit this form is sent to controller, but how do I sent List of models as parameter.
My architecture for this problem is something like this:
MyModel
public int ID { get;set; }
public string Something { get; set; }
/*This three textboxes can user set multiple times*/
/*Perhaps i Can create new model with these properties and then
/*put List of that model as property here, but how to fill that list inside view ??*/
public string TextBoxOneValue { get; set; }
public string TextBoxTwoValue { get; set; }
public string TextBoxThreeValue { get; set; }
Now, i was thinking that i Create PartialView with this 3 text boxes, and then when user clicks button on view another PartialView is loaded.
And now, let's say I have Two partial views loaded, and user clicks submit, how that I pass list with values of these 3 text boxes to controller ??
You can achieve above functionality this way :
View :-
Just add as many input fields as you want but when dynamically adding the inputs make sure they are named and indexed correctly as shown :-
<input type="text" name="[0].textdata" value="1" />
<input type="text" name="[1].textdata" value="2" />
<input type="text" name="[2].textdata" value="3" />
<input type="text" name="[3].textdata" value="4" />
..........
..........
Controller :-
Public ActionResult MyControllerAction(List<string> textdata) // here textdata will have list of posted input values.
{....}
Above shown example is with simple html input types (which is simple to implement) but if you want strongly typed textboxes and add them dynamically then see this link :- http://www.techiesweb.net/asp-net-mvc3-dynamically-added-form-fields-model-binding/
Related
I have a table in my web application, which is populated from the model, where properties have attribute for validation:
[Required(ErrorMessage = "Please enter amount!")]
[DisplayFormat(NullDisplayText = "", ApplyFormatInEditMode = true)]
public decimal? Amount { get; set; }
When I press Submit, the field is properly validated on the client, displaying an error message, if the amount is left empty.
Now the user can add new TRs to the table using jquery. The new record completely imitates the existing records, e.g. when I inspect the Amount field for an existing TR:
<input class="form-control" type="text" data-val="true" data-val-number="The field Amount must be a number." data-val-required="Please enter amount!" id="Financials_1__Amount" name="Financials[1].Amount" value="1834.09"><span class="text-danger field-validation-valid" data-valmsg-for="Financials[1].Amount" data-valmsg-replace="true"></span>
Cf. to the same field of the dynamically added TR:
<input class="form-control" type="text" data-val="true" data-val-number="The amount must be a number." data-val-required="Please enter amount!" id="Financials_77e9f261-010a-4c7c-ae50-e3f6587a8c4e__Amount" name="Financials[77e9f261-010a-4c7c-ae50-e3f6587a8c4e].Amount" value="33"><span class="text-danger field-validation-valid" data-valmsg-for="Financials[77e9f261-010a-4c7c-ae50-e3f6587a8c4e].Amount" data-valmsg-replace="true"></span>
The records look very similar. Yet when I leave the required field empty and press submit, the value is not validated on the client, and the execution comes to the controller's action method. There ModelState.IsValid is false though. This is my first issue.
Here is the action method:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(int contractorId, ContractorDetailsDto dto)
{
if (ModelState.IsValid)
{
...
}
return View(_contractorRepository.GetContractorDetailsViewModelByDto(dto));
}
As our ModelState is invalid, the same view is loaded. There the error is displayed in the validation summary, BUT NOT UNDER THE FIELD WITH THE INVALID VALUE. This is the second issue.
I have on my view:
#section Scripts {
<partial name="_ValidationScriptsPartial" />
}
How can I find the cause of my problems?
Answering for your main question. Can you try to execute next javascript code after you add new row
function refreshValidators(formSelector) {
var targetForm = $(formSelector);
targetForm.removeData('validator');
targetForm.removeData('unobtrusiveValidation');
targetForm.removeAttr('novalidate');
$.validator.unobtrusive.parse(targetForm);
}
Regarding your second problem I think you should create separate question for it as it unrelated to your main question. You need to find proper way how to add new rows in ASP.NET Core. For ASP.NET MVC we had next solution how to solve this task http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ . After googling BeginCollectionItem I found core analog solution, but it is pretty old and I didnt use it personaly.
I am a newbie to MVC3 technology and trying to workout my way get through a small problem.
I simply need to get checked checkbox values to be saved in database and on Edit view check them back.
<input type="checkbox" value="Photo" name="DocSub" /> Photograph<br />
<input type="checkbox" value="BirthCertificate" name="DocSub" /> Copy Of Birth Certificate<br />
<input type="checkbox" value="School Leaving Certificate" name="DocSub" /> School Leaving Certificate<br />
When the Submit button is clicked, the [HTTPPOST] Action method of the desired controller is called. There I receive the selected values in this form :
var selectedCheckBoxValues = Request.Form["DocSub"];
I am getting the all the checked checkbox values in comma separated form and able to store them to the database, but wondering if this is the right approach to go by.
Also I need to know to retrieve checkbox values from database on Edit view in already checked form.
the typical apporoach to these problems is to use a view with a model
ie, suppose this is view Documents.cshtml
#model DocumentViewModel
#Html.LabelFor(m => m.Photo)
#Html.CheckBoxFor( m => m.Photo )
#Html.LabelFor(m => m.BirthCertificate)
#Html.CheckBoxFor( m => m.BirthCertificate )
#Html.LabelFor(m => m.SchoolLeavingCertificate)
#Html.CheckBoxFor( m => m.SchoolLeavingCertificate )
and use a viewmodel to pass data to the view
the viewmodel is a class where you have the data your going to send to the view, ie.
public class DocumentViewModel{
public bool Photo {get;set;}
public bool BirthCertificate { get; set; }
public bool SchoolLeavingCertificate {get;set;}
}
and you'd have a controller that populates the viewmodel and calls the view
public ActionResult Documents()
{
var modelData = new DocumentViewModel();
//or retrieve from database at this point
// ie. modelData.Photo = some database value
return View(modelData);
}
[HttpPost]
public ActionResult Documents(DocumentViewModel documentsVM)
{
if (ModelState.IsValid)
{
//update the database record, save to database... (do stuff with documentsVM and the database)
return RedirectToAction("NextAction");
}
//else, if model is not valid redirect back to the view
return View(documentsVM);
}
look for tutorials out there on mvc basics. read code.
What I want to do is automatically add an image span after my input textboxes if the [Required] attribute decorates my ViewModel property be it an integer, double, string, date etc
For example, my ViewModel might look like
public class MyViewModel
{
[Required]
public string Name { get; set; }
}
and my View would look like
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
and the output would be something like
<input id="Name" class="text-box single-line" type="text" value="" name="Name" data-val-required="The Name field is required." data-val-length-max="20" data-val-length="The field Name must be a string with a maximum length of 20." data-val="true">
<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="Name"></span>
-- Note the automatically added span
<span class="indicator required" style="width: 11px;"></span>
I was intending to have some css that would show the image i.e.
span.required {
background-image: url("required.png");
}
Is this possible to do or do I need to create my own Helper method to implement this type of functionality?
Yes, it's possible, but in general I wouldn't recommend it, because templates are really there to customize type rendering, and you should be able to create templates without worrying if it overrides another template.
I would instead create a custom LabelFor helper, such as the one described here:
http://weblogs.asp.net/imranbaloch/archive/2010/07/03/asp-net-mvc-labelfor-helper-with-htmlattributes.aspx
or here:
http://weblogs.asp.net/raduenuca/archive/2011/02/17/asp-net-mvc-display-visual-hints-for-the-required-fields-in-your-model.aspx
A third option is to not do anything in MVC, but rather add some javascript that will add the indicator based on the standard MVC validation data attributes (if you're using unobtrusive validation). See the answer here:
https://stackoverflow.com/a/8524547/61164
What I did was to modify the jquery.validate.unobtrusive JS file to add a second container, specifically for your images, if there is a validation error.
var container2 = $(this).find("[data-valimg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
replace = $.parseJSON(container.attr("data-valimg-replace")) !== false;
container2.removeClass("img-validation-valid").addClass("img-validation-error");
Then don't forget to bind it to the model:
error.data("unobtrusiveContainer", container2);
Finally, empty it in the if (replace) code block:
if (replace) {
container.empty();
container2.empty();
error.removeClass("input-validation-error").appendTo(container);
}
else {
error.hide();
}
On success, remember to hide it:
var container2 = error.data("unobtrusiveContainer"),
replace = $.parseJSON(container.attr("data-valimg-replace"));
if (container2) {
container2.addClass("img-validation-valid").removeClass("img-validation-error");
error.removeData("unobtrusiveContainer");
if (replace) {
container2.empty();
}
}
If you take a look at the onError and onSuccess functions in the file, you should be able to find out where you can put them in.
In your view, add the following line of code to each form input there's validation for:
<img class="img-validation-valid" data-valimg-replace="true" data-valimg-for="<replace with field name here, ie. Name>" src="required.png" />
I've only tested this with the [Required] attribute, but it works. I'm also pretty sure you can use this for generating other stuff as well, not just images.
I'd like to create a datatable where each cell is clickable. I'm assuming that I can probably fill each cell with apex:outputlink and that takes care of the clickable part as well as calling my controller for each click. The big question I need an answer for is how do I pass information to my apex controller about which cell (i.e.: which row and which column) was actually clicked.
Any help for this is highly appreciated.
Its easy. Just define an action function to catch the values from the dataTable:
1) First defining three vars tht we will pass to controller: raw-id, cell-value, cell-type
public String clickedRowId { get; set; }
public String clickedCellValue { get; set; }
public String clickedCellType { get; set; }
public PageReference readCellMethod(){
System.debug('#### clickedRowId: ' + clickedRowId);
System.debug('#### clickedCellValue: ' + clickedCellValue);
System.debug('#### clickedCellType: ' + clickedCellType);
return null;
}
2) Second we create an action function, that calls our apex method an pass three vars to it:
<apex:actionFunction name="readCell" action="{!readCellMethod}">
<apex:param name="P1" value="" assignTo="{!clickedRowId}"/>
<apex:param name="P2" value="" assignTo="{!clickedCellValue}"/>
<apex:param name="P3" value="" assignTo="{!clickedCellType}"/>
</apex:actionFunction>
3) And third we create our dataTable, where each cell has onClick listener:
<apex:pageBlockTable value="{!someArray}" var="item">
<apex:column value="{!item.name}" onclick="readCell('{!item.id}','{!item.name}','name')" />
<apex:column value="{!item.CustomField1__c}" onclick="readCell('{!item.id}','{!item.CustomField1__c}','custom1')" />
<apex:column value="{!item.CustomField2__c}" onclick="readCell('{!item.id}','{!item.CustomField2__c}','custom2')" />
</apex:pageBlockTable>
We can access our actionFunction like any other JavaScript function. If user clicks on the cell - three vars will be send to the actionFunction and then to controller.
I am new to mvc and would like to add an additional field to my registration page that is simply a dropdownlist bound to a table in my model (a table of organization names and IDs). However, in my default application I see that the AccountController is using the RegisterModel model to create the register form view. This is fine, I don't want to disturb this. But I want to add a new select box on the page bound to a different model (my model with the organizations). How do I accomplish this?
I've found other posts that suggest I create a wrapper model for both my model and the RegisterModel, but this isn't working. My wrapper model looks like this:
public class RegisterPeopleModel
{
public RegisterModel reg { get; set; }
public fwfEntities fwf { get; set; }
}
And now the field validator for password is no longer working. The code in the view:
<div class="editor-field">
#Html.PasswordFor(m => m.reg.ConfirmPassword)
#Html.ValidationMessageFor(m => m.reg.ConfirmPassword)
</div>
Now renders this:
<div class="editor-field">
<input data-val="true" data-val-equalto="The password and confirmation password do not match." data-val-equalto-other="*.Password" id="reg_ConfirmPassword" name="reg.ConfirmPassword" type="password" />
<span class="field-validation-valid" data-valmsg-for="reg.ConfirmPassword" data-valmsg-replace="true"></span>
</div>
Notice that the IDs of the span and input no longer match. The form no longer works at all. This is leading me to believe I'm taking the wrong approach. Is there a better way of getting my select list on the page bound to a different model?
Thanks in advance.
Is there a better way of getting my select list on the page bound to a
different model?
If the model doesn't meet the requirements of the view you should modify this model. In ASP.NET MVC it is a good practice to design view models and pass only view models to views and not domain models (like for example EF autogenerated classes which is what this fwfEntities type seem to be). So design a view model which contains only the properties needed by your view and have your controller action query the database in order to fetch the model then map the model to a view model and finally pass this view model to the view.
Without seeing RegisterModel my guess is that ConfirmPassword has not got a required attribute for example;
[Required(ErrorMessage = "A password is required")]
public string ConfirmPassword { get; set; }
oh I believe the period in the id is replaced with an underscore so as not to cause issues with Jquery.