kendo scheduler not return date on server side using mvc - kendo-ui

I am having issue of using Kendo UI scheduler,
When I schedule task ,
Kendo UI start and end date not returning on server side.
Start and end date always return default date.
Here a Razor Code :
#model IEnumerable<Web.Models.PlantColor>
#{
ViewBag.Title = "Schedule View";
}
<h2>Schedule View</h2>
#(Html.Kendo().Scheduler<WorkScheduler.Web.Models.KendoSchedular>()
.Name("scheduler")
.Date(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day))
.StartTime(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 08, 00, 00))
.Height(600)
.Views(views =>
{
views.DayView();
views.WorkWeekView();
views.WeekView();
views.MonthView();
views.AgendaView();
})
.Resources(resource =>
{
resource.Add(m => m.PlantId)
.Title("Owner")
.DataTextField("Text")
.DataValueField("Value")
.DataColorField("Color")
.BindTo(Model);
})
.DataSource(d => d
.Model(m =>
{
m.Id(f => f.id);
})
.Read("ReadSchedule", "ScheduleView")
.Create("CreateSchedule", "ScheduleView")
.Destroy("Destroy", "ScheduleView")
.Update("Update", "ScheduleView")
)
)

Make sure that you have the start and end fields defined in your Model that you are posting back (and model inherits from ISchedulerEvent):
public class CalendarAppointmentViewModel : ISchedulerEvent
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Recurrence { get; set; }
public string StartTimezone { get; set; }
public string EndTimezone { get; set; }
private DateTime start;
public DateTime Start
{
get
{
return start;
}
set
{
start = value.ToUniversalTime();
}
}
private DateTime end;
public DateTime End
{
get
{
return end;
}
set
{
end = value.ToUniversalTime();
}
}
public string RecurrenceRule { get; set; }
public int? RecurrenceID { get; set; }
public string RecurrenceException { get; set; }
public bool IsAllDay { get; set; }

I can see this question is already accepted as best answer. Perhaps following might be helpful also for someone struggling to return Start/End dates from Editor of Kendo Scheduler.
I had same issue, and followed the solutions provided here, still no success. In my case defining the culture and creating a Model inherited from "ISchedulerEvent" was still returning default date to the server side in Create & Update events handler methods of the Controller.
For me problem was a missing .js file.
kendo.timezones.min.js
So for anyone who is in the same shoes like me, kindly look at your Scripts folder in the project, and if that .js file is missing.
And please follow these steps in setting up the project.

Related

Unable to bind data to Kendo Scheduler

