How make a dropdownlist? [Edited - almost working code]
View:
<div class="editor-label">
Firma
<div class="editor-field">
#Html.DropDownListFor(x => x.ID_firma, Model.firmaList)
#Html.ValidationMessageFor(model => model.nazwa)
</div>
Model:
public class produktModel
{
[Required(ErrorMessage="Proszę podać nazwę.")]
public string nazwa { get; set; }
[Required(ErrorMessage = "Proszę podać ilść produktu.")]
public decimal ilosc { get; set; }
[Required(ErrorMessage = "Proszę podać jednostkę produktu (np. kg, l, szt.).")]
public string jednostka { get; set; }
[Required(ErrorMessage = "Proszę podać cenę produktu.")]
public decimal cena { get; set; }
public string ID_firma { get; set; }
public IEnumerable<SelectListItem> firmaList { get; set; }
}
Controller:
public ActionResult dodaj()
{
var firma = baza.Firmas;
var model = new produktModel
{
firmaList = firma.AsEnumerable().Select(x => new SelectListItem
{
Value = x.ID_firma.ToString(),
Text = x.nazwa
})
};
return View(model);
}
[HttpPost]
public ActionResult dodaj(produktModel model)
{
Produkt prod = new Produkt();
prod.nazwa = model.nazwa;
prod.ilosc = model.ilosc;
prod.jednostka = model.jednostka;
prod.cena = model.cena;
prod.ID_firma = model.ID_firma;
baza.Produkts.InsertOnSubmit(prod);
baza.SubmitChanges();
return RedirectToAction("zarzadzaj_produktami", "Produkt");
}
It almost work...
I have only one problem (I hope)...
Value is string, and I save his value to database... (I don't now how to write it...)
prod.ID_firma = model.ID_firma;
prod.ID_firma is int. model.ID_firma is this value which is string. So I have an error:
Error 1 Cannot implicitly convert type 'string' to 'int?'
change your model a bit, i have assumed the column names change them according to your code
public class produktModel
{
[Required]
public string name { get; set; }
public decimal price { get; set; }
[Required]
public int companyID {get; set;}
public List<Company> compList {get; set;}
}
public class Company{
public int CompanyID {get;set;}
public string CompanyName {get;set;}
}
ActionResult should look like
public ActionResult add()
{
produktModel model = new produktModel();
model.compList= (from b in base.Companies
select new Company{
CompanyID = b.CompanyID,
CompanyName = b.CompanyName
}).ToList();
return View(model);
}
in your (strongly typed) view
#model produktModel
....
<div class="editor-label">
Company
<div class="editor-field">
#Html.DropDownListFor(model => model.companyID,
new SelectListItem(model.compList,
"CompanyID ",
"CompanyName "))
#Html.ValidationMessageFor(model => model.company_name)
</div>
...
Your question isn't clear enough.
Any way you can use the telerik combox\dropdown list or the default mvc dropdown list. you can find a lot of examples on google for that.
With Telerik write something like this:
#(Html.Telerik().ComboBox()
.Name("ComboBox")
.BindTo(new SelectList("CompanyID", "CompanyName")))
see this Telerik demo for more information.
Related
I want to display a checkbox in view using razor syntax.
the model property IsActive should be int.
Model is:-
public class Student
{
public int StudentID { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public int IsActive { get; set; }
}
View is:-
<div class="editor-label">
#Html.LabelFor(model => model.IsActive)
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.IsActive)
#Html.ValidationMessageFor(model => model.IsActive)
</div>
I should display checkbox and if checkbox is checked,1 should be saved to the database and if umchecked 0 should be saved.
Pls help me...
Thanks..
What don't you understand in the error message ? You can't use CheckBoxFor for an int property.
You should change your model and set
public bool IsActive {get;set;}
Now, there's probably a good reason for it to be an int, but hard to say why with your code...
if IsActive can be only 0 or 1, you should use a ViewModel class, and use a boolean property, which you will map to your class.
public class StudentViewModel
{
public int StudentID { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
}
then when you get your student from your db (in your "GET" action")
something like that (rustic)
public ActionResult StudentEdit(int id) {
var student = getStudentById(id);
var model = new StudentViewModel {
StudentId = student.StudentID,
Code = student.Code,
Description = student.Description,
IsActive = student.IsActive == 1
};
return View(model);
}
Your view should be typed with StudentViewModel
#model StudentViewModel
then in your POST action, reverse
[HttpPost]
public ActionResult StudentEdit(StudentViewModel model) {
var student = getStudentById(model.StudentID);
student.Code = model.Code;
student.Description = model.Description;
student.IsActive = model.IsActive ? 1 : 0;
UpdateStudent(student);
return Redirect...
}
EDIT :
This is a really rustic answer, and I'm sure you could do better.
For that, we would need some more infos :
Are you using Entity Framework (version) ?
If yes, Code first, Database first, model first ?
Which database is behind ?
Can you change something to the database ?
What type has IsActive in database ?
IsActive should be a bool, #Html.CheckBoxFor() helper method expects boolean parameter
change code to
public bool IsActive { get; set; }
I am having trouble with Model.IsValid on a property that's not required.
Here's the code.
BeginForm in the Edit.cshtml file
#using (Html.BeginForm("Edit", "Member", FormMethod.Post, new { enctype = "multipart/formdata" }))
{
#Html.Partial("_MemberForm", Model.Member)
}
MemberEditViewModel: (used for the Edit.cshtml file)
public class MemberEditViewModel
{
public MemberFormModel Member { get; set; }
}
MemberFormModel:
public class MemberFormModel : ICreateMemberCommand, IValidatableObject
{
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string SocialSecurityNumber { get; set; }
[Required]
public int PinCode { get; set; }
[Required]
public char Gender { get; set; }
public string Email { get; set; }
[Required]
public string Address { get; set; }
[Required]
public string ZipCode { get; set; }
[Required]
public string ZipAddress { get; set; }
public string Phone { get; set; }
public string Phone2 { get; set; }
[Required]
public string City { get; set; }
[Required]
public int CountryId { get; set; }
//not required (but still displaying error it's required)
public Membership Membership { get; set; }
// not required (displaying error it's required)
public PunchCard PunchCard { get; set; }
public bool IsActive { get; set; }
block of _MemberForm.cshtml (partial)
<fieldset>
<dl>
<dt>#Html.LabelFor(m => m.Id)</dt>
<dd>#Html.TextBoxFor(m => m.Id, new { disabled = "disabled", #readonly = "readonly" })</dd>
<dt>#Html.LabelFor(m => m.PinCode)</dt>
<dd>#Html.EditorFor(m => m.PinCode)</dd>
<!-- problem with membership, maybe with the .FromData/ToDate ? -->
<dt>#Html.LabelFor(m => m.Membership)</dt>
<dd>#Html.EditorFor(m => m.Membership.FromDate, new { #name = "Membership" }) -
#Html.EditorFor(m => m.Membership.ToDate, new { #name="Membership"})</dd>
<!-- problem with punch card, maybe with the .Times ? -->
<dt>#Html.LabelFor(m => m.PunchCard)</dt>
<dd>#Html.EditorFor(m => m.PunchCard.Times, new { #name = "PunchCard" })</dd>
</dl>
</fieldset>
The MemberController Edit Action
// POST: /Members/10002/Edit
[HttpPost]
public ActionResult Edit(FormCollection formValues, MemberFormModel memberForm)
{
var errors = ModelState.Values.SelectMany(v => v.Errors);
if(IsSaveOperation(formValues)){
if(TryUpdateMember(memberForm)){
return RedirectToAction("Details", "Member", new {id = memberForm.Id});
}
}
var mm = new MemberEditViewModel{ Member = memberForm };
return View(mm);
}
Membership.cs
public class Membership
{
public Membership(){ /* empty constructor */}
public Membership(int id, int memberId, DateTime fromDate, DateTime toDate)
{
Id = id;
MemberId = memberId;
FromDate = fromDate;
ToDate = toDate;
}
public int Id { get; set; }
public int MemberId { get; set; }
[DataType(DataType.Date)]
public DateTime FromDate { get; set; }
[DataType(DataType.Date)]
public DateTime ToDate { get; set; }
}
PunchCard.cs
public class PunchCard
{
public PunchCard() { /* empty constructor */ }
public PunchCard(int memberId, int times, DateTime createdDate, DateTime modifiedDate)
{
this.MemberId = memberId;
this.Times = times;
this.CreatedDate = createdDate;
this.ModifiedDate = modifiedDate;
}
public int Id { get; set; }
public int MemberId { get; set; }
public int Times { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime ModifiedDate { get; set; }
}
You see I dont have any [Required] attribute, neither in the MemberFormModel. So how come those two are Required ? Its a mystery.
You should not be using both the disabled and readonly attribute on your textbox:
#Html.TextBoxFor(m => m.Id, new { disabled = "disabled", #readonly = "readonly" })
I guess the disabled attribute takes precedence and the value of the Id is never sent to the server when you submit the form. That's why you get a modelstate error. Because your id property is required. Now you will be probably tell me that it is not decorated with the [Required] attribute but this doesn't matter. Since you have declared it as a non-nullable integer it is implicitly required and the framework automatically makes it required. If you don't want this to happen you should declare it as a nullable integer.
So back to your view, if you want to only display id, without allowing the user to modify it, use readonly:
#Html.TextBoxFor(m => m.Id, new { #readonly = "readonly" })
Obviously don't think that if you made a textbox readonly, the user cannot modify it. The normal user will not. But a hacker could always put whatever value he wants in this textbox and forge a request. So absolutely do not rely on this as some sort of security or something.
I am trying to create an Item that has an ItemType coming from another table. I am unable to get back the actual Type object from the Create page. This is the code I have tried:
Models:
public class ItemType {
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Item> Item{ get; set; }
}
public class Item {
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ItemType ItemType { get; set; }
}
In the ItemController, this is my create code:
public ActionResult Create() {
var itemTypeRepo = new ItemTypeRepository(context);
ViewBag.ItemTypes = new SelectList(itemTypeRepo.GetAll(), "ID", "Name");
return View();
}
[HttpPost]
public ActionResult Create(Item item) {
if (ModelState.IsValid) {
context.Items.Add(item);
context.SaveChanges();
return RedirectToAction("Index");
}
return View(item);
}
In my Create.cshtml view I have tried:
<div class="editor-field">
#Html.DropDownList("ItemType", String.Empty)
#Html.ValidationMessageFor(model => model.ItemType)
</div>
This returns no value at all and throws an error "The value 'X' is invalid." Where X is the ID of the ItemType I selected.
And
<div class="editor-field">
#Html.DropDownListFor(x => x.ItemType.Id, (SelectList)ViewBag.ItemType)
#Html.ValidationMessageFor(model => model.ItemType)
</div>
This creates a stub ItemType object with the correct ID but does not insert it into the database since the object is not fully loaded. If I look at ModelState object, I find that there is an error that the Name field is missing from ItemType object.
I also attempted to solve the problem using the second .cshtml code and adding this code:
public ActionResult Create(Item item) {
item.ItemType = context.ItemTypes.Find(item.ItemType.Id);
if (ModelState.IsValid)
This does not change the value of ModelState.IsValid from false even through it should.
What do I need to do to get this to work?
You should add a property ItemTypeId to your Item entity so that it acts as a foreign key.
public class Item
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int ItemTypeId { get; set; }
[ForeignKey("ItemTypeId")]
public virtual ItemType ItemType { get; set; }
}
You can then use that property for the dropdownlist:
<div class="editor-field">
#Html.DropDownListFor(x => x.ItemTypeId, (SelectList)ViewBag.ItemType)
#Html.ValidationMessageFor(model => model.ItemType)
</div>
I hope someone can help with this one. I have three Model classes like this:
public class Provider
{
public Guid ProviderId { get; set; }
public string Name { get; set; }
public Guid LocationId { get; set; }
public virtual Location Location { get; set; }
}
public class Location
{
public Guid LocationId { get; set; }
public string NameOrCode { get; set; }
public string Description { get; set; }
public string StreetNumber { get; set; }
public string StreetAddress1 { get; set; }
public string StreetAddress2 { get; set; }
public string City { get; set; }
public int? StateId { get; set; }
public string Zip { get; set; }
public string ContactPhone { get; set; }
public virtual State State { get; set; }
}
public class State
{
public int StateId { get; set; }
public string Name { get; set; }
public string Abbreviation { get; set; }
}
As you can see, a Provider has a Location (separate class for reuse elsewhere), and a Location has a State (which is null until selected).
My Controller looks like this for my Create methods:
public class ProviderController : BaseController
{
private SetupContext db = new SetupContext();
// other CRUD methods ...
//
// GET: /Provider/Create
public ActionResult Create()
{
Location location = new Location()
{
LocationId = Guid.NewGuid(),
NameOrCode = Resources.BillingLocation,
Description = Resources.BillingLocationDescription
};
Provider provider = new Provider()
{
ProviderId = Guid.NewGuid(),
LocationId = location.LocationId,
Location = location
};
ViewBag.StateId = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
return View(provider);
}
//
// POST: /Provider/Create
[HttpPost]
public ActionResult Create(Provider provider)
{
if (ModelState.IsValid)
{
db.Locations.Add(provider.Location);
db.Providers.Add(provider);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.StateId = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
return View(provider);
}
// other CRUD methods ...
}
Finally, my View looks like this:
<div class="editor-label">
#Html.LabelFor(model => model.Location.StateId, #Resources.Location_State_Display_Name)
</div>
<div class="editor-field">
#Html.DropDownList("StateId", #Resources.ChooseFromSelectPrompt)
#Html.ValidationMessageFor(model => model.Location.StateId)
</div>
My problem is that the state the user selects in the DropDownList never gets set on my Model on the Create POST. I have similar code in my Edit View and the state is populated correctly in that View (that is, the state associated with an existing Provider.Location shows selected in the DropDownList for the user to edit if desire), but in both the Create and the Edit Views the selection made by the user is never registered in my Model (specifically the Provider.Location.StateId) coming in from the POST.
Looking at the HTML produced I see this:
<div class="editor-label">
<label for="Location_StateId">State/Territory</label>
</div>
<div class="editor-field">
<select id="StateId" name="StateId"><option value="">[Choose]</option>
<option value="1">Alabama</option>
<option value="2">Alaska</option>
<!-- more options ... -->
</select>
<span class="field-validation-valid" data-valmsg-for="Location.StateId" data-valmsg-replace="true"></span>
</div>
I suspect I need to somehow convey the Location.StateId relationship instead of just StateId as I see above but I can't figure out the correct syntax to do that. I've tried changing my ViewBag dynamic property to Location_StateId like this:
ViewBag.Location_StateId = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
And the DropDownList in my View like this:
#Html.DropDownList("Location_StateId", #Resources.ChooseFromSelectPrompt)
I figured then perhaps that notation would work because the label beside my DropDownList was rendered as:
<div class="editor-label">
<label for="Location_StateId">State/Territory</label>
</div>
This attempt did not work. Can you help me out?
Thanks in advance.
#Html.DropDownList("Location.StateId", #Resources.ChooseFromSelectPrompt)
Also the following line doesn't do anything useful:
ViewBag.StateId = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
You are assigning a SelectList to something that is supposed to be a scalar property. You probably wanted to pass the collection as ViewBag:
ViewBag.States = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
and then in the view:
#Html.DropDownList("Location.StateId", (SelectList)ViewBag.States)
I'm trying (without success) to use the Remote validator on a DropDownList:
// Person.cs
public int PersonID { get; set; }
public string Name { get; set; }
// Card.cs
public int CardID { get; set; }
[Remote("PersonValidation", "Validation", ErrorMessage = "...")]
public int PersonID { get; set; }
public virtual Person Person { get; set; }
// CardController
public ActionResult Create()
{
ViewBag.PersonID = new SelectList(db.Persons, "PersonID", "Name");
Card card = new Card();
return View(card);
}
// create.cshtml (Card Views)
<div class="editor-label">#Html.LabelFor(model => model.personID, "Person")</div>
<div class="editor-field">
#Html.DropDownList("PersonID", String.Empty)
#Html.ValidationMessageFor(model => model.PersonID)
</div>
// ValidationController.cs
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
public JsonResult PersonValidation(int id)
{
Person person = db.Persons.Find(id);
return Json(person.Cards.Count > 0, JsonRequestBehavior.AllowGet);
}
The PersonValidation is never fired. The others "Remote" validations with text input are working perfectly.
Am I doing something wrong or is there a problem with DropDownList Remote validation?
Thanks!
The validator does not fire because you need to use #Html.DropDownListFor() in order to create an HTML element with "data-val" elements, which will be parsed into unobtrusive validators.