Kendo UI Cascading Dropdown initial value not setting up - kendo-ui

I have cascade dropdownlists and when trying to define initial value (under cascade, too) instead to call the ajax controller methods with parent selected value it's passing blank values.
I have equirement like, i can save my last search values and store it int database and after coming to that screen again, values will be selected by default.
Everything is in Javascript means storing the values/ retriving and applying to controls :
My Cascade dropdown code :
<div style="width: 400px; clear: both; float: left; position: relative; display: table-cell;">
<ul style="width: 450px; clear: both; float: none;">
<li>
<div class="editor-row">
<div class="editor-label-short">Home Country</div>
<div class="editor-field">
#(Html.Kendo().DropDownList()
.Name("HOME_COUNTRY_ID")
.HtmlAttributes(new { style = "width:200px" })
.OptionLabel("Select Home Country")
.DataTextField("Text")
.DataValueField("Value")
.DataSource(source => source.Read(read => read.Action("GetCountryJSON", "Employee")))
)
</div>
</div>
</li>
<li>
<div class="editor-row">
<div class="editor-label-short">Home City</div>
<div class="editor-field">
#(Html.Kendo().DropDownList()
.Name("HOME_CITY_ID")
.HtmlAttributes(new { style = "width:200px" })
.OptionLabel("Select Home City")
.DataTextField("Text")
.DataValueField("Value")
.DataSource(source => source.Read(read => read.Action("GetCityByCountryJSON", "Employee")
.Data("getCountryId"))
.ServerFiltering(true))
.AutoBind(false)
.CascadeFrom("HOME_COUNTRY_ID")
)
</div>
</div>
</li>
</ul>
</div>
Javacript Code which assigning Values in Page load means After Dom ready:
function applyvaluetoControls() {
setdefaultvaluestoControls();
$.each(activeLayout.controls, function(index) {
$.each(options.emementArray, function(innerindex) {
if (options.emementArray[innerindex].attr("id") === activeLayout.controls[index]["id"]) {
if ((options.emementArray[innerindex]).is(':checkbox')) {
options.emementArray[innerindex].prop('checked', activeLayout.controls[index]["value"]);
} else {
if (options.emementArray[innerindex].attr("data-role") !== undefined && options.emementArray[innerindex].attr("data-role") === "dropdownlist") {
// console.log(options.emementArray[innerindex].data('kendoDropDownList'));
if (options.emementArray[innerindex].data('kendoDropDownList').options.cascadeFrom !== "") {
console.log($("#" + options.emementArray[innerindex].data('kendoDropDownList').options.cascadeFrom).val());
options.emementArray[innerindex].data('kendoDropDownList').dataSource.read({ CompanyId: $("#" + options.emementArray[innerindex].data('kendoDropDownList').options.cascadeFrom).val() });
options.emementArray[innerindex].data('kendoDropDownList').value(activeLayout.controls[index]["value"]);
} else {
options.emementArray[innerindex].data('kendoDropDownList').enable();
options.emementArray[innerindex].data('kendoDropDownList').value(activeLayout.controls[index]["value"]);
}
console.log(activeLayout.controls[index]["id"]);
console.log(activeLayout.controls[index]["value"]);
} else {
options.emementArray[innerindex].val(activeLayout.controls[index]["value"]);
}
}
}
});
});
}
Console Log:
HOME_COUNTRY_ID // Parent Control Id
322 // It Setting the value to Parent
// Blank value when I am trying to read the value Parent Control (Country)
City : // Parent triggering Chile but with Blank Value
HOME_CITY_ID // Child
342 // Value
City : 322 // after coming out of loop it's again calling Child with Parent selected value
and It's wiping out intial selected value of child.
Any help will be highly appreciated!!