I've got this Kendo Scheduler that is displayed in the View but without any data.
The Scheduler on the View:
#(Html.Kendo().Scheduler<ProjName.Models.ScheduleInspectionModel>()
.Name("scheduler")
.Views(views =>
{
views.DayView();
views.WorkWeekView();
views.WeekView();
views.MonthView(mv => mv.Selected(true));
views.AgendaView();
})
.Timezone("Etc/UTC")
.DataSource(d => d
.Read("ControllerName", "GetScheduleInspections")
)
)
The datasource invokes the controller method below:
public ActionResult GetScheduleInspections([DataSourceRequest]DataSourceRequest request)
{
ScheduleInspectionModel sim = new ScheduleInspectionModel();
var gsio = sim.getScheduleInspections();
List<ScheduleInspectionModel> list = new List<ScheduleInspectionModel>();
if (gsio.scheduleinspections != null)
{
foreach (wsScheduleInspection.scheduleInspectionOutput scheduleInspection in gsio.scheduleinspections)
{
ScheduleInspectionModel sim2 = new ScheduleInspectionModel
{
GlobalEquipConditionId = scheduleInspection.globalEquipmentCondition.id,
Description = scheduleInspection.globalEquipmentCondition.code,
Start = DateTime.Now,
End = DateTime.Now.AddHours(2),
Title = scheduleInspection.globalEquipmentCondition.code,
IsAllDay = true
};
list.Add(sim2);
}
}
return Json(list.ToDataSourceResult(request));
}
But this method is never run, despite being on the Scheduler Datasource property. It should run that method and return a list of inspections. I don't know why isn't the method being hit. With a Kendo Grid, for example, the method on the Datasource Read is hit as soon as the page is loaded.
Try making sure your definition has these two items as I think they are required.
.Date(new DateTime(2013, 6, 13))
.StartTime(new DateTime(2013, 6, 13, 7, 00, 00))
EDIT
I was able to get the following code to work:
Model
// NOTE: It's important that your model class implements ISchedulerEvent
public class TaskViewModel : ISchedulerEvent
{
public string Title { get; set; }
public string Description { get; set; }
public bool IsAllDay { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
public string StartTimezone { get; set; }
public string EndTimezone { get; set; }
public string RecurrenceRule { get; set; }
public string RecurrenceException { get; set; }
}
SchedulerController.cs
public class SchedulerController : Controller
{
// GET: Scheduler
public ActionResult Index()
{
var model = new SchedulerViewModel();
// In this case, it doesn't matter what this model is really since we're using AJAX binding
return View(model);
}
// I usually have my binding methods for Kendo use HttpPost
[HttpPost]
public ActionResult GetData([DataSourceRequest] DataSourceRequest request)
{
var data = new List<TaskViewModel>
{
new TaskViewModel
{
Start = new DateTime(2014, 12, 1, 8, 0, 0),
End = new DateTime(2014, 12, 1, 17, 0, 0),
Title = "Task 1"
}
};
return Json(data.ToDataSourceResult(request));
}
}
Index.cshtml (view)
#(Html.Kendo().Scheduler<TaskViewModel>()
.Name("scheduler")
.Views(views =>
{
views.DayView();
views.WorkWeekView();
views.WeekView();
views.MonthView(mv => mv.Selected(true));
views.AgendaView();
})
.Timezone("Etc/UTC")
.DataSource(d => d
.Read("GetData", "Scheduler")
))
If this doesn't work for you, I would make sure your versions (for Kendo, jQuery, etc) are correct. Hope this helps.
Yes, Scheduler read is called as soon as it is loeded. But it may not be getting data in proper format as it expects. So it is not able to bind the data. If you can check for these modification:
1) Define the "Model" in "DataSource" of scheduler as defined in this example.
2) Also the action method should return object of "MyModel" class(model on which scheduler is defined)
not "ScheduleInspectionModel" class.

KendoUI Scheduler

I am trying to implement the scheduler control to show live calculation of material usage on daily bases (in a week by week view).
I am unable to have the Usage data displayed in the cells although I managed to have to Materials displayed on the left hand side. I wonder if any one could help or give me some hints on what I am doing wrong. Here is my code so far:
I can be sure that data is being return to the view but the view is not showing the usage data, which is simply numeric values corresponding to a material on a specific day of the week. I have also attached a screenshot of how it looks like:
the Controller method to read the data:
public JsonResult Read([DataSourceRequest] DataSourceRequest request)
{
try
{
var usageList = new List<ReportUsageViewModel>();
var imports = _importRespository.GetImports();
foreach (var usageReportStoredProcedure in imports)
{
var usageViewModel = new ReportUsageViewModel();
usageViewModel.MaterialID = usageReportStoredProcedure.MaterialID;
usageViewModel.Start = usageReportStoredProcedure.ScanDate;
usageViewModel.End = usageReportStoredProcedure.ScanDate;
usageViewModel.DailyUsage = usageReportStoredProcedure.UsageQuantity;
usageViewModel.Title = usageReportStoredProcedure.UsageQuantity.ToString();
usageList.Add(usageViewModel);
}
return Json(usageList.ToDataSourceResult(request));
}
catch (Exception exc)
{
ErrorHelper.WriteToEventLog(exc);
return null;
}
}
The actual control
<div id="StockViewer">
#(Html.Kendo().Scheduler<WorcesterMarble.ViewModels.ReportUsageViewModel>()
.Name("StockViewer")
.Timezone("Europe/London")
.Resources(resource => resource.Add(m => m.MaterialID)
.Title("Materials")
.Name("Materials")
.DataTextField("Name")
.DataValueField("MaterialID")
.BindTo(Model.MaertiaList))
.MajorTick(270)
.MinorTickCount(1)
.StartTime(DateTime.Now.Date.AddHours(8))
.EndTime(DateTime.Now.Date.AddHours(17))
.AllDaySlot(false)
.Date(DateTime.Now.Date)
.Editable(false)
.Views(x => x.WeekView(v =>
{
v.Footer(false);
v.Selected(true);
v.DateHeaderTemplate("<span class='k-link k-nav-day'>#=kendo.toString(date, 'ddd dd/M')#</span>");
}))
.Group(group => group.Resources("Materials").Orientation(SchedulerGroupOrientation.Vertical))
.DataSource(d => d
.Model(m => {
m.Id(f => f.MaterialID);
m.Field(f => f.Title).DefaultValue("No title");
})
.Read("Read", "ReportUsage")
)
)
Update: This is the ViewModel implementing the ISchedulerEvent
public class ReportUsageViewModel : ISchedulerEvent
{
public int MaterialID { get; set; }
public string MaterialName { get; set; }
public int? DailyUsage { get; set; }
public List<MaterialViewModel> MaertiaList { get; set; }
public string Description { get; set; }
public System.DateTime End { get; set; }
public bool IsAllDay { get; set; }
public string RecurrenceException { get; set; }
public string RecurrenceRule { get; set; }
public System.DateTime Start { get; set; }
public string Title { get; set; }
}
The issue was in these two lines:
.StartTime(DateTime.Now.Date.AddHours(8))
.EndTime(DateTime.Now.Date.AddHours(17))
The data was there but these two lines were hiding it. The data was being logged at times outside the time range of 8 to 17 so I removed these two lines and then set the Major ticks to 1440, which is the total number of ticks in 24 hrs, which helped me hiding the time column as I didn't need it..

