Duplicate input ids when using multiple partials in ASP.NET MVC - asp.net-mvc-3

I have three partial views that are each strongly typed with separate models. Each view contains it's own form and submits to different actions. Some of the models contain properties with the same names and when I use the html helper methods to create the textboxes and labels, I'm ending up with duplicate html ids on the page.
Partial _Residential View
#model MyProject.Models.ResidentialModel
#using (Html.BeginForm("Residential", "Transaction"))
{
#Html.LabelFor(m => m.PersonName)
#Html.TextBoxFor(m => m.PersonName)
#Html.LabelFor(m => m.ReferenceNumber)
#Html.LabelForm(m => m.ReferenceNumber)
<input type="submit" value="Submit" />
}
Partial _Business View
#model MyProject.Models.BusinessModel
#using (Html.BeginForm("Business", "Transaction"))
{
#Html.LabelFor(m => m.BusinessName)
#Html.TextBoxFor(m => m.BusinessName)
#Html.LabelFor(m => m.ReferenceNumber)
#Html.LabelForm(m => m.ReferenceNumber)
<input type="submit" value="Submit" />
}
Normal View
<h2>Residential Transaction</h2>
#Html.Partial("_Residential")
<h2>Business Transaction</h2>
#Html.Partial("_Business")
The output that I'm getting looks like the following:
<h2>Residential Transaction</h2>
<form action="/Transaction/Residential" method="post">
<label for="PersonName">Person Name:</label>
<input type="text id="PersonName" name="PersonName" />
<label for="ReferenceNumber">Reference Number:</label>
<input type="text" id="ReferenceNumber" name="ReferenceNumber" />
<input type="submit" value="Submit" />
</form>
<h2>Business Transaction</h2>
<form action="/Transaction/Business" method="post">
<label for="BusinessName">Business Name:</label>
<input type="text" id="BusinessName" name="BusinessName" />
<label for="ReferenceNumber">Reference Number:</label>
<input type="text" id="ReferenceNumber" name="ReferenceNumber" />
<input type="submit" value="Submit" />
</form>
Since ReferenceNumber is in both models, I'm getting a duplicate id on the page. I figured out that i can pass an extra htmlAttributes parameter to TextBoxFor to change the id.
#Html.TextBoxFor(m => m.ReferenceNumber, new { id = "ResidentialReferenceNumber" })
...
#Html.TextBoxFor(m => m.ReferenceNumber, new { id = "BusinessReferenceNumber" })
This fixes the ids on the inputs but the 'for' attribute on the labels still has the wrong value. I looked through the various overloads for LabelFor() and unlike the TextBoxFor, there isn't an htmlAttributes property. Is there some way that I can tell model or view to use a different id for these fields?

MVC helpers do not take into account that you can have multiple models in a view. All properties that have the same name will get duplicate values (one value per model).
That is, if ResidentalTransaction and BusinessModel has a Name property, your html form will have two <input type="text" name="Name" /> fields.
I'm unsure of how it works if you add all models to the same viewmodel and use Html.TextBoxFor(m => m.ResidentalTransaction.Id);

Related

Laravel - Redirect users back to another form with all data intact, on clicking Previous button

I have two forms as below
Form 1
<form id="form1" action="loc1" method="post">
<div class="form-group">
<label for="exampleDOB">Date of Brth:</label>
<input type="text" class="form-control" id="dob" name="dob" placeholder="Date of Birth"
value="{{$tuser->DOB ?? ''}}" >
<div class="error text-danger"></div>
</div>
<button type="submit">Next Step</button><br><br>
<button type="button">Previous </button>
</form>
Form 2
<form id="form2" action="loc2" method="post">
<div class="form-group">
<label for="exampleMob">Mobile Number:</label>
<input type="text" class="form-control" id="mobno" name="mobno" placeholder="Valid Mobile
Number" value="{{$tuser->mobno ?? ''}}" >
<div class="error text-danger"></div>
</div>
<button type="submit">Final Step</button><br><br>
<button type="button">Previous </button>
</form>
$tuser is an object containing all the data for that user, from the database
When users click on Next Step in Form 1, the data is stored in database and the user is directed to Form 2.
But the problem is- on clicking the Previous button, I am losing all the pre-filled data in the Previous form. How can I retain form data (to be shown in the input fields as available in the database)?
if you have saved them in DB, so you can retrieve all of it using an id and store it in session like:
session->put("form_1_id",$DBInsertedId);
in form 1 you can check if there are any results, you can retrieve it like:
if(session->has("form_1_id"))
return view('form_1',['filled_data' => Model::find(session->get("form_1_id")) ]);
and in the view you can check for parameter existence form_1_id like you did:
<input type="text" class="form-control" id="dob" name="dob" placeholder="Date of Birth"
value="{{$filled_data->DOB ?? ''}}" >
just add a filled name id in your input view and fill it if form has been filled out before. since doing this can assure you that the filled form will be updated if there was a record for it before:
<input type="hidden" id="id" name="id" value="{{$filled_data->id ?? ''}}" >
and in your controller:
Model::insertOrUpdate(['id' => $request->id ], ... );
UPDATE:
insertOrUpdate Equivalent in psudo-code :
if(DB::exist(['id' => $request->id]))
update(['id' => $request->id , ... ]);
else
insert([ ... ]);