ChildrenUsing these properties from your example in your child drop down you are instructing the drop down to:
.AutoBind(false) //<--Don't do any data retrieval until asked or clicked
.OptionLabel("Select Home City") //<--If the value is null display this and value will be ""
.CascadeFrom("HOME_COUNTRY_ID") //<--Get my values using the DataValueField from this control and refresh when it changes
I bet by having the cascade on like that you will need a configuration similar to this fictitious scenario:
Parent DropDown Config
.Name("ddlParent")
.OptionLabel((#Model.ForceParentSelect) ? "" : "All Parents")
.Value(Model.ParentID.HasValue ? Model.ParentID.Value.ToString() : "")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetParents", "Parent");
});
})
Child DropDown Config
<script>
function filterChild{ return { ParentID: $("#ddlParent").val() }; }
</script>
.Name("ddlChild")
.OptionLabel((#Model.ForceChildSelect) ? "" : "All Childs")
.Value(Model.ChildID.HasValue ? Model.ChildID.Value.ToString() : "")
.AutoBind(Model.ParentID.HasValue)
.CascadeFrom(Model.ParentID.HasValue ? "" : "ddlParent")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetChildren", "Child")
.Data("filterChild");
})
})

Related

Event: onChange dropdown list

Here i have an element:
<div id="prof_Severity" class="form-group row">
<div class="col-md-3">
#Html.Label("Severity: *", htmlAttributes: new { #class = "control-label single-line-valignment" })
</div>
<div class="col-md-4">
#(Html.Kendo().DropDownList()
.Name("Severity")
.BindTo(Enumerable.Range(1, 10))
.OptionLabel("Select severity...")
.HtmlAttributes(new { style = "width: 100%; text-align: center;" })
.Events(e => e.Change("onSeverityChange"))
.Value(Model.Severity.ToString())
)
</div>
<div class="col-md-1" style="text-align: right;">
#Html.Label("Note:", htmlAttributes: new { #class = "control-label single-line-valignment" })
</div>
<div class="col-md-4">
#(Html.Kendo().TextBox().Name("SeverityNote").Value(Model.SeverityNotes).HtmlAttributes(new { type = "text", style = "width: 100%; max-width: 100%", placeholder = "Specify if \"Severity is equal 9 or 10\", selected " }))
)
</div>
</div>
How can i define the onSeverityChange function in javascript, if i select the value of Severity less than 8 then, the textbox of Note field shoud be locked and when Severity is bigger than 8 then the textbox of the Note field to be unlocked?
Thank you.
You can accomplish that by doing something like the following (non-tested code here!)
function onSeverityChange() {
var dropdownlist = $("#Severity").data("kendoDropDownList");
var severityValue = dropdownlist.value();
if (severityValue < 8) {
//lock textbox
$('#SeverityNote').prop("disabled", true);
} else {
//unlock textbox
$('#SeverityNote').prop("disabled", false);
}
}

How to change the colors of items conditionally in Kendo treeview

