Unable to get the value of the combo set to the viewmodel - kendo-ui

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()
}
}

Related

Unable to retrieve the hidden element in partial view from main view

I have implemented kendo combobox on my MVC5 view and want the combobox to be filtered based on the value in my model. I need to retrieve the value from my model. I have currently bound that value to a hidden field called CountryCode in my partial view. The script is in my main view. I am getting error message undefined while trying to access the hidden field. The model is definitely getting populated with the CountryCode.
#using System.Collections
#model CC.GRP.MCRequest.ViewModels.RequestStatusUpdateViewModel
#{
Layout = null;
}
<div class="k-popup-edit-form k-window-content k-content" >
<div class="k-edit-form-container">
#Html.HiddenFor(model => model.CountryCode)
<div class="editor-label">
#Html.LabelFor(model => model.RequestID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.RequestID, new { htmlAttributes = new { #readonly = "readonly" } })
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ProjectName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ProjectName, new { htmlAttributes = new { #readonly = "readonly" } })
</div>
<div class="editor-label">
#Html.LabelFor(model => model.RequestStatus)
</div>
<div class="editor-field">
#(Html.Kendo().ComboBoxFor(model => model.RequestStatusCode)
.HtmlAttributes(new { style = "width:100%" })
.DataTextField("Status")
.Placeholder("Select...")
.DataValueField("RequestStatusCode")
.AutoBind(false)
.Filter("contains")
.DataSource(dataSource => dataSource
.Read(read =>
{
read.Action("GetRequestStatus", "Request")
.Type(HttpVerbs.Post)
.Data("GetCountryCodeFilter");
}).ServerFiltering(true)
)
)
</div>
#Html.ValidationMessageFor(model => model.RequestStatusCode, "", new { #class = "text-danger" })
</div>
</div>
Controller method that populates the combo
public ActionResult GetRequestStatus(string countryCode)
{
var response = requestRepository.GetRequestStatus(countryCode).AsQueryable().ProjectTo<RequestStatusViewModel>();
var jsonResult = Json(response, JsonRequestBehavior.AllowGet);
jsonResult.MaxJsonLength = int.MaxValue;
return jsonResult;
}
Controller method that loads the view
public ActionResult RequestStatus(int requestId, string projectName, string countryCode)
{
RequestStatusUpdateViewModel reqeustStatusUpdateViewModel = new RequestStatusUpdateViewModel();
reqeustStatusUpdateViewModel.RequestID = requestId;
reqeustStatusUpdateViewModel.ProjectName = projectName;
reqeustStatusUpdateViewModel.CountryCode = countryCode;
if (!ModelState.IsValid)
{
// return View("NewRequestView", Mapper.Map<RequestStatusViewModel>(newReqeustViewModel));
return null;
}
return View("_RequestStatusView", Mapper.Map<RequestStatusUpdateViewModel>(reqeustStatusUpdateViewModel));
}
RequestStatusViewModel
public class RequestStatusViewModel
{
public string RequestStatusCode { get; set; }
public string Status { get; set; }
public int DisplaySequenceNo { get; set; }
}
Script in the main view
function GetCountryCodeFilter() {
alert("Hello");
alert($('#CountryCode').val());
return { countryCode: $('#CountryCode').val() }
};
I'm assuming this is a popup from a kendo grid. The problem is that view gets serialized and sent to the popup when any row is clicked. It doesn't bind the data like you expect in MVC - it sends the same serialized data every time. See here.
So change your hidden to use kendo's MVVM binding so each instance gets the value from the grid row. (CountryCode needs to exist in the grid's datasource):
#Html.HiddenFor(x => x.CountryCode, new { data_bind = "value: CountryCode" }) // underscore becomes dash
Or you could just use:
<input type="hidden" name="CountryCode" id="CountryCode" data-bind = "value: CountryCode"/>

populating textboxes based on selection of kendo combo box