Telerik MVC Grid with Dynamic Columns at Run Time from a Collection or Dictionary

After spending the last couple days searching, I'm officially stuck. I'm working on a binding an object to the Telerik MVC 3 Grid, but the catch is that it needs to have dynamically created columns (not auto generated). Three of the columns are known, the others are unknown, and this is the tricky part. Basically, it can be like these examples:
KnownColumn1 | KnownColumn2 | UnknownColumn1 | KnownColumn3
KnownColumn1 | KnownColumn2 | UnknownColumn1 | UnknownColumn2 | UnknownColumn3 | KnownColumn3
etc.
Because I'm putting the unknown columns in a list (I've tried a dictionary too so I can get the column names), this has complicated things for me when binding. My code is below:
Model (There can be zero to hundreds of rows, but this model is in a view model of type List, there can also be 0 to 20 plus columns that are dynamically added)
public class VendorPaymentsGLAccount
{
public string GeneralLedgerAccountNumber { get; set; }
public string GeneralLedgerAccountName { get; set; }
public string DisplayName { get { return string.Format("{0} - {1}", GeneralLedgerAccountNumber, GeneralLedgerAccountName); } }
public Dictionary<string, double> MonthAmount { get; set; }
public double Total { get { return MonthAmount.Sum(x => x.Value); } }
public List<string> Columns { get; set; }
public List<double> Amounts { get; set; }
public VendorPaymentsGLAccount() { }
}
View (The section that's commented out was trying to use the dictionary)
<fieldset>
<legend>General Ledger Account Spend History</legend>
#if (Model.VendorPaymentsGLAccounts != null)
{
<br />
#(Html.Telerik().Grid(Model.VendorPaymentsGLAccounts)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(gl => gl.DisplayName).Title("General Ledger Account").Width(200).Filterable(false).Sortable(false);
//foreach (var month in Model.VendorPaymentsGLAccounts[0].MonthAmount)
//{
// //columns.Bound(gl => gl.MonthAmount[month.Key.ToString()].ToString()).Title(month.Key.ToString()).Width(100).Filterable(false).Sortable(false);
// //columns.Template(v => Html.ActionLink(v.VoucherID, "VoucherSummary", new { id = v.VoucherID, bu = v.BusinessUnitID, dtt = v.InvoiceDate.Ticks })).Title("Voucher").Width(100);
// columns.Template(gl => Html.ActionLink(gl.MonthAmount[month.Key.ToString()].ToString(), "VoucherSummary")).Title(month.Key.ToString()).Width(100);
//}
for (int i = 1; i <= (Model.VendorPaymentsGLAccounts[0].Columns.Count() - 1); i++)
{
string colTemp = Model.VendorPaymentsGLAccounts[0].Columns[i - 1];
columns.Template(gl => gl.Amounts[i - 1]).Title(colTemp).Width(100);
}
columns.Template(gl => String.Format("{0:C}", gl.Total)).Title("Total");
})
.Sortable()
.Pageable()
.Filterable()
.Footer(true))
}
else
{
<br />
#:There are no records that match your selected criteria.
}
</fieldset>
Using the dictionary approach, I was able to get the columns generated correctly with the right header text, but the values for the columns (in my testing there were only 2 columns) were the same. Can anyone help with this? This seems to be an oddball issue. Just trying to figure out how to do this correctly.
Update: Here is a screen shot using the dictionary approach that shows the issue. The column headings are correct, but the values are the same for both of the dynamic columns.
Using dynamically defined columns with the Telerik grid control can be tricky. But in your case, it's mainly a typical pitfall of closures.
In the following loop, the compiler will bind each instance of gl => gl.Amounts[i - 1] to the variable i and evaluate it later:
for (int i = 1; i <= (Model.VendorPaymentsGLAccounts[0].Columns.Count() - 1); i++)
{
string colTemp = Model.VendorPaymentsGLAccounts[0].Columns[i - 1];
columns.Template(gl => gl.Amounts[i - 1]).Title(colTemp).Width(100);
}
In fact, it's evaluated after the loop has finished. So i will always have the value that lead to the completion of the loop.
The fix is to use a temporary variable:
for (int i = 1; i <= (Model.VendorPaymentsGLAccounts[0].Columns.Count() - 1); i++)
{
string colTemp = Model.VendorPaymentsGLAccounts[0].Columns[i - 1];
int columnIndex = i - 1;
columns.Template(gl => gl.Amounts[columnIndex]).Title(colTemp).Width(100);
}
I had the same problem, and was googling plenty of hours around, and have done a lot of attempts from various assistance lines. But even so, it was not so trivial to solve!
And for that reason and to have also another working example here, I will provide also my solution!
Information: It only works at my place with an IList Model. Other collections had also caused problems!
#model IList<CBS.Web.Models.Equipment.EquipmentViewModel>
#(Html.Telerik().Grid(Model)
.Name("Grid")
.DataKeys(keys =>
{
keys.Add(m => m.ID);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
// renders the grid initially
.Select("EquipmentGrid", "Equipment");
})
.Columns(columns =>
{
// Equipment IDs
columns.Bound(m => m.ID).Hidden(true);
columns.Bound(m => m.Name).Title("Equipments").Width(200);
// Every item (EquipmentViewModel) of the Model has the same Count of Fields
for (int i = 0; i < (Model[0].Fields.Count()); i++)
{
// Name of the column is everytime same as in Model[0]
string columnName = Model[0].Fields.ElementAt(i).FieldDefinition.Name;
// Constructs i-counted columns, dynamically on how much
// Fields are owned by an Equipment. But note, that all Equipment-items
// in the Model must have the same Count and disposal of Fields!
columns.Template(m => m.Fields
.Where(f => f.FieldDefinition.Name == columnName)
.Where(f => f.EquipmentId == m.ID).First().Value)
.Title(columnName)
.Width(columnName.Length * 8); // * 8 was the optimal lenght per character
}
})
.ClientEvents(events => events.OnRowSelect("onRowSelected"))
.Selectable()
.Resizable(resizing => resizing.Columns(true))
.Pageable()
.Scrollable()
.Groupable()
.Filterable()
)
Controller:
public ActionResult EquipmentGrid(Guid id)
{
var belongingEquipments = _equipmentRepository.GetNotDeleted()
.OrderBy(e => e.Name).ToList()
.Where(e => e.RevisionId == id);
List<EquipmentViewModel> equVMList = new List<EquipmentViewModel>();
for (int i = 0; i < belongingEquipments.Count(); i++)
{
var equVM = new EquipmentViewModel
{
ID = belongingEquipments.ElementAt(i).ID,
Name = belongingEquipments.ElementAt(i).Name,
RevisionId = belongingEquipments.ElementAt(i).RevisionId,
EquipmentTypeId = belongingEquipments.ElementAt(i).EquipmentTypeId,
Fields = SortFields(belongingEquipments.ElementAt(i).Fields.ToList())
};
equVMList.Add(equVM);
}
return PartialView("EquipmentGrid", equVMList);
}
Models:
namespace CBS.Web.Models.Equipment
{
public class EquipmentViewModel
{
public Guid ID { get; set; }
public string Name { get; set; }
public Guid RevisionId { get; set; }
public Guid EquipmentTypeId { get; set; }
public virtual ICollection<FieldEntity> Fields { get; set; }
}
}
FieldDefinition
namespace CBS.DataAccess.Entities
{
public class FieldDefinitionEntity : EntityBase
{
[Required]
public virtual Guid EquipmentTypeId { get; set; }
public virtual EquipmentTypeEntity EquipmentType { get; set; }
[Required(AllowEmptyStrings = false)]
public virtual string Name { get; set; }
public virtual int Numbering { get; set; }
[Required]
public virtual Guid TypeInformationId { get; set; }
public virtual TypeInformationEntity TypeInformation { get; set; }
public virtual ICollection<FieldEntity> Fields { get; set; }
}
}
Field
namespace CBS.DataAccess.Entities
{
public class FieldEntity : EntityBase
{
[Required]
public virtual Guid EquipmentId { get; set; }
public virtual EquipmentEntity Equipment { get; set; }
[Required]
public virtual Guid FieldDefinitionId { get; set; }
public virtual FieldDefinitionEntity FieldDefinition { get; set; }
public virtual string Value { get; set; }
}
}
I dynamically bind the columns at runtime with reflection:
#model IEnumerable<object>
#using System.Collections
#using System.Collections.Generic
#using System.Reflection;
#(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
Type t = Model.GetType().GetGenericArguments()[0];
foreach (var prop in t.GetProperties())
{
if (IsCoreType(prop.PropertyType))
{
columns.Bound(prop.PropertyType, prop.Name);
}
}
})
.DataBinding(binding => binding.Ajax()
.Select("SelectMethod", "SomeController")
)
.Sortable()
.Pageable()
.Filterable()
.Groupable()
)
#functions{
public bool IsCoreType(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
return IsCoreType(type.GetGenericArguments()[0]);
}
return !(type != typeof(object) && Type.GetTypeCode(type) == TypeCode.Object);
}
}
Here is the workaround:
#(Html.Telerik().Grid(Model.Users)
.Name("Grid")
.Columns(columns => {
columns.GenerateCustomColumns(columnSettings);
}).DataBinding(dataBinding => dataBinding.Ajax().Select("_getusers", "home"))
.Scrollable(scrolling => scrolling.Enabled(true).Height("auto"))
.Pageable(paging => paging.Enabled(true)
.PageSize(10, new int[] { 5, 10, 20, 50, 100, 500 })
.Position(GridPagerPosition.Both)
.Total(Model.Users.Count)
.Style(GridPagerStyles.PageSizeDropDown | GridPagerStyles.NextPreviousAndNumeric)
.PageTo(1))
.Filterable(filtering => filtering.Enabled(true))
.Reorderable(reordering => reordering.Columns(true))
.NoRecordsTemplate(" ")
.EnableCustomBinding(true)
)
// Extension method to genarate columns dynamically
public static class TelerikMvcGridColumnHelper
{
public static void GenerateCustomColumns<T>(this GridColumnFactory<T> columns,List<GridCustomColumnSettings> settings) where T:class
{
if (settings != null)
{
settings.ForEach(column =>
{
var boundedColumn = columns.Bound(column.Member);
if (column.ClientFooterTemplate != null)
boundedColumn.ClientFooterTemplate(column.ClientFooterTemplate);
if (!string.IsNullOrEmpty(column.Width))
boundedColumn.Width(column.Width);
});
}
}
}
// Column settings class
public class GridCustomColumnSettings : GridColumnSettings
{
public string ClientFooterTemplate { get; set; }
}
I did this simple way. NOTE : the following solution works in ajax edit mode too (not just a read-only grid) :
when the ViewModels are :
public class PriceSheetEditGridViewModel
{
public IEnumerable<PriceSheetRowViewModel> Rows { get; set; }
public IEnumerable<PriceSheetColumnViewModel> Columns { get; set; }
}
public class PriceSheetColumnViewModel
{
public int Id { get; set; }
public string Title { get; set; }
}
public class PriceSheetRowViewModel
{
public int RowNo { get; set; }
public string Description { get; set; }
public double?[] Prices { get; set; }
}
the view can be like this (part of view.cshtml file...) :
....
#model PriceSheetEditGridViewModel
...
columns.Bound(o => o.Description ).Width(150);
int i = 0;
foreach (var col in Model.Columns)
{
columns
.Bound(model => model.Prices).EditorTemplateName("PriceSheetCellPrice").EditorViewData(new { ColumnId = i })
.ClientTemplate("<span><#=Prices ? jsHelper.addCommas(Prices[" + i.ToString() + "]):null#></span>")
.Title(col.Title).Width(80);
i++;
}
....
and the PriceSheetCellPrice.cshtml editor template file (in shared\editortemplates folder) :
#model decimal?
#(Html.Telerik().NumericTextBox()
.Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)+"["+ViewBag.ColumnId+"]")
.InputHtmlAttributes(new { style = "width:100%" })
})
.EmptyMessage("")
.DecimalDigits(0)
.DecimalSeparator(",")
.MinValue(0)
.Value((double?) Model)
)

