Design a Editor Template - asp.net-mvc

Currently I have a editor template page which has the code:
#model Comics.Models.LocalComicCategoriesModel
#Html.LabelFor(x => x.Title, Model.Title)
#Html.CheckBoxFor(x => x.isChecked)
#Html.HiddenFor(x => x.Id)
Which I call from different pages with:
#Html.EditorFor(x => x.Categories)
When the template gets outputted, i just get a clunky html with no design to it like:
What I want is something like:
I can achieve this by doing:
#model IEnumerable<Comics.Models.LocalComicCategoriesModel>
<div id="checkbox-list">
#for (int iterator = 0; iterator < Model.Count(); iterator++)
{
if ((iterator % 6) == 0 || iterator == 0)
{
#Html.Raw("<div class='checkboxes_cont' style='float: left;'>");
}
string catTitle = Model.ElementAt(iterator).Title;
bool catChecked = Model.ElementAt(iterator).isChecked;
string catId = Model.ElementAt(iterator).Id.ToString();
<div class="itemtest" style="width: 100px;">
<input id="Categories_#iterator.ToString()__isChecked" name="Categories[#iterator.ToString()].isChecked" type="checkbox" value="#catChecked.ToString()" data-title="#catTitle" #if (catChecked) { Write("checked=checked"); }>
<label for="Categories_#iterator.ToString()__Title">#catTitle</label>
<input name="Categories[#iterator.ToString()].isChecked" type="hidden" value="false">
<input data-val="true" data-val-number="The field Id must be a number." id="Categories_#iterator.ToString()__Id" name="Categories[#iterator.ToString()].Id" type="hidden" value="#catId">
</div>
if ((iterator % 6) == 5 || iterator == Model.Count() - 1)
{
#Html.Raw("</div>")
}
}
</div>
However when I send data back to the controller, the value for the new checkbox dosent get sent back. I was wondering if it were possible to do it through the editor template.

The problem is that you're trying to solve the display with HTML, which is emphatically not the purpose of HTML; that's the domain of CSS. Apply style to the checkboxes in your stylesheet and let your HTML just be.

Related

ASP.NET MVC - Check Box List for Link Table Values

Hoping someone can help me out, what I am trying to achieve a checkbox list (populated from a database table) which then inserts into a link table.
I'm not sure how best to achieve this, this is what I have so far which displays correctly, but I'm not sure how I can get this to save.
#using (Html.BeginForm("Create", "ReviewChecklistsController"))
{
foreach (var item in ViewBag.ChecklistId)
{
<div class="checkbox">
<label>
<input type="checkbox"
name="#item.Value"
value="#item.Value" /> #item.Text
</label>
</div>
}
<p></p>
<div class="form-group">
<input type="submit" class="btn btn-success" value="Save Checklist" />
</div>
}
Below is how I have set it up in the database, if you need any more information please let me know. I am using Entity Framework.
What I want is ReviewChecklist\ChecklistId to map to List_Checklist\ChecklistId and then State is just a boolean so if the checkbox is checked or not.
I've managed to get it working using the below. Is this okay, or is there a better way to do it?
#using (Html.BeginForm("Create", "ReviewChecklistsController"))
{
int i = 0;
foreach (var item in ViewBag.ChecklistId)
{
var nameStatus = "reviewChecklist[" + i + "].Status";
var nameReviewId = "reviewChecklist[" + i + "].ReviewId";
var nameChecklistId = "reviewChecklist[" + i + "].ChecklistId";
#Html.HiddenFor(model => model.ReviewId, new { Name = nameReviewId })
#Html.HiddenFor(model => model.ChecklistId, new { Name = nameChecklistId, Value = item.Value })
<p>
#Html.CheckBoxFor(model => model.Status, new { Name = nameStatus })
#item.Text
</p>
i++;
}
<p></p>
<div class="form-group">
<input type="submit" class="btn btn-success" value="Save Checklist" />
</div>
}

Editor Template for Enum with RadioButton not working

