How can i get the selected row KendoGrid Data Item?
I research a lot online and I came across this post http://dojo.telerik.com/egUpI which does exactly what i am looking for i would like implement the same.
I have the following code to populate grid in asp.net view. I need your help when row selected populate a elements.
Here is my Grid View:
<h1> Contacts</h1>
#{
var gridColumnSettings = new List<GridColumnSettings>
{
new GridColumnSettings
{
Member = nameof(Contact.Name),
MemberType = typeof(string)
},
new GridColumnSettings
{
Member = nameof(Contact.PhoneNumber),
MemberType = typeof(string)
}
};
var gridViewModel = new GridViewModel
{
Name = "ContactGrid", // Grid Name
Columns = gridColumnSettings,
AutoBind = true,
DataSourceSettings = new GridDataSourceSettings
{
ReadDataSource = new DataSourceSetting()
{
ActionName = "Contact",
ControllerName = "Contact",
HttpVerb = HttpVerbs.Get,
}
},
SelectionSettings = new GridSelectionSettings
{
IsSelectable = true, // To make grid selectable
GridSelectionMode = 0,
GridSelectionType = 0
},
}
};
}
Here is my Form on the same Page to display the selected grid row information
<form>
<h3>Name</h3>
<div class="col-sm-3">
<input type="text" readonly class="form-control " id="Name">
</div>
<h3>Phone</h3>
<div class="col-sm-3">
<input type="text" readonly class="form-control" id="Phone">
</div>
</form>
I tried this Jquery, but not working
<script>
function fillForm() {
$("#ContactGrid").kendoGrid({
change: function (e) {
var dataItem = this.dataItem(this.select());
fillForm(dataItem);
}
});
}
// Fill Form based on the selected row
var fillForm = function(dataItem) {
var columns = $("#ContactGrid").data("kendoGrid").options.columns;
var form = $("form");
for (var i = 0; i < columns.length; i++) {
var field = columns[i].field;
form.find("#" + field).val(dataItem[field]);
}
}
</script>
Related
I'm following this tutorial to create a modified version of a blog. In this case, the "posts" are the same things as "projects," the "tags" are called "technologies," and the comments are all the same. In this case, the create new post/project function also should be able to update existing posts/projects. When I click submit, however, editing an old post, it simply creates a new one.
Here is my controller:
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult Update(int? p, string title, string shortDescription, string longDescription, DateTime dateTime, string technologies)
{
Project project = GetProject(p);
if (!User.IsInRole("ChapterAdvisor") || !(User.Identity.GetFirstName() + " " + User.Identity.GetLastName()).Equals(project.ProjectLeader))
{
RedirectToAction("Index");
}
project.Title = title;
project.ShortDescription = shortDescription;
project.LongDescription = longDescription;
project.TimeCreated = dateTime;
project.ProjectLeader = User.Identity.GetFirstName() + " " + User.Identity.GetLastName();
project.Technologies.Clear();
technologies = technologies ?? string.Empty;
string[] technologyNames = technologies.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
foreach (string technologyName in technologyNames)
{
project.Technologies.Add(GetTechnology(technologyName));
}
if (!p.HasValue)
{
model.Projects.Add(project);
}
try
{
model.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
Exception raise = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
string message = string.Format("{0}:{1}",
validationErrors.Entry.Entity.ToString(),
validationError.ErrorMessage);
// raise a new exception nesting
// the current instance as InnerException
raise = new InvalidOperationException(message, raise);
}
}
throw raise;
}
return RedirectToAction("Details", new { p = project.Id });
}
public ActionResult Edit(int? p)
{
Project project = GetProject(p);
StringBuilder technologyList = new StringBuilder();
foreach (Technology technology in project.Technologies)
{
technologyList.AppendFormat("{0} ", technology.Name);
}
ViewBag.Technologies = technologyList.ToString();
return View(project);
}
private Technology GetTechnology(string technologyName)
{
return model.Technologies.Where(x => x.Name == technologyName).FirstOrDefault() ?? new Technology() { Name = technologyName };
}
private Project GetProject(int? id) => id.HasValue ? model.Projects.Where(x => x.Id == id).First() : new Project() { Id = -1 };
And this is my view:
<form action="#Href("~/Projects/Update")" method="post" id="postForm">
#Html.AntiForgeryToken()
#if (Model.Id != -1)
{
<input type="hidden" value="#Model.Id" />
}
#{ DateTime dateTime = Model.TimeCreated.Year > 2000 ? Model.TimeCreated : DateTime.Now; }
<input type="text" name="dateTime" value="#dateTime" /> Date<br />
<input type="text" name="title" value="#Model.Title" /> Project Name<br />
#Html.DropDownListFor(m => m.Technologies, new SelectList(new List<Object> { new { value = "Animation", text = "Animation" }, new { value = "Robotics", text = "Robotics" }, new { value = "Architecture", text = "Architecture" }, new { value = "CAD", text = "CAD" }, new { value = "Websites", text = "Websites" }, new { value = "Games", text = "Games" }, new { value = "Biotechnology", text = "Biotechnology" }, new { value = "Club", text = "Club" }, new { value = "Other", text = "Other" } }, "value", "text"), new { #style = "border: 1px solid #e8e8e8;padding: 0.5em 1.07em 0.5em;background: #f5f5f5;font-size: 0.875rem;border-radius: 5px;width: 100%;line-height: 1.43;min-height: 3.5em;" })
<textarea name="shortDescription" rows="5" cols="80">#Model.ShortDescription</textarea><br />
<textarea name="longDescription" rows="10" cols="80">#Model.LongDescription</textarea><br />
<input type="submit" name="submit" value="Save Changes" />
</form>
Any ideas why it is creating a new "project" instead of updating the one defined by the variable passed in the url?
Every post from that form is being treated as a "new" record because it doesn't contain the ID from an existing record. So the logic always assumes it's new.
This is because the hidden input isn't included in the POST data because it has no name:
<input type="hidden" value="#Model.Id" />
It looks like your action expects the ID value to be called "p":
<input type="hidden" name="p" value="#Model.Id" />
InquiryOrderViewModel
public class InquiryOrderViewModel
{
public InquiryOrder InquiryOrder { get; set; }
public List<InquiryOrderDetail> InquiryOrderDetails { get; set; }
}
InquiryOrderIndex View and the Script to add items
#model eKnittingData.InquiryOrderViewModel
#using (Html.BeginForm("Save", "InquiryOrder"))
{
<div id="editorRows">
#foreach (var item in Model.InquiryOrderDetails)
{
Html.RenderPartial("_DetailEditorRow", item);
}
</div>
#Html.ActionLink("Add another...", null, null, new { id = "addItem" })
<div class="col-md-6"> <input type="submit" value="Save" class="btn btn-success" /> </div>
}
<script>
$('#addItem').click(function (e) {
e.preventDefault();
var isExist = false;
$('.editorRow').each(function () {
if ($(this).children('.class01').val() == 0 || $(this).children('.class02').find("option:selected").text() == "Select") {
isExist = true;
return false;
}
});
if (isExist == false) {
$('.editorRow').each(function () {
$(".editorRow").children().attr("disabled", "disabled");
});
$.ajax({
url: '#Url.Action("BlankEditorRow", "InquiryOrder")',
cache: false,
success: function (data) {
$("#editorRows").append(data);
}
});
}
});
</script>
DetailEditorRow PartialView
#model eKnittingData.InquiryOrderDetail
#using eKnitting.Helpers
#using (Html.BeginCollectionItem("InquiryOrderDetails"))
{
<div class="editorRow">
#Html.DropDownListFor(a => a.ComponentId, (SelectList)ViewBag.CompList, "Select", new { Class = "class02" })
#Html.DropDownListFor(a => a.DesignCodeId, (SelectList)ViewBag.DCodeList, "Select", new { Class = "class03" })
#Html.TextBoxFor(a => a.NoOfParts, new { Class = "class01" })
delete
</div>
}
ActionResult which returns PartialView
public ActionResult BlankEditorRow()
{
var objContext = new KnittingdbContext();
ViewBag.CompList = new SelectList(objContext.Components, "ComponentId", "ComponentName");
ViewBag.DCodeList = new SelectList(objContext.DesignCodes, "DesignCodeId", "DesignCodeCode");
return PartialView("_DetailEditorRow", new InquiryOrderDetail());
}
ActionResult for 'GET'
var objContext = new KnittingdbContext();
var newIovm = new InquiryOrderViewModel();
var newIo = new InquiryOrder();
//initial item
var newIoD = new List<InquiryOrderDetail>
{
new InquiryOrderDetail()
};
newIovm.InquiryOrder = newIo;
newIovm.InquiryOrderDetails = newIoD;
ViewBag.CompList = new SelectList(objContext.Components, "ComponentId", "ComponentName");
ViewBag.DCodeList = new SelectList(objContext.DesignCodes, "DesignCodeId", "DesignCodeCode");
return View(newIovm);
ActionResult for 'POST'
public ActionResult Save(InquiryOrderViewModel inquiryOrderViewModel)
{
.................
}
When i click the add button im able to add items dynamically. But for PostBack it gives me only the lastly appended item. I checked it by putting a break point on post ActionResult. How can i get the whole collection for PostBack? Where did i go wrong? All help appreciated. Thanks!
Your scripts sets a variable var isExist = false;. When you add a new item, you check if the value is false (which it is if you got that far) and then disable all existing inputs.
Disabled form controls do not post back, hence you only get the values for the last row you have added.
Its unclear why you would want to disable them, but if you want to prevent editing of existing rows, the make them readonly
$(".editorRow").children().prop("readonly", true);
Working in Asp.Net MVC 3.
Controller Code:
[HttpPost]
public ActionResult MyChart(string sDate)
{
/*Call Entity Database*/
Contact_Center_DashboardEntities3 db = new Contact_Center_DashboardEntities3();
var results01 = db.sp_Report_Hybrid_Metrics("9 September", sDate, "Auto", "R2/R8", "Claims", "Claims", "R02_R08.AUTO.CLM.FMN.Q").ToList();
var chart = new Chart();
chart.Width = 1000;
chart.Height = 200;
var area = new ChartArea();
// configure your chart area (dimensions, etc) here.
chart.ChartAreas.Add(area);
area.AxisX.MajorGrid.Enabled = false;
area.AxisY.MajorGrid.Enabled = false;
area.AxisY2.MajorGrid.Enabled = false;
area.AxisY2.LabelStyle.Format = "0%";
// create and customize your data series.
var series = new Series();
foreach (var item in results01)
{
series.Points.AddXY(item.Date, item.Volume);
}
series.Font = new Font("Segoe UI", 8.0f, FontStyle.Bold);
series.ChartType = SeriesChartType.Column;
series.YAxisType = AxisType.Primary;
// create and customize your data series.
var seriesSecondary = new Series();
foreach (var item in results01)
{
seriesSecondary.Points.AddXY(item.Date, item.XferPer);
}
seriesSecondary.Font = new Font("Segoe UI", 8.0f, FontStyle.Bold);
seriesSecondary.ChartType = SeriesChartType.Line;
seriesSecondary.YAxisType = AxisType.Secondary;
seriesSecondary.LabelFormat = "0%";
seriesSecondary.IsValueShownAsLabel = true;
chart.Series.Add(series);
chart.Series.Add(seriesSecondary);
var returnStream = new MemoryStream();
chart.ImageType = ChartImageType.Png;
chart.SaveImage(returnStream);
returnStream.Position = 0;
return new FileStreamResult(returnStream, "image/png");
}
Tables View Code:
#using (Html.BeginForm("MyChart", "Home", FormMethod.Post))
{
<fieldset>
<div class="editor-field">
<input type="submit" value="09/06/2014" name = "sDate"/>
</div>
</fieldset>
}
When the user clicks the Submit button, the value passes to the "MyChart" ActionResult correctly, but then takes me to the MyChart view. What I need it to do is pass the value through, stay on the Tables View, and refresh the chart.
You could try something like this:
#using (Ajax.BeginForm("MyChart", "Home", new AjaxOptions{HttpMethod= "Post", UpdateTargetId = "chartContainer", InsertionMode = InsertionMode.Replace}))
{
<fieldset>
<div class="editor-field">
<input type="submit" value="09/06/2014" name = "sDate"/>
</div>
</fieldset>
}
<div id="chartContainer">
</div>
The request is done by ajax and inserts the response of the request into the element addressed by updatetargetid. If the submit button should be deleted after clicking it once, place the form inside the div. Otherwise the chart would be refreshed overtime you press the submit-button.
Ok so i have a view with this so far
function AppViewModel() {
this.title = ko.observable("#Model.Title");
this.firstName = ko.observable("#Model.FirstName");
this.lastName = ko.observable("#Model.LastName");
this.fullName = ko.computed(function () {
return this.title() + " " + this.firstName() + " " + this.lastName();
}, this);
}
#{
var jsList = Html.Raw(JsonConvert.SerializeObject(ViewBag.Countries));
}
function newViewModel() {
var theAppViewModel = new AppViewModel()
var g = ko.mapping.fromJS(theAppViewModel);
var viewModel = { vm: ko.observable([]) }
viewModel.vm = ko.mapping.fromJS(#jsList);
ko.applyBindings(g);
}
// Activates knockout.js
$(document).ready(function () {
ko.applyBindings(new newViewModel());
});
<ul style="list-style-type: none; float: left; margin-top: 20px; ">
<li>
#Html.LabelFor(model => model.Title)
<input data-bind="value: title"/>
</li>
<li>
#Html.LabelFor(model => model.FirstName)
<input data-bind="value: firstName" />
</li>
<li>
#Html.LabelFor(model => model.LastName)
<input data-bind="value: lastName" />
</li>
<li>
Full Name
<Span data-bind="text: fullName"></Span>
</li>
<li>
Coutries:
<select data-bind="foreach: vm">
<option data-bind="text: CountryName"></option>
</select>
</li>
</ul>
My Controller has this on it,
public ActionResult Index()
{
//ViewBag.Message = "KO js in mvc 4";
ViewBag.Countries = new List<Country>(){
new Country()
{
Id = 1,
CountryName = "America",
Abbreviation = "USA"
},
new Country()
{
Id = 2,
CountryName = "United Kingdon",
Abbreviation = "UK"
},
new Country()
{
Id = 3,
CountryName = "Irland",
Abbreviation = "IRL",
}
};
var vm = new PersonViewModel()
{
Id = 1,
DateOfBirth = new DateTime(1993, 01, 22),
Title = "Miss",
FirstName = "Jamie",
LastName = "Oscar",
};
return View(vm);
}
I can return the List from the controller in a standard loop like this:
<select>
#foreach(var c in ViewBag.Countries)
{
<option>#c.CountryName</option>
}
</select>
But I would like to bind the results to the list Via Knockout.js.
Your current viewModel that is containing the countries list is not bound, the only bound View-Model is the g you're calling applyBinding() with. Also, there's no point calling applyBinding() twice (on the same element).
Try this instead:
$(document).ready(function() {
var vm = new AppViewModel();
vm.Countries = ko.mapping.fromJS(#jsList);
ko.applyBindings(vm);
});
<select data-bind="value: countryId,
options: Countries,
optionsText: 'CountryName',
optionsValue: 'Id'"></select>
Please keep in mind that the value directive is referring to the chosen CountryId of the person but you currently don't have such a field in your View-Model.
Consider adding it as well:
var vm = new PersonViewModel()
{
Id = 1,
DateOfBirth = new DateTime(1993, 01, 22),
Title = "Miss",
FirstName = "Jamie",
LastName = "Oscar",
CountryId = 1
};
function AppViewModel() {
this.title = ko.observable("#Model.Title");
this.firstName = ko.observable("#Model.FirstName");
this.lastName = ko.observable("#Model.LastName");
this.countryId = ko.observable(#Model.CountryId);
}
it has now come to my attention that I can now bind knockout Json result to a #html.DropDownListFor attribute helper and still bind my data from knockout I have a DropDown list that is populated by knockout json array object, but then also bind this to the MVC 4 model this can be then used in the controller and the passed back to WCF or Linq to SQL for database
#Html.DropDownListFor(m => m.SelectedAuthType,
(SelectList)Model.authlevellistItems,
new { id = "alddl", data_bind = " options: Countries, optionsText: 'CountryName', optionsValue: 'Id'" })
works perfectly with models now as well as JSON knockout results.
So I want to get a value of the dropdown (== id of the account) to insert a new transaction
Here below you can find my View:
<div id="content">
<h2>Overschrijving</h2>
<p id="topmsg">velden met een * zijn verplicht</p><p> </p>
<dl class="clearfix form">
#using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
#Html.ValidationSummary(true, "Gelieve alles correct in te vullen.")
<dt>#Html.Label("Rekening: *")</dt>
<dd>#Html.DropDownList("ddlAccounts")</dd>
<dt>#Html.Label("Begunstigde: *")</dt>
<dd>#Html.TextBox("ToAccountNumber")</dd>
<dt>#Html.Label("Bedrag: *")</dt>
<dd>#Html.TextBox("Amount", null, new { #class = "inpshort" })</dd>
<dt>#Html.Label("Mededeling: ")</dt>
<dd>#Html.TextBox("Message", null, new { #class = "inplong" })</dd>
<dd class="buttons">
<input type="submit" value="Bevestigen" />
<input type="submit" value="Annuleren" />
</dd>
}
</dl>
</div>
this is the Controller code:
public ActionResult Transfer(int? id) {
Holder h = Holder.GetHolderByHolderId(Convert.ToInt32(User.Identity.Name));
List<Account> holderAccounts = Account.GetAccountsByHolderId(h.Id);
List<SelectListItem> ddlHolderAccounts = new List<SelectListItem>();
ddlHolderAccounts.Add(new SelectListItem { Text = "selecteer...", Value = "-1", Selected = true });
foreach (Account acc in holderAccounts) {
if (acc.Id == id) {
ddlHolderAccounts.Add(new SelectListItem { Text = acc.Name, Value = acc.Id.ToString(), Selected = true });
} else {
ddlHolderAccounts.Add(new SelectListItem { Text = acc.Name, Value = acc.Id.ToString() });
}
}
ViewData["ddlAccounts"] = ddlHolderAccounts;
return View();
}
[HttpPost]
public ActionResult Transfer(Transaction tra) {
if (ModelState.IsValid) {
Transaction.InsertTransaction(tra.Amount, tra.Message, tra.FromAccountId, tra.ToAccountNumber);
}
return View(tra);
}
Now I searched a lot with Google, it's probably better to use the DropDownListFor to fill your drop down list? But could anyone show me an example?
By looking at your code, I can see that you're not passing a list of SelectListItems to the DropDownList helper. You can do this one of two ways.
1- Bind it to a property on your model:
#Html.DropDownListFor(x=>Model.Property, new List<SelectListItem> { new SelectListItem { Text = "Item1", Value = "Value1" })
Or
2- You can do it without binding to a model property like:
#Html.DropDownList("propertyName", new List<SelectListItem> { new SelectListItem { Text = "Item1", Value = "Value1" } })
If you're using the second approach then your controller action must accept "propertyName" as a parameter when submitting.
And don't forget to provide a list of SelectListItems to select from (which you're not doing in your code).
Hope this helps.
should be
#Html.DropDownListFor(x=>Model.Property, new List { new SelectListItem { Text = "Item1", Value = "Value1" }})