Use knockout.js for 4 cascading dropdowns based on a hierarchy of objects

I am trying to get four cascading dropdowns using knockout.js:
Search Criteria
Sub Criteria
Value
State
I was able to get the first cascade going (but not the others due to databinding issues) by using code from the following link:
http://blogs.msdn.com/b/thebeebs/archive/2011/12/01/price-calculator.aspx
The data for these dropdowns is being returned to my razor viewpage as an IEnumrable of SearchCriterion from an MVC view using ViewBag.CriteriaData variable. The code for my classes is as follows:
public class SearchCriterion
{
public string Text { get; set; }
public string Value { get; set; }
public List<SubCriterion> SubCriteria { get; set; }
}
public class SubCriterion
{
public string SearchCriterionValue { get; set; }
public string Text { get; set; }
public string Value { get; set; }
public List<ColumnValue> ColumnValues { get; set; }
}
public class ColumnValue
{
public string SearchCriterionValue { get; set; }
public string SubCriterionValue { get; set; }
public string Text { get; set; }
public string Value { get; set; }
public IEnumerable<StateValue> StateValues { get; set; }
}
public class StateValue
{
public string SearchCriterionValue { get; set; }
public string SubCriterionValue { get; set; }
public string ColumnValue { get; set; }
public IEnumerable<int> InputStateIds { get; set; }
public IEnumerable<int> OutputStateIds { get; set; }
public int SelectedInputStateId { get; set; }
public int SelectedOutputStateId { get; set; }
public string Text { get; set; }
public string Value { get; set; }
}
The issues I am facing are in the following portions of the .cshtml code:
What do I specify in this template for the other two dropdowns. e.g. the third dropdown needs to be bound to ColumnValue.Value (ColumnValue is part of SubCriterion)
<script id='criteriaRowTemplate' type='text/html'>
<tr>
<td><select data-bind='options: criteriaData, optionsText: "Text", optionsCaption: "Search Criterion", value: SearchCriterion' /></td>
<td><select data-bind='visible: SearchCriterion, options: SearchCriterion() ? SearchCriterion().SubCriteria : null, optionsText: "Text", optionsCaption: "Sub Criterion", value: SubCriterion' /></td>
<td><select data-bind='visible: SubCriterion, options: SubCriterion() ? SubCriterion().ColumnValues : null, optionsText: "Text", optionsCaption: "Column Value", value: ColumnValue'/></td>
<td><select data-bind='visible: ColumnValue, options: ColumnValue() ? ColumnValue().StateValues : null, optionsText: "Text", optionsCaption: "State", value: StateValue'/></td>
<td><button data-bind='click: function() { viewModel.removeLine($data) }'>Remove</button></td>
</tr>
</script>
Is this correct?
var CriteriaLine = function() {
this.SearchCriterion = ko.observable();
this.SubCriterion = ko.observable();
this.ColumnValue = ko.observable();
this.StateValue = ko.observable();
// Whenever the Search Criteria changes, reset the Sub Criteria selection
this.SearchCriterion.subscribe(function() { this.SubCriterion(undefined); }.bind(this));
this.SubCriterion.subscribe(function() { this.ColumnValue(undefined); }.bind(this));
this.ColumnValue.subscribe(function() { this.StateValue(undefined); }.bind(this));
};
How do I map the complete C# object with the Javascript object? It works if we just have the first two dropdowns:
// Create a Javascript object object with the same property names as the C# object
var dataToSearch = $.map(this.lines(), function (line) { return line.StateValue() ? line.StateValue() : undefined; });
var SearchObject = new function () {
this.StateValues = dataToSearch;
};
// Convert the object to JSON
var searchCriteria = JSON.stringify(SearchObject);
Does anything need to change here for the binding?
// Apply the data from the server to the variable
var criteriaData = #Html.Raw(#Json.Encode(ViewBag.CriteriaData));
var viewModel = new Criteria();
ko.applyBindings(viewModel, document.getElementById("criteriaDiv"));
EDIT:
I am now able to populate the cascading dropdowns (updated code above). Now I have 4 columns, each column having one of the dropdowns. I also have 1...n number of rows being added dynamically by using Knockoutjs. So, the user can now select values from these dropdowns and add more rows of dropdowns if he wants. The only thing remaining is to return the values that the user selects for the dropdowns to the controller(point 3 above). I am not sure how I can do that. Any help would be appreciated.
EDIT 2:
Added working code for Item # 3 and modified the ColumnValue and StateValue classes.
I'm not sure I fully understand your question, but I'm going to take a whack at it anyway :). I think you're looking for a way to "validate" if it is in fact time to allow the next drop down to be active?
If so, you could approach it from a standpoint of Computed Observables. Basically, you would bind each of your dropdowns to a computed value which is derived from the previous dependencies.
Let me write fiddle and I'll show you :)
OK, give this a shot...sorry for the delay...http://jsfiddle.net/farina/ZNBcM/3/
I update the answer, Hope, it will help new Comers.
Methods for Binding Hierarchical Dropdowns using Knockout JS in MVC
Here you can find the good example .

