How to call the properties of a HTML Helper? - asp.net-mvc-3

How can i change the property to editable Text box? for instance
when I click a button the read only property will change to editable.
#Html.TextBoxFor(m => m.SName, new { #readonly="readonly"})
Thanks to #von v. here's the solution below
#Html.TextBoxFor(m => m.SName, new { #readonly="readonly"})
<button value="New" id="btnConfirm">New</button>
<script>
$("#btnConfirm").click(function(){
$("#SName").removeAttr('readonly');
});
</script>

You can do this in jquery:
$("#button_id").click(function() {
$("#Sname").removeAttr('readonly');
});
UPDATE:
having several #Html.TextBoxFor(m => m.SName, new {
#readonly="readonly"}) #Html.TextBoxFor(m => m.FName, new {
#readonly="readonly"}) #Html.TextBoxFor(m => m.LName, new {
#readonly="readonly"}) How can I call it on the javascript function.
You mean like this:
$("#button_id").click(function() {
$("#Sname").removeAttr('readonly');
$("#LName").removeAttr('readonly');
$("#FName").removeAttr('readonly');
});

Related

Unable to get the value of the combo set to the viewmodel

I have implemented the cascading feature of kendo drop down. While trying to save the information, I am not able to get the value of the combo in my viewmodel. If I comment the name attribute, I do get the value however I need the name attribute for the cascading feature to work. I was trying a workaround using jquery to set the model value but getting errors. Could somebody tell me how to fix this issue.
Sales Organisation Combo
<div class="form-group">
#Html.LabelFor(model => model.Company, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
<div class="editor-field">
#(Html.Kendo().ComboBoxFor(model => model.CountryCode)
.Name("SalesOrganisation")
.HtmlAttributes(new { style = "width:100%" })
.DataTextField("CompanyCodeCompany")
.DataValueField("CountryCode")
.Filter("contains")
.MinLength(3)
.DataSource(dataSource => dataSource
.Read(read => read.Action("RequestHeader_SalesOrganisation", "Request").Type(HttpVerbs.Post))
.ServerFiltering(true)
)
)
</div>
#Html.ValidationMessageFor(model => model.Company, "", new { #class = "text-danger" })
</div>
</div>
Sales Office combo
<div class="form-group">
#Html.LabelFor(model => model.SalesOffice, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
<div class="editor-field">
#(Html.Kendo().ComboBoxFor(model => model.SalesOfficeID)
// .Name("SalesOffice")
.HtmlAttributes(new { style = "width:100%" })
.DataTextField("SalesOffice")
.DataValueField("SalesOfficeID")
.AutoBind(false)
.Value("")
.DataSource(dataSource => dataSource
.Read(read =>
{
read.Action("RequestHeader_SalesOffice", "Request")
.Type(HttpVerbs.Post)
.Data("GetFilterOption");
}).ServerFiltering(true)
).CascadeFrom("SalesOrganisation").Filter("contains")
)
</div>
#Html.ValidationMessageFor(model => model.SalesOffice, "", new { #class = "text-danger" })
</div>
</div>
Javascript for cascading feature to work
function GetFilterOption() {
return {
id: $('#SalesOrganisation').val()
}
}
Javascript - Trying to set the model which doesnt work
function GetFilterOption() {
var countryCode = $('#SalesOrganisation').val();
var model = $('#SalesOrganisation').data('kendoComboBox');
model.value = countryCode;
return id = countryCode;
}
When you use .ComboBoxFor(), you should not use .Name().
When you use .ComboBoxFor(m => m.FieldName) then the id/name attribute will be set to "FieldName" by kendo's implementation of the Razor helper and matches the name of your model field.
If you then use .Name("SomeOtherFieldName"), you change the id/name attribute to "SomeOtherFieldName" and it no longer matches the field name of your model, which is why you no longer get the value.
What you want to do is not use .Name() and set up the .CascadeFrom() appropriately, i.e.
#(Html.Kendo().ComboBoxFor(model => model.CountryCode)
....
#(Html.Kendo().ComboBoxFor(model => model.SalesOfficeID)
.CascadeFrom("CountryCode")
function GetFilterOption() {
return {
id: $('#CountryCode').val()
}
}

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...

Radio Button doesn't reflect Model's value

I have a kendo Grid for a class, and for that class I've built an editor template to produce a radio button for one of the fields.
This radio button doesn't reflect propertie's value and is always false, although I've checked the value, by printing it on the form, and I'm sure it's true. If I set a default value for that field, the radio button will reflect that value, regardless of the real value of the field.
I should note that I'm using a client template to display a text for that field, and it works fine.
This is the Grid:
#(Html.Kendo().Grid<Class>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(x => x.BActive).ClientTemplate("#= BActive ? 'Open':'Close' #");
/// removed for brevity
})
.Editable(editable => editable.Mode(GridEditMode.PopUp))
.DataSource(ds => ds.Ajax()
.Model(model => {
model.Id(x => x.SWhCode);
model.Field(x => x.BActive).DefaultValue(true);
})
)
)
And this is the lines that produce the radio button inside the editorTemplate:
<label>
#Html.RadioButtonFor(x => x.BActive, true, new { #class = "radio-inline" }) Open
</label>
<label>
#Html.RadioButtonFor(x => x.BActive, false, new { #class = "radio-inline" }) Close
</label>
bool type will be render in client like this
true => True
false => False
Have you try to inspect your element rendered in HTML? You'll see that the bool value transform into capitalize string. To overcome this you should change true and false in radio button with type string too.
Your view code should be like this
<label>
#Html.RadioButtonFor(x => x.BActive, "true", new { #class = "radio-inline" }) Open
</label>
<label>
#Html.RadioButtonFor(x => x.BActive, "false", new { #class = "radio-inline" }) Close
</label>

changing Datasource of Kendoui Multiselect at runtime

I would like to bind data to a kendoui multiselect at runtime.
for example suppose that I want to bind it as a cascade of a drobdownlist.
any idea?
<p>
<label for="categories">Catergories:</label>
#(Html.Kendo().DropDownList()
.Name("categories")
.HtmlAttributes(new { style = "width:300px" })
.OptionLabel("Select category...")
.DataTextField("CategoryName")
.DataValueField("CategoryId")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeCategories", "CoreParam");
});
})
.Events(e =>e.Select("select"))
)
</p>
<p>
<label for="parameters">Parameters:</label>
#(Html.Kendo().MultiSelect()
.Name("parameters")
.HtmlAttributes(new { style = "width:400px" })
.DataTextField("ParamDesc")
.DataValueField("ParamCode")
.Placeholder("Select products...")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeParams", "CoreParam")
.Data("filterParams");
})
.ServerFiltering(true);
})
.AutoBind(false)
)
</p>
<script type="text/javascript">
function filterParams() {
return {
categories: $("#categories").val()
};
}
function select(e) {
var dropdownlist = $("#categories").data("kendoDropDownList");
dropdownlist.select(e.item.index());
var multiselect = $("#parameters").data("kendoMultiSelect");
multiselect.dataSource.read();
};
</script>
You could create a custom MVVM binder which will get the text of the dropdownlist and will set a property of the ViewModel. This property can be bound to the hidden field. Check out the link below for more information.

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