I updated a Enum Editor I found online to generate kendo radio controls instead of regular but the first radio button is generated with correct attributes and the remaining are wrong and at runtime, the whole set of radio buttons are not clickable
Here is the .cshtml for the editor:
#model Enum
#{
Func<Enum, string> getDescription = en =>
{
Type type = en.GetType();
System.Reflection.MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute), false);
if (attrs != null && attrs.Length > 0)
{
return ((System.ComponentModel.DataAnnotations.DisplayAttribute)attrs[0]).GetName();
}
}
return en.ToString();
};
var listItems = Enum.GetValues(Model.GetType()).OfType<Enum>().Select(e =>
new SelectListItem()
{
Text = getDescription(e),
Value = e.ToString(),
Selected = e.Equals(Model)
});
string prefix = ViewData.TemplateInfo.HtmlFieldPrefix;
int index = 0;
ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty;
foreach (var li in listItems)
{
string fieldName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}", prefix, index++);
<div >
#(Html.Kendo().RadioButton()
.Label(li.Text)
.Name(prefix)
.Value(li.Value)
.Checked(li.Selected)
.HtmlAttributes(new { #id = fieldName })
)
#*
This works properly
#Html.RadioButton(prefix, li.Value, li.Selected, new { #id = fieldName, #class = "k-radio" })
#Html.Label(fieldName, li.Text, new { #class = "k-radio-label" })
*#
</div>
}
ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
}
Here is the first radio on the form:
<div>
<input name="StaffType" class="k-radio k-radio" id="StaffType_0" type="radio" checked="checked" value="DACStaff" data-val-required="The StaffTypeEnum field is required." data-val="true">
<label class="k-radio-label" for="StaffType_0_DACStaff">DAC Staff</label>
</div>
And here is the next one:
<div>
<input name="StaffType" class="k-radio k-radio" id="StaffType_1" type="radio" value="AirportStaff">
<label class="k-radio-label" for="StaffType_1_AirportStaff">Airport Staff</label>
</div>
I see that the class tag k-radio is applied twice and except the first element has the data-* attributes but second radio button and onwards, the generated code is missing attributes.
Can someone point out why the generated code is not functioning?
Usage:
<div class="form-group">
#Html.LabelFor(m => m.StaffType, new { #class = "col-sm-3 control-label" })
<div class="col-sm-6">
#Html.EditorFor(m => m.StaffType, "RadioButtonListEnum")
</div>
</div>

How can I model bind to a textbox placeholder?

I have been able to bind the info to the textbox like so:
<div id="wordsInsideOfText">
#foreach (var item in Model.KVpairs)
{
#Html.TextBoxFor(modelItem => item)
<hr />
}
</div>
but what I am trying to do is something like this:
<div id="wordsInsideOfText">
#foreach (var item in Model.KVpairs)
{
#Html.TextBoxFor().PlaceHolder(modelItem => item)
<hr />
}
</div>
So that I can get the information from my model into the placeholder rather than as regular text.I have looked around some, and maybe I don't fully understand how to phrase my question/search but I wasn't able to come up with anything.
you have to do like this:
#Html.TextBoxFor(modelItem => item, new {placeholder = item})
or:
<input type="text" placeholder="#item"/>

Add if condition on View (ASP.NET MVC 4)