MVC 3 Format Validation Messages

I am working with a form layout that has 4 input fields per row so I need to find a different way to display the validation messages. I was thinking I could display any messages above the form but would like to add a border and a background color.
I am using unobtrusive JS for validation.
Is there a way to detect if there are validation errors from the view?
Example
#using (Ajax.BeginForm("ProcessContactInfo", ajaxOpts))
{
#Html.ValidationSummary(true)
if (!ViewData.ModelState.IsValid)//does nothing because using unobtrusiveJS validation
{
<div id="ValidationResultsArea" style="padding:20px; border: 1px solid #000000; background-color: #ffffcc; display: none" >
#Html.ValidationMessageFor(model => model.Contact.FirstName)<br />
#Html.ValidationMessageFor(model => model.Contact.LastName)<br />
#Html.ValidationMessageFor(model => model.Contact.Email)<br />
#Html.ValidationMessageFor(model => model.Contact.Message)<br />
</div>
}
<p><span class="required">* All fields are required.</span></p>
}
Looks like you are looking for something similar to this....
If that is what you are looking for, then you can easily achieve it if you are using MVC3 and jquery validation. jQuery validation uses custom data attributes, css and unobtrusive javascript to perform user input validation, so when validation fails for a specific input field, jQuery "injects" data attributes and css classes, then you can take advantage of this by using css to define how you want to the fields to look like. Here's the HTML belonging to the screenshot above...
<div class="editor-label">
<label for="UserName" style="display: none;">User name</label>
</div>
<div class="editor-field">
<span class="field-validation-error" data-valmsg-for="UserName" data-valmsg-replace="true">The User name field is required.</span>
<input class="input-validation-error" data-val="true" data-val-required="The User name field is required." id="UserName" name="UserName" placeholder="Username" type="text" value="">
</div>
<div class="editor-label">
<label for="Password" style="display: none;">Password</label>
</div>
<div class="editor-field">
<span class="field-validation-error" data-valmsg-for="Password" data-valmsg-replace="true">The Password field is required.</span>
<input class="input-validation-error" data-val="true" data-val-required="The Password field is required." id="Password" name="Password" placeholder="Password" type="password">
</div>
<div class="editor-label">
<input data-val="true" data-val-required="The Remember me? field is required." id="RememberMe" name="RememberMe" type="checkbox" value="true"><input name="RememberMe" type="hidden" value="false"> Remember Me
</div>
<p>
<input type="submit" value="Log On">
</p>
You can see that jQuery Validation framework added a class (input-validation-error) to the Username input field. You can specify override this css class in your project.

How can I submit ASP,NET MVC listbox selections outside of the html form?