I need to populate two textbox controls based on a selection of combo box in my MVC 5 application. The combo box is a kendo MVC control. The values that need to be assigned to the text box controls are there in the collection that is bound to the combo box control. Could somebody let me know how to go about it. Does this need to be handled in javascript/ jquery or is it handled in kendo combo box events. An example would be great.
Combo box
#Html.LabelFor(model => model.Name1, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-4">
<div class="editor-field">
#(Html.Kendo().ComboBoxFor(model => model.Name1)
.HtmlAttributes(new { style = "width:300px" })
.DataTextField("Name1")
.DataValueField("CustomerMasterDataId")
.DataSource(dataSource => dataSource
.Read(read => read.Action("RequestHeader_CustomerData", "Request").Type(HttpVerbs.Post))
)
)
</div>
#Html.ValidationMessageFor(model => model.CustomerNumber, "", new { #class = "text-danger" })
</div>
Textbox
<div class="form-group">
#Html.LabelFor(model => model.CustomerNumber, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
<div class="editor-field">
#Html.EditorFor(model => model.CustomerNumber, new { htmlAttributes = new { #class = "form-control" } })
</div>
#Html.ValidationMessageFor(model => model.CustomerNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="clearfix"></div>
<div class="form-group">
#Html.LabelFor(model => model.CustomerGroup, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
<div class="editor-field">
#Html.EditorFor(model => model.CustomerGroup, new { htmlAttributes = new { #class = "form-control" } })
</div>
#Html.ValidationMessageFor(model => model.CustomerGroup, "", new { #class = "text-danger" })
</div>
</div>
Controller method that poulates the combo
public ActionResult RequestHeader_CustomerData()
{
var response = requestRepository.GetCustomerData().AsQueryable().ProjectTo<CustomerViewModel>();
var jsonResult = Json(response, JsonRequestBehavior.AllowGet);
jsonResult.MaxJsonLength = int.MaxValue;
return jsonResult;
}
Please note that the CustomerNumber and Name1 field would be used to populate the text boxes
ViewModel
public class CustomerViewModel
{
public int CustomerMasterDataId { get; set; }
public int CustomerNumber { get; set; }
[Display(Name = "Customer Name")]
public string Name1 { get; set; }
[Display(Name = "Customer Group")]
public string CustomerGroup { get; set; }
}
Yes, handle the change event:
#(Html.Kendo().ComboBoxFor(model => model.Name1)
.HtmlAttributes(new { style = "width:300px" })
.DataTextField("Name1")
.DataValueField("CustomerMasterDataId")
.DataSource(dataSource => dataSource
.Events(e => e.Change(onComboChange))
.Read(read => read.Action("RequestHeader_CustomerData", "Request").Type(HttpVerbs.Post))
)
)
Now handle it in js:
#section scripts
{
<script type="text/javascript">
function onComboChange(e) {
var dataItem = e.sender.dataItem();
if (dataItem) {
//set the value of text box (input)
$("#CustomerNumber").val(dataItem.CustomerNumber);
$("#CustomerGroup").val(dataItem.CustomerGroup);
};
};
</script>
}
Here is a js equivalent: http://jsfiddle.net/sg53719/74LwhebL/1/

Bind form.serialize() as custom object

