How do I disable my #Html.ListBoxFor() - asp.net-mvc

I need to be able to disable this ListBoxFor() depending on the Review status. Although the code below works it shows all list items.
#Html.ListBoxFor(m => m.ListOptions, filetypes, Model.IsUnderReview ? new { #class = "disabled" } : new { #class = "multiselectFileTypes" })
What would be the syntax to disable it but just so it shows '2 items selected'?

You cannot do inline condition checking for the htmlAttributes parameter.
This should work.
#using (Html.BeginForm())
{
<label>Select something </label>
if (!Model.IsUnderReview )
{
#Html.ListBoxFor(m => m.ListOptions, filetypes, new { #class = "multiselectFileTypes"})
}
else
{
#Html.ListBoxFor(m => m.ListOptions, filetypes, new { disabled = "disabled" })
}
}

It seems the answer is to use the Html.helper command HiddenFor(), like this
#if (Model.IsUnderReview)
{
//You then need to generate a hidden input for each value in SelectedRoles, as it's an array
#Html.HiddenFor(m => m.SelectedRoles)
}
else
{
#Html.ListBoxFor(x => x.SelectedRoles, filetypes, new { #class = "multiselectFileTypes" , id = "staticFieldM_" + Model.ID})
}
By creating a hidden input for each SelectedRole item you then disable the whole list.

Related

ASP.NET MVC EntityFramework How to Save New Object along with Multiple Child Objects in Create