Render Partial View from within a System.Web.Helpers.WebGrid

I am trying to render a Partial from within a System.Web.Helpers.WebGrid
my model class looks like this:
class GameInfo
{
public List<AppUser> Team1 { get; set; }
public List<AppUser> Team2 { get; set; }
// and more properties
}
class AppUser
{
public string PictureUrl { get; set; }
public string ProfileUrl { get; set; }
public long GamesWon { get; set; }
public long GamesLost { get; set; }
public int Points { get; set; }
// and more properties
}
I want my GridView to show a list of GameInfo's in my grid view.
What is turning out be to be tougher than expected is rendering the Teams (List).
To stay DRY I created a partial view to render a Team (_Team.cstml).
This is my razor code:
#if (Model != null)
{
var webgrid = new WebGrid(source: Model.Games,
rowsPerPage: 10);
<div id="grid">
#webgrid.GetHtml(
columns: webgrid.Columns(
webgrid.Column(header: "Score", format: #<text>#item.Score1/#item.Score1</text>),
webgrid.Column(header: "Team 1", format: (item) =>
{
return "hello sb"; // this line works!
//return Html.Partial("_Team", item.Team1); // this gives an error
})
)
)
</div>
}
Any idea how I can get this to work?
Thank you!
In case someone else runs into this, I managed to solve it this morning.
This works:
webgrid.Column(header: "Team 1", format: (item) =>
{
List<Cuarenta.Web.Models.AppUser> team = ((Cards.Cloud.WebRole.Admin.GameInfo)item.Value).Team1;
return Html.Partial("_Team", team);
})

Resources