I'm trying to send an AJAX post to an MVC action result and pass a custom object (ContactInformationModel) over as the parameter for the action result. However the expected type of the parameter is apparently not correct because the parameter is always null. I thought this was possible but maybe it's not?
My action result is:
[HttpPost]
public ActionResult UpdateContactInformation(ContactInformationModel model)
{
...
}
My jQuery:
//Serialize the ContactInformationModel object
var formData = $('#frmSubmitContactInformation').serialize();
// Submit ajax call
$.ajax({
url: "/api/[Redacted]/UpdateContactInformation",
type: "POST",
data: { model: formData },
cache: false,
success: function (data) {
if (data.Success) {
alert('success');
} else {
alert('fail');
}
}
});
My markup (ASP.NET MVC View):
#model [Redacted].Output.ContactInformationModel
<form id="frmSubmitContactInformation">
Add contact information to your project <button type="button" class="strip-button js-contact-launch js-edit-toggle"><span class="icon icon-edit"></span></button> <button class="btn btn--small btn--green add-half-left-margin js-submit-btn-contactinfo js-contact-launch js-edit-toggle hidden" type="submit">#Translation.Text("done")</button>
#*Done Button*#
<div class="js-contact-drawer hidden">
<div class="reveal-output__form column column--no-vert-padding add-half-bottom-margin add-half-top-margin form-group">
<div class="content-block">
#* First/Last/Company Name *#
<div class="content-block__third-column">
#Html.LabelFor(x => x.FirstName)
#Html.TextBoxFor(x => x.FirstName,
new
{
#Value = Model == null ? "" : Model.FirstName,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.LastName)
#Html.TextBoxFor(x => x.LastName,
new
{
#Value = Model == null ? "" : Model.LastName,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.CompanyName)
#Html.TextBoxFor(x => x.CompanyName,
new
{
#Value = Model == null ? "" : Model.CompanyName,
#class = "form-control"
})
</div>
</div>
<div class="content-block">
#* Email/Phone *#
<div class="content-block__third-column">
#Html.LabelFor(x => x.EmailAddress)
#Html.ValidationMessageFor(x => x.EmailAddress)
#Html.TextBoxFor(x => x.EmailAddress,
new
{
#Value = Model == null ? "" : Model.EmailAddress,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.PhoneNumber)
#Html.ValidationMessageFor(x => x.PhoneNumber)
#Html.TextBoxFor(x => x.PhoneNumber,
new
{
#Value = Model == null ? "" : Model.PhoneNumber,
#class = "form-control"
})
</div>
</div>
<div class="content-block">
#* Address 1/Address 2 *#
<div class="content-block__third-column">
#Html.LabelFor(x => x.Address1)
#Html.TextBoxFor(x => x.Address1,
new
{
#Value = Model == null ? "" : Model.Address1,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.Address2)
#Html.TextBoxFor(x => x.Address2,
new
{
#Value = Model == null ? "" : Model.Address2,
#class = "form-control"
})
</div>
</div>
<div class="content-block">
#* City/State/Zip*#
<div class="content-block__third-column">
#Html.LabelFor(x => x.City)
#Html.TextBoxFor(x => x.City,
new
{
#Value = Model == null ? "" : Model.City,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.State)
#Html.DropDownListFor(x => x.State, AddressHelper.GetUnitedStatesListItems(), Translation.Text("state"), new {#class = "custom-select"})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.PostalCode)
#Html.ValidationMessageFor(x => x.PostalCode)
#Html.TextBoxFor(x => x.PostalCode,
new
{
#Value = Model == null ? "" : Model.PostalCode,
#class = "form-control"
})
</div>
</div>
<input type="hidden" name="ProjectId" value="#Model.ProjectId" />
</div>
</div>
</form>
I'm positive that the class referenced in the view is the exact same as I am referencing in the controller. Also, the JS runs fine itself. What could be the issue?
Paul,
The issue is your data object. You need to directly post your serialized form object as data.
$.ajax({
url: "/api/[Redacted]/UpdateContactInformation",
type: "POST",
data: formData,
cache: false,
success: function (data) {
if (data.Success) {
alert('success');
} else {
alert('fail');
}
}
});

MVC 5 Ajax form with field updates asynchronously and still supporting a Full form post

So I have been using MVC for a while but not a lot of Ajax.
So the issue i have is that I have a create view where the first field of the create view is a Date picker which on change i want ajax to change the selection dropdown of another field on the form. I have the Ajax update working , but the form Post (Create button), now only calls into the Ajax method on the controller. I want the Ajax post back to call the default method Create method on the Controller. So the Create form contains 3 fields
A date (which has the OnChange Ajax submit)
A drop down list of id's and text
other fields as required
I have included the model and cshtml view files (one the partial). The controller is just simply a method taking either the datetime value or the entire model.
So I have the code working where, when the date changes it updates the relevant LocalIds field, but because the 'create' button is inside the Ajax.BeginForm tags, when the create button is pressed, it generates an Ajax call, and I want it to generate a Form Post. What am i missing
CreateModel
public class IdsSelection
{
public string Id { get; set; }
public List<SelectListItem> Selections { get; set; }
}
public class CreateModel
{
[Display(Name="Local Id's")]
public IdsSelection LocalIds;
[Display(Name="Day")]
[Required, DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}",ApplyFormatInEditMode=true)]
public DateTime Date { get; set; }
[Required, Display(Name = "Other Value")]
[Range(1.0, 1000000.0, ErrorMessage ="Value must be greater than zero")]
public decimal OtherValue { get; set; }
public CreateModel()
{
Date = DateTime.Today;
}
}
CreateView.cshtml
#Model Demo.Models.CreateModel
....
#using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
UpdateTargetId = "changeid",
}))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date, new
{
htmlAttributes = new
{
autofocus = "autofocus",
#class = "form-control",
#Value = Model.Date.ToString("yyyy-MM-dd"),
onchange = "$(this.form).submit();"
}
})
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>
#Html.Partial("_ShowIds", Model.LocalIds)
<div class="form-group">
#Html.LabelFor(model => model.OtherValue, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.OtherValue, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.OtherValue, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
}
_ShowIds.cshtml
#model Demo.Models.IdsSelection
<div id="changeid" class="form-group">
#Html.Label("Local Id", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#if(Model.Selections.Count == 1) // one
{
#Html.HiddenFor(model => model.Id)
#Html.EditorFor(model => model.Selections[0].Text, new
{
htmlAttributes = new
{
#class = "form-control",
#readonly = "readonly",
}
})
}
else // more entries so show a dropdown
{
#Html.DropDownListFor(model => model.Id, Model.Selections, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model, "", new { #class = "text-danger" })
}
</div>
</div>
You have not shown you controller methods, but assuming the method which generates this view is named Create(), then create a corresponding POST method
[httpPost]
public ActionResult Create(CreateModel model)
for saving the data. The remove #using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions() { ..... ])) and replace with a normal form to post back to the server (and you can remove jquery.unobtrusive-ajax.min.js)
#using (Html.BeginForm())
{
....
Next create a controller method that returns your partial view based on the selected date
public PartialViewResult FetchLocalIds(DateTime date)
{
IdsSelection model = // populate model based on selected date
return PartialView("_ShowIds", model);
}
Next, in the view, wrap the current #Html.Partial() in a placeholder element
<div id="localids">
#Html.Partial("_ShowIds", Model.LocalIds)
</div>
Then use jquery to handle the datepickers .change() event and call the FetchLocalIds() method to update the DOM using the .load() function.
$('#Date').change(function() {
$('#localids').load('#Url.Action("FetchLocalIds")', { date: $(this).val() })
})
Note also to remove onchange = "$(this.form).submit();" from the #Html.EditorFor(model => model.Date, new { ... })

How to retrieve users to a dropdownlist from AD with restful service

I have MVC3 project whit claim based authentication.
I've managed to get the sign in to work.
What I want to do now is to fill a DropDownList with with groups, then another DropDownlist with users belonging to this group.
As of now, I fill the DropDownlist with users which are from my local database.
This my method for getting the users from a certain office
private static void GetUsers(UsersContext.Format wFormat)
{
new UsersContext(new Uri("http://site/api/users"), wFormat)
.Users
.Where(x => x.Office.Equals("HomeOffice"))
.ToList()
.ForEach(
item =>
{
var user = item.DisplayName;
});
}
This how my controller get filled now:
public ActionResult Create()
{
var model = new TaskViewModel();
var subjectypes = createNKIRep.GetAllSubjectTypesById();
var customer = createNKIRep.GetAllCustomersByID();
var teams = createNKIRep.GetAllTeamsByID();
var users = createNKIRep.GetAllUsersByID();
model.Teams = new SelectList(teams, "Id", "Name");
model.Users = new SelectList(users, "Id", "Name");
model.SubjectTypes = new SelectList(subjectypes, "Id", "Name");
model.Company = new SelectList(customer, "Id", "CompanyName");
}
return View(model);
This my view where I fill the dropdownlist
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<h4>Get users to customer</h4>
<legend></legend>
<p>Subjecttype</p>
<div class="editor-field">
#Html.DropDownListFor(m => m.SubjectTypeName, Model.SubjectTypes, "Subjecttype", new { #class = "selectstyle" })
#Html.ValidationMessageFor(model => model.SubjectTypeName)
</div>
<p>Team</p>
<div class="editor-field">
#Html.DropDownListFor(model => model.TeamName, Model.Teams, "Team", new { #class = "selectstyle"})
#Html.ValidationMessageFor(model => model.TeamName)
</div>
<p>Users</p>
<div class="editor-field">
#Html.DropDownListFor(model => model.UserName, Model.Users, "Users", new { #class = "selectstyle"})
#Html.ValidationMessageFor(model => model.UsersName)
</div>
<p>Customer</p>
<div class="editor-field">
#Html.DropDownListFor(model => model.CompanyName, Model.Company, "Company", new { #class = "selectstyle" })
#Html.ValidationMessageFor(model => model.CompanyName)
</div>
So my problem is, that I don't know how to fill the Dropdownlist with the values from my AD using restful service. Any idea how it can be done?

Resources