I am using first time Kendo ui so I have very limited knowledge about it. What should I do to change treeview items color for some conditions.
<div>
#(
Html.Kendo().TreeView()
.Name("treeview")
.TemplateId("treeviewTemp")
.HtmlAttributes(new { #class = "rightlist"})
.BindTo((IEnumerable<NavigationViewModel>)ViewBag.Tree, (NavigationBindingFactory<TreeViewItem> mappings) =>
{
mappings.For<NavigationViewModel>(binding => binding.ItemDataBound((item, node) =>
{
item.Text = node.Description;
}).Children(node => node.Children));
mappings.For<NavigationViewModel>(binding => binding.ItemDataBound((item, subCategory) =>
{ item.Text = subCategory.Description; }));
})
)
</div>
And this is the templete. Template works for color change but tree items comes as "undefined". Is it also possible to add some conditions in script?
<script id="treeviewTemp" type="text/kendo-ui-template">
<div>
<span style="color: Green">#: item.Text #</span>
</div>
</script>

How to close Kendo UI Autocomplete programmatically

I am using the Kendo UI Autocomplete Box in a ASP.Net MVC Application.
(KENDO UI for ASP.NET MVC Q1 2016)
The part of the .cshtml code looks like this:
<div class="row">
<div class="col-md-10">
<div class="form-group">
#Html.Label(Strings.ManagerTimeEffortFormPartial_LabelLookupCustomer, new { #class = "k-label" })
#Html.TextBox("CustomerId", "", new { style = "display: none;" })
#(Html.Kendo().AutoComplete()
.Name("CustomerName")
.DataTextField("DisplayName")
.Filter(FilterType.Contains)
.MinLength(3)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("SearchCustomers", "Customer")
.Data("onSearchManagerEffortCustomerName");
})
.ServerFiltering(true);
})
.HtmlAttributes(new { #class = "k-textbox-fullwidth" })
.Events(e =>
{
e.Select("onSelectManagerEffortCustomer");
})
)
</div>
</div>
</div>
The element needs to be prefilled with a value. I am doing this after the ui was loaded:
$(function () {
var customerValue = $("#Project_CustomerName").val();
var customerNameAutoComplete = $("#CustomerName").data("kendoAutoComplete");
$("#CustomerName").val(customerValue);
customerNameAutoComplete.search(customerValue);
customerNameAutoComplete.select(customerNameAutoComplete.ul.children().eq(0));
customerNameAutoComplete.close();
});
Calling the "Close" method should close the suggestions (from what I understood in the documentation) but it does not work (the suggestions are still open). If I scroll the window in the ui or click somewhere else it closes immediately, but setting focus programmatically to another element or triggering a click-event via code doesn't help. I could hide/change the DOM-elements one by one, but I don't think this is a good solution, there are too many attributes changing when the item is selected with a mouse click.
Everything else in the code works fine (binding source, selecting the element and so on - I did not post the JS-Code for these parts here). I also tried to play with the "suggest" method without any luck. Any idea or a hint in the right direction?
This is how the autocomplete looks like after calling the "Close" method (still open):
Screenshot of Autocomplete Box with open suggestions
Sorry for this... again I got caught by the asynchronous loading trap...
of course I need to wait for the data bound event until i should select the item...
<div class="row">
<div class="col-md-10">
<div class="form-group">
#Html.Label(Strings.ManagerTimeEffortFormPartial_LabelLookupCustomer, new { #class = "k-label" })
#Html.TextBox("CustomerId", "", new { style = "display: none;" })
#(Html.Kendo().AutoComplete()
.Name("CustomerName")
.DataTextField("DisplayName")
.Filter(FilterType.Contains)
.MinLength(3)
.Suggest(false)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("SearchCustomers", "Customer")
.Data("onSearchManagerEffortCustomerName");
})
.ServerFiltering(true);
})
.HtmlAttributes(new { #class = "k-textbox-fullwidth" })
.Events(e =>
{
e.Select("onSelectManagerEffortCustomer");
e.DataBound("OnCustomerDataBound");
})
)
</div>
</div>
</div>
<script>
function OnCustomerDataBound() {
var customerNameAutoComplete = $("#CustomerName").data("kendoAutoComplete");
var select = customerNameAutoComplete.ul.children().eq(0);
customerNameAutoComplete.select(select);
customerNameAutoComplete.close();
}
$(function () {
var customerValue = $("#Project_CustomerName").val();
var customerId = $("#Project_CustomerId").val();
var consProjectId = $("#Project_ConsultingProjectId").val();
var customerNameAutoComplete = $("#CustomerName").data("kendoAutoComplete");
$("#CustomerName").val(customerValue);
$("#CustomerId").val(customerId);
customerNameAutoComplete.search(customerValue);
customerNameAutoComplete.trigger("change");
RefreshDropDownList("ManagerEffortCustomerProjects");
});
Now it works perfectly fine! Although it is kind of embarrassing, i will not delete this post. Maybe someone else will need some help to step off the hose...

Kendo grid dropdown issue

I have a view with tabs and each tab has a kendo grid with inline edit and have dropdown inside the grid. Problem which i am facing is when i update the value of the drop down is not showing the updated value but when i refresh the page the updated value is showing. But if i refresh the problem here is if i update the value is the sceond tab it i do refresh it will go to second tab. Is there any way I can acheive this without refesh.
#model BHI.TESQ.Entities.Interfaces.Models.ILocationAdminModel
#if (TempData["Result"] == "Data Saved Successfully")
{
<script>
alert('Location Data Saved Successfully');
</script>
}
#using (Html.BeginForm("SaveLocationAdmin", "Administration", FormMethod.Post))
{
<div style="margin-top: 45px;height:400px">
<h5 class="page-header k-block k-primary" style="overflow: hidden; margin-left: 5px; max-width: 1133px;">#ViewBag.Title</h5>
<table style="width: 100%; margin-top: 0px">
<tr style="margin-top: 0px;">
<td>
#*<table style="width: 100%">
<tr>
<td>*#
#(Html.Kendo().Splitter()
.Name("vertical")
.HtmlAttributes(new { style = "min-height:400px" })
.Orientation(SplitterOrientation.Horizontal)
.Panes(verticalPanes =>
{
verticalPanes.Add()
.Size("150px")
.HtmlAttributes(new { style = "min-height:400px" })
.Scrollable(false)
.Resizable(false)
.Content(Html.Action("AdminLinks").ToString());
verticalPanes.Add()
.HtmlAttributes(new { id = "top-pane" })
.Scrollable(false)
.Collapsible(false)
.Content(
Html.Kendo().Splitter()
.Name("horizontal")
.HtmlAttributes(new { style = "min-height:400px" })
.Panes(horizontalPanes =>
{
horizontalPanes.Add()
.HtmlAttributes(new { id = "left-pane" })
.Size("300px")
.Collapsible(true)
.Resizable(false)
.Content(#<div class="pane-content">
<h6 class="header k-block">Create New Location</h6>
<table>
<tr>
<td class="td-style">Location Name<span class="asterisk_input"></span></td>
<td>
<input id="txtLocName" name="txtLocName" type="text" class="textbox" required />
</td>
</tr>
<tr>
<td class="td-style">Country<span class="asterisk_input"></span></td>
<td>
#(Html.Kendo().DropDownList()
.Name("ddCountry")
.HtmlAttributes(new { required = "required" })
//.BindTo(new List<string>() {
// "United States",
// "United Kingdom (UK)",
// })
.BindTo(#Model.Country)
.OptionLabel("--Select Country--")
.DataTextField("CountryName")
.DataValueField("CountryId")
.Events(e => e.Change("OnCountryChange"))
)
<input type="hidden" id="hddCountry" name="hddCountry" value="" />
</td>
</tr>
<tr>
<td class="td-style">State</td>
<td>
#(Html.Kendo().DropDownList()
.Name("ddState")
.OptionLabel("--Select State--")
.DataTextField("StateName")
.DataValueField("StateId")
.Events(e => e.Change("OnStateChange"))
//.BindTo(new List<string>() {
// "Texas",
// })
.DataSource(source =>
{
source.Read(read => { read.Action("GetStateList", "Administration").Data("filterState"); }).ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom("ddCountry")
)
<script>
function filterState() {
return {
countryId: $("#ddCountry").val()
};
}
</script>
<input type="hidden" id="hddState" name="hddState" value="" />
</td>
</tr>
<tr>
<td class="td-style">Location Status<span class="asterisk_input"></span></td>
<td>
#*#(Html.Kendo().DropDownList()
.Name("ddLocStatus")
.BindTo(new List<string>() {
"Active",
"In-Active",
})
)*#
<input id="chkBoxStatus" type="checkbox" name="chkBoxStatus" value="true" />
</td>
</tr>
<tr>
<td align="right">
#(Html.Kendo().Button()
.Name("btnInsert")
.Events(ev => ev.Click("onClick"))
.HtmlAttributes(new { type = "submit", #class = "btn btn-primary button" })
.Content("Save"))
</td>
<td>
#(Html.Kendo().Button()
.Name("btnCancel")
.HtmlAttributes(new { type = "button", #class = "btn btn-primary button" })
.Content("Cancel"))
</td>
</tr>
</table>
</div>
);
horizontalPanes.Add()
.HtmlAttributes(new { id = "center-pane" })
.Scrollable(false)
.Content(#<div>
#(Html.Kendo().Grid(Model.Locations)
.Name("Grid")
.HtmlAttributes(new { style = "min-height:400px" })
.Columns(columns =>
{
columns.Command(command => { command.Edit().HtmlAttributes(new { type = "button", #class = "btn btn-primary button" }); }).Width(100);
columns.Bound(p => p.LocationId).Width(140).Hidden(true);
columns.Bound(p => p.LocationName).Width(140);
columns.Bound(p => p.CountryId).EditorTemplateName("CountryNames").Title("CountryName").ClientTemplate("#:CountryName#").Width(150);
columns.Bound(p => p.StateId).EditorTemplateName("StateNames").Title("StateName").ClientTemplate("#:StateName#").Width(150);
columns.Bound(p => p.IsActive).Width(100);
})
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable()
.Navigatable()
.Sortable()
.Scrollable()
.Groupable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.ServerOperation(false)
.Events(events => { events.Error("error_handler"); events.RequestEnd("onRequestEnd"); })
.Model(model => { model.Id(p => p.LocationId); model.Field(p => p.LocationId).Editable(false); })
.Update(update => update.Action("Update_Location", "Administration"))
)
)
</div>
);
}).ToHtmlString()
);
})
)
</td>
</tr>
</table>
#*</td>
</tr>
</table>
*#
</div>
}
<style scoped>
#vertical {
width: 95%;
}
.pane-content {
width: 300px;
}
div.k-grid-content {
min-height: 300px;
}
</style>
<script type="text/javascript">
function error_handler(e) {
if (e.errors) {
var message = "Errors:\n";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
alert(message);
var grid = $("#Grid").data("kendoGrid");
grid.cancelChanges();
}
}
$(document).ready(function () {
$('#btnCancel').click(function () {
$(':input').not(':button, :submit, :reset, :hidden').val('')
$('input:checkbox').removeAttr('checked')
var dropdownlist = $("#ddCountry").data("kendoDropDownList");
dropdownlist.select(0);
var dropdownlist = $("#ddState").data("kendoDropDownList");
dropdownlist.select(0);
});
});
function onClick(e) {
var locationName = $("#txtLocName").val();
if (locationName != "") {
var selectedText = $("#ddCountry").data("kendoDropDownList").text();
if (selectedText == "--Select Country--") {
alert('Please select country');
}
}
}
function OnCountryChange(e) {
var selectedText = $("#ddCountry").data("kendoDropDownList").text()
$("#hddCountry").val(selectedText);
}
function OnStateChange(e) {
var selectedText = $("#ddState").data("kendoDropDownList").text()
$("#hddState").val(selectedText);
}
function onRequestEnd(e) {
if (e.type == "create" || e.type == "update") {
if (e.response == null || e.response.Errors == null) {
alert("Location Data Updated Successfully");
}
}
}
</script>
Ok. So taking your code sample and assuming a couple of things:
Your code:
public ActionResult Update_Parameter([DataSourceRequest] DataSourceRequest request, Parameter UpdatedParameter)
{
try
{
mTestAdminLogic.SaveModel((ITestAdminModel)model, ViewBag.ApplicationId, Operation.UpdateParameter);
}
catch (Exception ex)
{
ModelState.AddModelError("ParameterUpdateError", ex.Message);
}
return RedirectToAction("TestAdmin");
}
and these are my changes:
public JsonResult Update_Parameter([DataSourceRequest] DataSourceRequest request, Parameter UpdatedParameter)
{
var returnModel = {your return model here};
try
{
returnModel = mTestAdminLogic.SaveModel((ITestAdminModel)model, ViewBag.ApplicationId, Operation.UpdateParameter);
}
catch (Exception ex)
{
ModelState.AddModelError("ParameterUpdateError", ex.Message);
}
return Json(new[] { returnModel }.ToDataSourceResult(request, ModelState), JsonRequestBehavior.DenyGet);
}
So let me explain.
If this action is only being used to update the Grid then change it to a JsonResult as the result of the grid update will be expecting JSON back.
I am assuming you have left our the declaration of your Data Layer logic and have cut it down to this single line:
mTestAdminLogic.SaveModel((ITestAdminModel)model, ViewBag.ApplicationId, Operation.UpdateParameter);
now if this model is different to the one expected by the grid the resulting action of this line should return back the appropriate model that the grid is expecting. As you have not declared that in your grid I am assuming it is some kind of LocationBasedModel.
Now once this update has completed then you should be returning back the appropriate model and adding the following Using statement using Kendo.Mvc.Extensions; this will give you access to the .ToDataSourceResult() extension method which will then allow you to transform this single model back to the grid and let the grid update its view of the data. Including the request and modelstate will also provide any errors and apply any existing filtering etc. back to the grid.
This would resolve the issue with the page "refreshing" itself everytime this action is called.
Any issues let me know and I will update my answer to reflect any changes you need.

Best approach for extending unobtrusive javascript in MVC3 to add a style to a div client side

I'm using html5/Razor/MVC3 leveraging the Bootstrap template from Twitter. I want to have form validation that looks slick like they've documented (http://twitter.github.com/bootstrap/#forms). So if we take a look at how the standard boiler-plate MVC3 for account registration, the markup would look like:
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { #class="form-stacked" })) {
#Html.ValidationSummary(true, "Snap! Something went wrong")
<div>
<fieldset>
<legend>Account Information</legend>
<div class="clearfix error">
#Html.LabelFor(m => m.UserName)
<div class="input">
#Html.TextBoxFor(m => m.UserName)
<span class="help-inline">#Html.ValidationMessageFor(m => m.UserName)</span>
</div>
</div>
<div class="clearfix">
#Html.LabelFor(m => m.Email)
<div class="input">
#Html.TextBoxFor(m => m.Email)
<span class="help-inline">#Html.ValidationMessageFor(m => m.Email)</span>
</div>
</div>
<div class="clearfix">
#Html.LabelFor(m => m.Password)
<div class="input">
#Html.PasswordFor(m => m.Password)
<span class="help-inline">#Html.ValidationMessageFor(m => m.Password)</span>
</div>
</div>
<div class="clearfix">
#Html.LabelFor(m => m.ConfirmPassword)
<div class="input">
#Html.PasswordFor(m => m.ConfirmPassword)
<span class="help-inline">#Html.ValidationMessageFor(m => m.ConfirmPassword)</span>
</div>
</div>
</fieldset>
<div class="actions">
<button class="btn large primary" type="submit">Register</button>
</div>
</div>
What I want to do is have the container div inject the "error" class like I've hard-coded in the first input. (So upon entering the page, the div would have a class of "clearfix" but if that input block failed validation, it would tag it as "clearfix error"). I figure I'm going to have to update the div block to include an id of some sort and perhaps add a new data- attribute to the ValidationMessage. I don't have a problem extending the ValidationMessageFor helper. I'm just not 100% sure what the approach should be for extending the library that's there. Any suggestions on how to approach this?
TIA.
UPDATE:
I am thinking this approach is reasonable:
<div id="UserNameContainer" class="clearfix error">
#Html.LabelFor(m => m.UserName)
<div class="input">
#Html.TextBoxFor(m => m.UserName)
<span class="help-inline">#Html.ValidationMessageFor(m => m.UserName, null, new { #data_container = "UserNameContainer" })</span>
</div>
</div>
By decorating my validation message with a data-container name, I could then target the container div. Now I just need to figure out how to intercept the validation message.
The $.validator.setDefaults method solved this issue for me with Bootstrap from Twitter. I'm usingjquery.validate.js and jquery.validate.unobtrusive.js.
Since unobtrusive validation on DOM ready scans your document and caches unobtrusive validation options for each form it encounters, it is needed to call the $.validator.setDefaults method before document scan occurs.
// setup defaults for $.validator outside domReady handler
$.validator.setDefaults({
highlight: function (element) {
$(element).closest(".clearfix").addClass("error");
},
unhighlight: function (element) {
$(element).closest(".clearfix").removeClass("error");
}
});
$(document).ready(function() {
// do other stuff
});
Came accross the same issue. I am tackling it by adding and extesion to the HtmlHelper Class.
This is what I did for the ValidationSummary:
public static class TwitterBootstrapHelperExtensions
{
public static MvcHtmlString BootstrapValidationSummary(this HtmlHelper helper,
bool excludePropertyErrors,
string message)
{
if(helper.ViewData.ModelState.Values.All(v => v.Errors.Count == 0)) return new MvcHtmlString(string.Empty);
string errorsList = "<ul>";
foreach (var error in helper.ViewData.ModelState.Values.Where(v => v.Errors.Count >0))
{
errorsList += string.Format("<li>{0}</li>", error.Errors.First().ErrorMessage);
}
errorsList += "</ul>";
return new MvcHtmlString(string.Format("<div class=\"alert-message error\"><span>{0}</span>{1}</div>",message,errorsList));
}
}
And in the .cshtml file I replace Html.ValidationSummary with this:
#Html.BootstrapValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.")
Remember to add the namespance of your extension class in the views folder web.config file.
I will post here later if I tackle the individual input item before you.
HTH
Rather than reinventing this particular wheel, check the validationEngine plugin available at http://www.position-absolute.com/articles/jquery-form-validator-because-form-validation-is-a-mess/.
You can customize the popup elements as you want, and it is trivial to connect to jQuery.validate.js.
I prefere to change the CSS of bootstrap.
Just added the classes of jQuery validate in the right place.
field-validation-error and input-validation-error
form .clearfix.error > label, form .clearfix.error .help-block, form .clearfix.error .help-inline, .field-validation-error {
color: #b94a48;
}
form .clearfix.error input, form .clearfix.error textarea, .input-validation-error {
color: #b94a48;
border-color: #ee5f5b;
}
form .clearfix.error input:focus, form .clearfix.error textarea:focus, .input-validation-error:focus {
border-color: #e9322d;
-webkit-box-shadow: 0 0 6px #f8b9b7;
-moz-box-shadow: 0 0 6px #f8b9b7;
box-shadow: 0 0 6px #f8b9b7;
}
You can integrate MVC3 validation with Bootstrap framework by adding the following javascript to your page (View)
<script>
$(document).ready(function () {
/* Bootstrap Fix */
$.validator.setDefaults({
highlight: function (element) {
$(element).closest("div.control-group").addClass("error");
},
unhighlight: function (element) {
$(element).closest("div.control-group").removeClass("error");
}
});
var current_div;
$(".editor-label, .editor-field").each(function () {
var $this = $(this);
if ($this.hasClass("editor-label")) {
current_div = $('<div class="control-group"></div>').insertBefore(this);
}
current_div.append(this);
});
$(".editor-label").each(function () {
$(this).contents().unwrap();
});
$(".editor-field").each(function () {
$(this).addClass("controls");
$(this).removeClass("editor-field");
});
$("label").each(function () {
$(this).addClass("control-label");
});
$("span.field-validation-valid, span.field-validation-error").each(function () {
$(this).addClass("help-inline");
});
$("form").each(function () {
$(this).addClass("form-horizontal");
$(this).find("div.control-group").each(function () {
if ($(this).find("span.field-validation-error").length > 0) {
$(this).addClass("error");
}
});
});
});
</script>
Besides, on the Views (for example "Create.cshtml") make sure that the fields in the form are formatted as the following...
<div class="editor-label">
#Html.LabelFor(Function(model) model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(Function(model) model.Name)
#Html.ValidationMessageFor(Function(model) model.Name)
</div>
With this solution, it will most likely be enough to just add a javascript without edit the View.
What I've done is taken the css classes for the validation errors and created a new css file with the same classes but with bootstrap values.
You can find it in a nuget package at: http://nuget.org/List/Packages/MahApps.Twitter.Bootstrap
That also provides some scaffolding templates to autocreate new views.
I needed to solve this using Bootstrap 3.1 and Razor. This is what I used:
$.validator.setDefaults({
highlight: function (element) {
$(element).parents(".form-group").addClass("has-error");
},
unhighlight: function (element) {
$(element).parents(".form-group").removeClass("has-error");
}
});
$(function () {
$('span.field-validation-valid, span.field-validation-error').each(function () {
$(this).addClass('help-block');
});
$('form').submit(function () {
if ($(this).valid()) {
$(this).find('div.form-group').each(function () {
if ($(this).find('span.field-validation-error').length == 0) {
$(this).removeClass('has-error');
}
});
}
else {
$(this).find('div.form-group').each(function () {
if ($(this).find('span.field-validation-error').length > 0) {
$(this).addClass('has-error');
}
});
}
});
$('form').each(function () {
$(this).find('div.form-group').each(function () {
if ($(this).find('span.field-validation-error').length > 0) {
$(this).addClass('has-error');
}
});
});
});
This is a combination of #german's answer and help from this post by "theBraindonor". Updated to use new Bootstrap 3 classes.

Resources