I have a basic ASP.NET MVC3 view like this:
#Html.Label("Administrative Options");
<br />
#Html.ListBoxFor(m => m.SelectedUsers, Model.Users)
<br />
using (Html.BeginForm("AssignAdmins", "Account"))
{
<div id="MakeAdminsbtn">
<input id="MakeAdmins" type="submit" value="Assign Administrators" onclick="return confirm('Are you sure you want to Admin?');" />
</div>
}
<br />
using (Html.BeginForm("RevokeAdmins", "Account"))
{
<div id="RemAdminsbtn">
<input id="RemAdmins" type="submit" value="Revoke Administrators" onclick="return confirm('Are you sure you want to De-Admin?');" />
</div>
}
<br />
using (Html.BeginForm("DeleteAccounts", "Account"))
{
<div id="DelAcctbtn">
<input id="DelAcct" type="submit" value="Delete Accounts" onclick="return confirm('Are you sure you want to Delete?');" />
</div>
}
Each button is in it's own form because I think that's what I have to do in order to submit to different actions?
The problem I'm having is that the returned model does not contain the SelectedUsers from the ListBoxFor unless that statement is inside the form used by the submit button.
How can I get the model appropriately populated with the selected users for each of the given submit options while only displaying a single ListBox?
You could use only one ActionMethod and there base on witch button is clicked to call that action that you nead example:
#using (Html.BeginForm("Index", "Home"))
{
<div>
#Html.ListBoxFor(m => m.SelectedUsers, Model.Users)
<input id="MakeAdmins" type="submit" name="btnSubmit" value="Assign Administrators" onclick="return confirm('Are you sure you want to Admin?');" />
<input id="RemAdmins" type="submit" name="btnSubmit" value="Revoke Administrators" onclick="return confirm('Are you sure you want to De-Admin?');" />
<input id="DelAcct" type="submit" name="btnSubmit" value="Delete Accounts" onclick="return confirm('Are you sure you want to Delete?');" />
</div>
}
and then in your controller
[HttpPost]
public ActionResult Index(string btnSubmit, FormCollection collection)
{
//btnSubmit this is the button that is clicked.
return View();
}
Sorry for my bad English.

MVC (in SItefinity)

In my View I have something like:
#model CreatorModel
<form name="myForm" action="/Creator/CreateAction" enctype="multipart/form-data" id="myForm" method="post">
<div class="a">
<h2 class="a">....</h2>
<div class="b">
<br />
Select a file for a <input type="file" name="aFile" id="aFile" />
<br /><br />
Select a file for b<input type="file" name="bFile" id="bFile" />
<br /><br />
<input type="submit" id="CreateAction" name="CreateAction" value="CreateAction" />
</div>
</form>
But I have an error : File /Creator/CreateAction is not found (CreateAction is an action from CreatorController)
What can I enter as action in <form...> in order to find action from controller?
When I'm using this syntax:
#using (Html.BeginForm("FileUpload", "Board", FormMethod.Post, new { enctype = "multipart/form-data" })) { <input type="file" /> <input type="submit" /> }
I also have an error: A reference is not set to an instance of an object"
Maybe there is a bad routing?
when using MVC widgets in Hybrid mode (on a webforms template) you need to use a special version of BeginForm (because webforms only allows one form on the page).
#Html.BeginSitefinityForm()
should be the form you use to define a form area in your widget. Replace the regular one with that and the widget should work as expected.
I hope this is helpful!

Submit Button with multiple fieldsets on one view

I have a view that has the ultimate aim of being a user creation form. It is structured in the following way:
<fieldset>
#Html.DropDownList("first dropdown")
</fieldset>
<fieldset id="exists">
#Html.DropDownList("seconddropdown")
#Html.DropDownList("third dropdown")
#Html.DropDownList("fourth dropdown")
<input type="submit" value="Create User"/>
</fieldset>
<fieldset id="new">
#Html.DropDownList("dropdown")
#Html.DropDownList("dropdown")
#Html.DropDownList("dropdown")
<input type="submit" value="Create User"/>
</fieldset>
<script>
//script here shows and hides fieldsets depending on value chosen in first dropdown
</script>
Depening on the value chosen in the first dropdown, either fieldset exist or fieldset new will show. they both interact with the database differently so I really need to be able to handle the submit action separately for each. I have tried creating a submit within each fieldset, but the controller action is never hit.
I am obviously missing the mark with MVC submit buttons so could anyone help me understand how these work and how to create multiple (and separate) submit possibilities on one view.
Many thanks
You could have two forms, each that post to a different action...the submit will then only submit the form values in that form...
e.g.
#using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
<fieldset id="exists">
#Html.DropDownList("seconddropdown")
#Html.DropDownList("third dropdown")
#Html.DropDownList("fourth dropdown")
<input type="submit" value="Log in"/>
</fieldset>
}
#using (Html.BeginForm("Create", "Account", FormMethod.Post))
{
<fieldset id="new">
#Html.DropDownList("dropdown")
#Html.DropDownList("dropdown")
#Html.DropDownList("dropdown")
<input type="submit" value="Create"/>
</fieldset>
}

Resources