I'm using the database first method. I have a single form where data is entered. From this, a new "form entry", a new customer and 3 new addresses will be created. 2 addresses are associated with the customer, 1 address is associated with the form entry as a whole, and the customer is associated with the form entry.
The question (revision 2):
How does one usually go about preparing fields that reference objects that will be created simultaneously -- "hey, these id fields right here will reference objects created simultaneously from the same, current dataset you're being built from"?
(
i.e. How would one normally do something like the following in MVC:
1) create each of the 3 addresses as new addresses;
2) associate 2 of them with a new customer via checkoutForm.Customer.HomeAddressId and checkoutForm.Customer.MailingAddressId;
3) associate the other with checkoutForm.PlaceOfUseAddressId itself;
4) save the customer; then
5) associate the customer with checkoutForm.CustomerId; and, finally
6) save the checkoutForm itself,
while not making ModelState.IsValid false in the meantime because checkoutForm.CustomerId and each x.AddressId are required but are initially null?
)
Any references to something that explains a procedure for simultaneously creating multiple dependent objects like this would be fantastic!
Edit: I removed the bind attribute from the parameter for Create(), and that makes all the data pull into the correct fields. The dropdownlists are properly grabbing their respective StateId.
Currently, ModelState.IsValid reports false on submit. The required ids of the child objects are null and such (which makes sense, because that's what I'm trying to figure out how to tell .NET -- here's an object association that will be created once we have the data).
Edit2: I refined the question yet again, now that I'm getting closer to what I actually need to fix: ModelState.IsValid == false, because the pertinent ids for checkoutForm and Customer that reference dependencies are null.
Depiction of the model behind this form:
Here's the form itself:
( Note the 2 dropdownlists. Everything else is a textbox for strings, ints, or dates. )
What I have for the controller so far (not much beyond what the scaffolding created):
// GET: CheckoutForms/Create
public ActionResult Create()
{
ViewBag.HomeStateList = new SelectList(db.RT_STATE_LIST, "ST_SEQ", "ST_ABBR", 2);
ViewBag.MailingStateList = new SelectList(db.RT_STATE_LIST, "ST_SEQ", "ST_ABBR", 2);
return View();
}
// POST: CheckoutForms/Create
[HttpPost]
[ValidateAntiForgeryToken]
// public ActionResult Create([Bind(Include = "Customer.FirstName,Customer.LastName,VacuumNumber,Customer.Phone,Customer.DriversLicense,Customer.HomeAddress.Street,Customer.HomeAddress.City,Customer.HomeAddress.StateId,Customer.MailingAddress.Street,Customer.MailingAddress.City,Customer.MailingAddress.StateId,Customer.MailingAddress.PostalCode,PlaceOfUseAddress.Street,PlaceOfUseAddress.City,PlaceOfUseAddress.StateId,PickupDate,DueDate,ReturnedDate,EnteredBy,EnteredDate,ModifiedBy,ModifiedDate")] CheckoutForm checkoutForm)
public ActionResult Create(CheckoutForm checkoutForm)
{
if (ModelState.IsValid)
{
checkoutForm.PlaceOfUseAddress.StateId = 1;
// !!! Need to be given correct value once authorization is set up.
checkoutForm.EnteredBy = -1;
checkoutForm.ModifiedBy = -1;
checkoutForm.EnteredDate = System.DateTime.Now;
checkoutForm.ModifiedDate = System.DateTime.Now;
// ??? db.Addresses.Add(checkoutForm.PlaceOfUseAddress);
// ??? db.Addresses.Add(checkoutForm.Customer.HomeAddress);
// ??? db.Addresses.Add(checkoutForm.Customer.MailingAddress);
// ??? db.SaveChanges();
// ??? checkoutForm.PlaceOfUseAddressId = checkoutForm.PlaceOfUseAddress.AddressId;
// ??? checkoutForm.Customer.HomeAddressId = checkoutForm.Customer.HomeAddress.AddressId;
// ??? checkoutForm.Customer.MailingAddressId = checkoutForm.Customer.MailingAddress.AddressId;
// ??? db.Customers.Add(checkoutForm.Customer);
// ??? db.SaveChanges();
db.CheckoutForms.Add(checkoutForm);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.HomeStateList = new SelectList(db.RT_STATE_LIST, "ST_SEQ", "ST_ABBR", checkoutForm.Customer.HomeAddress.StateId);
ViewBag.MailingStateList = new SelectList(db.RT_STATE_LIST, "ST_SEQ", "ST_ABBR", checkoutForm.Customer.MailingAddress.StateId);
return View(checkoutForm);
}
Finally, here are the form elements from the view (with everything else stripped out:
#using (Html.BeginForm())
{
#Html.HiddenFor(model => model.CustomerId)
#Html.HiddenFor(model => model.PlaceOfUseAddressId)
#Html.HiddenFor(model => model.Customer.HomeAddressId)
#Html.HiddenFor(model => model.Customer.MailingAddressId)
#Html.HiddenFor(model => model.EnteredBy)
#Html.HiddenFor(model => model.EnteredDate)
#Html.HiddenFor(model => model.ModifiedBy)
#Html.HiddenFor(model => model.ModifiedDate)
<!-- Name and Vacuum Number -->
#Html.EditorFor(model => model.Customer.FirstName, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.EditorFor(model => model.Customer.LastName, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.EditorFor(model => model.VacuumNumber, new { htmlAttributes = new { #class = "form-control checkout" } })
<!-- Driver's License -->
<!-- Phone Number -->
#Html.EditorFor(model => model.Customer.Phone, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.EditorFor(model => model.Customer.DriversLicense, new { htmlAttributes = new { #class = "form-control checkout" } })
<!-- Place of Use Address -->
#Html.EditorFor(model => model.PlaceOfUseAddress.Street, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.EditorFor(model => model.PlaceOfUseAddress.City, new { htmlAttributes = new { #class = "form-control checkout" } })
<!-- Customer's Home Address -->
#Html.EditorFor(model => model.Customer.HomeAddress.Street, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.EditorFor(model => model.Customer.HomeAddress.City, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.DropDownListFor(model => model.Customer.HomeAddress.StateId, ViewBag.HomeStateList as SelectList, htmlAttributes: new { #class = "form-control checkout" })
<!-- Customer's Mailing Address -->
#Html.EditorFor(model => model.Customer.MailingAddress.Street, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.EditorFor(model => model.Customer.MailingAddress.City, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.DropDownListFor(model => model.Customer.MailingAddress.StateId, ViewBag.MailingStateList as SelectList, htmlAttributes: new { #class = "form-control checkout" })
#Html.EditorFor(model => model.Customer.MailingAddress.PostalCode, new { htmlAttributes = new { #class = "form-control checkout" } })
<!-- Dates Picked Up, Due, and Returned -->
#Html.EditorFor(model => model.PickupDate, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.EditorFor(model => model.DueDate, new { htmlAttributes = new { #class = "form-control checkout" } })
#Html.EditorFor(model => model.ReturnedDate, new { htmlAttributes = new { #class = "form-control checkout" } })
}
Figured it out.
On the View, the Hidden fields are connected with the foreign key address ids (as I had them), but must also be pre-populated with bogus values (so they aren't null), like so:
#Html.HiddenFor(model => model.CustomerId, new { #Value = "0" })
#Html.HiddenFor(model => model.PlaceOfUseAddressId, new { #Value = "0"})
#Html.HiddenFor(model => model.Customer.HomeAddressId, new { #Value = "0" })
#Html.HiddenFor(model => model.Customer.MailingAddressId, new { #Value = "0" })
Then, the procedure on the Controller ends up being fairly straightforward, because MVC is otherwise successfully handling all the pieces. I just need to save and associate them, children on up:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CheckoutForm checkoutForm)
{
Address PlaceOfUse = new Address();
Address HomeAddy = new Address();
Address MailingAddy = new Address();
Customer Client = new Customer();
if (ModelState.IsValid)
{
// Not currently available to the user to be filled in by them
checkoutForm.PlaceOfUseAddress.StateId = 1;
// !!! Need to be given correct value once authorization is set up.
checkoutForm.EnteredBy = TestAccountId;
checkoutForm.ModifiedBy = TestAccountId;
checkoutForm.EnteredDate = System.DateTime.Now;
checkoutForm.ModifiedDate = System.DateTime.Now;
PlaceOfUse = checkoutForm.PlaceOfUseAddress;
HomeAddy = checkoutForm.Customer.HomeAddress;
MailingAddy = checkoutForm.Customer.MailingAddress;
db.Addresses.Add(PlaceOfUse);
db.Addresses.Add(HomeAddy);
db.Addresses.Add(MailingAddy);
db.SaveChanges();
checkoutForm.PlaceOfUseAddressId = PlaceOfUse.AddressId;
checkoutForm.Customer.HomeAddressId = HomeAddy.AddressId;
checkoutForm.Customer.MailingAddressId = MailingAddy.AddressId;
Client = checkoutForm.Customer;
db.Customers.Add(Client);
db.SaveChanges();
checkoutForm.CustomerId = Client.CustomerId;
db.CheckoutForms.Add(checkoutForm);
db.SaveChanges();
return RedirectToAction("Index");
}
else {
// To review in debug mode, when there are problems
//var errors = this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors);
ViewBag.HomeStateList = new SelectList(db.RT_STATE_LIST, "ST_SEQ", "ST_ABBR", checkoutForm.Customer.HomeAddress.StateId);
ViewBag.MailingStateList = new SelectList(db.RT_STATE_LIST, "ST_SEQ", "ST_ABBR", checkoutForm.Customer.MailingAddress.StateId);
return View(checkoutForm);
}
}
Plus, removing the "Bind" attribute from Create()'s parameter made it all a lot easier.

How do I make a textbox readonly only for a specific MVC Action?

The title might be confusing, so here is my problem:
I'd like in my View a readonly textbox only if my Action is for editing (something like EditLocation) and if my Action is intended for adding a new record (AddLocation), I'd like an editable textbox.
My ff. code works, but I was wondering if there's a "cleaner" solution
#using (Html.BeginForm(Model.Location.Id == 0 ? "AddLocation" : "EditLocation", "Location"))
{
<fieldset>
#Html.HiddenFor(x => x.Location.Id)
#Html.HiddenFor(x => x.Location.CompanyGroupId)
#Html.HiddenFor(x => x.CompanyGroup.Id)
#Html.HiddenFor(x => x.CompanyGroup.Code)
<div class="form-group">
<strong><span>#ResourcesCommon.Location_Code</span></strong>
#if (Model.Location.Id == 0)
{
#Html.TextBoxFor(x => x.Location.Code, new { #class = "form-control" })
#Html.ValidationMessageFor(x => x.Location.Code)
}
else
{
#Html.TextBoxFor(x => x.Location.Code, new { #class = "form-control", #readonly = "readonly" })
#Html.ValidationMessageFor(x => x.Location.Code)
}
</div> ...
Thanks and have a good week ahead!
This might help you:
#Html.TextBoxFor(x => x.Location.Code, new Dictionary<string, object>()
.AddIf(true, "#class", "form-control")
.AddIf(Model.Location.Id != 0, "#readonly", "readonly"))
// This returns the dictionary so that you can "fluently" add values
public static IDictionary<TKey, TValue> AddIf<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, bool addIt, TKey key, TValue value)
{
if (addIt)
dictionary.Add(key, value);
return dictionary;
}
I took it from another stackoverflow post long back which i don't have the link.
You could do something like this (but it will produce more code):
#Html.TextBoxFor(x => x.Location.Code, new { #class = "form-control", #id="myInput" })
and then add some js:
$(document).ready(function() {
$('#myInput').attr('readonly', #Html.Raw(Model.Location.Id != 0? "true" : "false"));
});

Conditionally disable textbox in Razor view

Its a quick question.
#Html.TextBoxFor(model => model.VIN, string.IsNullOrEmpty(Model.VIN) ? new { #class = "required Vin" } : new { #disabled = "disabled" })
I get the error that Type of expression can not be determined because there is no implicit conversion anonymous type #1 and anonymous type #2.
Is there a way to conditionally disable text box?
Try something like
#Html.TextBoxFor(model => model.VIN, string.IsNullOrEmpty(Model.VIN) ? new { #class = "required Vin" } : (object)new { disabled = "disabled" })

Remove MVC 5 EditorTemplate additional ID

I am using this Editor Template for Dropdownlist with ViewBag/ViewData of same property Name
#model System.String
#*
For Using this Editor Template
- There should be a viewbag/viewdata (type SelectList) of same name as of calling Model's Property
*#
#{
var modelMetadata = ViewData.ModelMetadata;
// Get property name of the model
var propertyname = modelMetadata.PropertyName;
}
#if (ViewData[propertyname] == null)
{
#Html.DropDownList(propertyname , Enumerable.Empty<SelectListItem>(), "--Select--", new { #class = "form-control" })
}
else
{
#Html.DropDownList(propertyname , null, "--Select--", new { #class = "form-control" })
}
now using it as
#Html.EditorFor(i=>i.Country,"CustomDropDown")
I also have a ViewBag.Country as SelectList of countries.
Everything works fine, but now the Naming of the Control becomes
<select class="form-control" id="Country_Country" name="Country.Country">
how to remove the additional Country from the id and name?
Additional Info:
I could have just used the #Html.DropDownList("Country") but it doesn't allow me to add the css class to the control.
I think i found the Solution.
I changed the DropDownList to DropDownListFor with some changes
#if (ViewData[propertyname] == null)
{
#Html.DropDownListFor(m=>m, Enumerable.Empty<SelectListItem>(), "--Select--", new { #class = "form-control" })
}
else
{
#Html.DropDownListFor(m => m, ViewData[propertyname] as SelectList, "--Select--", new { #class = "form-control" })
}
this auto ViewData bind is kind of confusing at times. >_<

How do I add HtmlAttributes in mvc using ViewBag or Model values?

I have a textarea that I might want to disable in certain conditions. I want to send this information as a ViewBag parameter, but I can't figure out how to do it.
The textarea in my view looks like this
#Html.TextAreaFor(f => f.ProgressDetail, new { #class = "followUpProgress", ViewBag.DisableProgressDetail })
And in the controller I have something like this:
if(conditions)
ViewBag.DisableProgressDetail = "disabled=\"disabled\"";
The html output, however, is this:
<textarea DisableProgressDetail="disabled="disabled"" class="followUpProgress" cols="20" id="ProgressDetail" name="ProgressDetail" rows="2">
</textarea>
What you want is this:
#Html.TextAreaFor(f => f.ProgressDetail, new { #class = "followUpProgress", disabled = ViewBag.DisableProgressDetail })
Then in your controller, just make it:
ViewBage.DisableProgressDetail = "disabled";
The attribute if not specified comes from the name of the property, that is why you are getting an html attribute named for the ViewBag property. One way to get it working would be:
// in the view:
#Html.TextAreaFor(f => f.ProgressDetail, new { #class = "followUpProgress", ViewBag.disabled })
-------------------------------------------------------------
// in the controller
ViewBag.disabled = "disabled";
If you don't like that approach you might just set the disabled bit like this:
// in the view:
#Html.TextAreaFor(f => f.ProgressDetail, new { #class = "followUpProgress", disabled=ViewBag.DisableProgressDetail })
-------------------------------------------------------------
// in the controller:
if(conditions)
ViewBag.DisableProgressDetail = "disabled";
else
ViewBag.DisableProgressDetail = "false";
// or more simply
ViewBag.DisableProgressDetail = (conditions) ? "disabled" : "false";
It doesn´t work. You can try this:
//In the controller
if(Mycondition){ ViewBag.disabled = true;}
else { ViewBag.disabled = false;}
//In the view
#Html.TextBoxFor(model => model.MyProperty, ViewBag.disabled ? (object)new { #class = "MyClass", size = "20", maxlength = "20", disabled = "disabled" } : (object)new { #class = "MyClass", size = "20", maxlength = "20" })

Resources