I have this code in my View
#using (Html.BeginForm("Add", "AdminUsers"))
{
<div class="control-group">
<span class="control-label">* Role:</span>
<div class="controls">
<select name="Role">
<option value="#Argussite.SupplierService.Core.Domain.Role.Manager"
#if (Model.Role == Argussite.SupplierService.Core.Domain.Role.Manager) { <text>selected="selected"</text> }>
#Argussite.SupplierService.Core.Domain.Role.ManagerTitle</option>
<option value="#Argussite.SupplierService.Core.Domain.Role.ChiefManager"
#if (Model.Role == Argussite.SupplierService.Core.Domain.Role.ChiefManager) { <text>selected="selected"</text> }>
#Argussite.SupplierService.Core.Domain.Role.ChiefManagerTitle</option>
<option value="#Argussite.SupplierService.Core.Domain.Role.Ceo"
#if (Model.Role == Argussite.SupplierService.Core.Domain.Role.Ceo) { <text>selected="selected"</text> }>
#Argussite.SupplierService.Core.Domain.Role.CeoTitle</option>
</select>
</div>
</div>
//...
<div class="control-group">
<span class="control-label">* Phone:</span>
<div class="controls">
#Html.TextBoxFor(m => m.PhoneNumber)
#Html.ValidationMessageFor(m => m.PhoneNumber, null, new {#class="text-error"})
</div>
</div>
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-primary">Add</button>
Cancel
</div>
</div>
}
And I need to add a checking if I selected at the list
Model.Role == Argussite.SupplierService.Core.Domain.Role.Manager
I need to show
<div class="control-group">
<span class="control-label">* Phone:</span>
<div class="controls">
#Html.TextBoxFor(m => m.PhoneNumber)
#Html.ValidationMessageFor(m => m.PhoneNumber, null, new {#class="text-error"})
</div>
</div>
If I changed selected value at the list
Model.Role == Argussite.SupplierService.Core.Domain.Role.ChiefManager
or
Model.Role == Argussite.SupplierService.Core.Domain.Role.Ceo
I need to show Phone Field without * and I dont need Validation this field.
How can I do that?
It's my control
[HttpPost]
public ActionResult Add(AddArgussoftUserInput input)
{
if ((input.Role == Role.Manager || input.Role == Role.ChiefManager) && string.IsNullOrWhiteSpace(input.PhoneNumber))
{
ModelState.AddModelError("PhoneNumber", "Please, provide a valid Phone Number");
}
if (!Context.IsUserNameUnique(input.Name))
{
ModelState.AddModelError("Name", AddArgussoftUserInput.NameIsNotUniqueError);
}
if (!Context.IsUserEmailUnique(input.Email))
{
ModelState.AddModelError("Email", AddArgussoftUserInput.EmailIsNotUniqueError);
}
if (!ModelState.IsValid)
{
return View(input);
}
var user = new User(input.Name, input.Email, input.FullName, input.Role, input.PhoneNumber);
Context.Users.Add(user);
Register(new UserCreatedNotification(user, null /* supplier */, UrlBuilder));
TriggerPopupSuccess(string.Format("Account '{0}' for user {1} has been created.", input.Name, input.FullName));
return RedirectToAction("Index");
}
You can make a HtmlHelper that extends the MvcHtml.
I've handled this problem somewhat like this but with custom authorizeattributes.
namespace System.Web.Mvc.Html
{
public static class HtmlHelperExtensions
{
public static MvcHtmlString AuthorizeCeo()
{
return Model.Role == "Ceo" ? value : MvcHtmlString.Empty;
}
}
This way you can use it like:
#Html.ActionLink("Phonenumber *", "actionName", "controllerName").AuthorizeCeo()
And it will only show if the user is authorized.
You can use jQuery to hook the change event of the select list and show a div based on the selected Role.
I set up a quick jsFiddle to show you here
http://jsfiddle.net/nwdev/X5Zva/
<select id="RoleList">
<option value="Manager">Manager</option>
<option value="CEO">CEO</option>
</select>
<div id="RequiredPhone">
phone field with validation
</div>
<div id="OptionalPhone">
optional phone field here
</div>
And some jQuery to get it wired up...
jQuery(function() {
jQuery('#RequiredPhone').hide();
jQuery('#OptionalPhone').hide();
});
function updateOption() {
jQuery('#RequiredPhone').toggle(this.value == 'Manager');
jQuery('#OptionalPhone').toggle(this.value == 'CEO');
}
jQuery(document).ready(function() {
jQuery("#RoleList").each(updateOption);
jQuery("#RoleList").change(updateOption);
});
So, if you select Manager from the dropdrop it will show the ReqiredPhone div and if you select the CEO it will show the OptionalPhone div.
This should get you going in the right direction.
I haven't tested this with the validation field. You might have to add it dynamically.

ASP.NET MVC 3 Binding Unsuccessful

I am having trouble making my ASP.NET MVC 3 View bind data back to a Model.
The typical objects such as string ContactName and string Title are being sent back successfully.
My public List<KeyValuePair<string, ListingTranslation>> ExpirimentToRemove object however isn't being sent back for some reason.
The following is contains code of the specific objects that aren't being binded successfully.
<div>
<ul class="nav nav-tabs">
#for (int i = 0; i < Model.ExpirimentToRemove.Count; i++)
{
<li class="#i == 0 ? 'active' : ''">#Model.Translations.Keys.ToList()[i]</li>
}
</ul>
<div class="tab-content" style="overflow: visible;">
#for (int i = 0; i < Model.ExpirimentToRemove.Count; i++)
{
<div class="tab-pane#i == 0 ? ' active' : ''" id="##Model.Translations.Keys.ToList()[i]">
#Html.TextBoxFor(m => Model.ExpirimentToRemove[i].Value.Title)
#Html.TextBoxFor(m => Model.ExpirimentToRemove[i].Value.FullDescription)
#Html.TextBoxFor(m => Model.ExpirimentToRemove[i].Value.PreviewDescription)
</div>
}
</div>
The trick for a list of items to be bound back is to have hidden fields.
Here is a great article explaining it in detail
Example:
<input type="hidden" name="products.Index" value="caliente" />
<input type="text" name="products[caliente].Name" value="Salsa" />
<input type="text" name="products[caliente].Price" value="1.23" />
The only other way is to manually manipulate the name attribute for the element that corresponds with the object path for the given item in List<T>.

Resources