I'm trying to include a Kendo UI ASP.NET MVC Grid on the Edit page of my MVC application and I would like to restrict that grid to only return values from the current route id. I've been researching ways to do this, but can't find anything that's exactly what I need, or I'm just too new at this to connect the dots.
My ideas so far are to either apply a filter to the DataSource or send a parameter to the controller and have it restrict the DataSourceResult.
For the DataSource filter in the view, I can do this:
.Filter(filters => { filters.Add(d => d.CompanyId).IsEqualTo(2); })
But I can't figure out how to replace the hardcoded 2 with the value from, say, #ViewContext.RouteData.Values["id"], or something.
Passing a parameter to the controller, I can get the following:
public ActionResult Divisions_Read([DataSourceRequest]DataSourceRequest request, int id)
{
using (var db = new AppContext())
{
IQueryable<Division> divisions = db.Divisions;
DataSourceResult result = divisions.ToDataSourceResult(request, division => new DivisionViewModel
{
DivisionId = division.DivisionId,
CompanyId = division.CompanyId,
CountryId = division.CountryId,
DivisionName = division.DivisionName
});
return Json(result);
}
}
But I have no idea how to use that id to basically add a "where CompanyId = Id" statement to the result.
Any ideas on what the best way to do this would be? Am I missing something really obvious?
Thanks!
ETA: Passing the parameter to the Controller through the Read action, as suggested by mmillican and other places in my research, and changing
DataSourceResult result = divisions.ToDataSourceResult(request, division => new DivisionViewModel
to
DataSourceResult result = divisions.Where(c => c.CompanyId == companyId).ToDataSourceResult(request, division => new DivisionViewModel
did the trick. That extra bit in the controller was what I was looking for, but couldn't seem to find anywhere.
Assuming you have a model for your page that looks like this:
public class MyViewModel
{
public int Id { get; set; } // assuming Id is what you want to filter by
// .. other VM properties
}
you can do something like this in your grid data binding
.DataSource(ds => ds
.Ajax()
.Model(mdl => mdl.Id(x => x.Id))
.Read("Divisions_Read", "Divisions", new { id = Model.Id })
)
in your controller, you would set the model's Id property to whatever ID that is in the route.
Related
I'm trying to add dropdownlist in client template, but somehow not able, could someone please help me on this?
columns.Bound(o => o.ImportFunctionText).ClientTemplate("# if (ImportFunction == 0) { # Account # } else if (ImportFunction == 1) { # Row # } #")
.EditorTemplateName("DropDownList")
.EditorViewData(new
{
Id = "ImportFunction",
Data = ViewBag.dropDownList,
FieldName = "value:ImportFunction"
})
.Width(210)
.Title("Function");
Thanks.
in order to make use of editor templates you have to store your editor template within the folder ~/Views/Shared/EditorTemplates/tmp_dropdown_attribute.cshtml as a partial view.
according to the telerik asp net mvc docs your should the template look like the following:
#(Html.Kendo().DropDownList()
.Name("Employee") // Name of the widget should be the same as the name of the property
.DataValueField("EmployeeID") // The value of the dropdown is taken from the EmployeeID property
.DataTextField("EmployeeName") // The text of the items is taken from the EmployeeName property
.BindTo((System.Collections.IEnumerable)ViewData["employees"]) // A list of all employees which is populated in the controller
)
and your controller should bind the viewdata container within the controller method which generates the view like that:
public ActionResult Index()
{
ViewData["employees"] = new NorthwindDataContext()
.Employees
.Select(e => new Employee
{
EmployeeID = e.EmployeeID,
EmployeeName = e.FirstName + " " + e.LastName
})
.OrderBy(e => e.EmployeeName);
return View();
}
for further reading please refer to the docs which can be found here:
http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/templating/editor-templates
Currently using the Kendo UI AutoCompleteFor() and ComboBoxFor() helper.
Noticing that they generate/render a bunch of <li>s.
How does one add additional custom data-* attributes to those <li>s?
Here's the current scenario:
The user starts typing stuff in the AutoCompleteFor
An ajax call is triggered to fetch some data related to what the
user has typed.
The obtained results are transformed into an
IEnumerable<SelectListItem>.
The result is then sent to Json. Json(result, JsonRequestBehavior.AllowGet)
My goal is to add one or more additional data-* attribute to each of these <li> generate lines so that I can fetch these data-* in the onChange() event.
How does one achieve this?
In addition, I'm aware that I could create my own .Template() and possibly achieve my task but I was curious if anyone knows of a different way to do this then having to create my own template.
Sincerely
Ok I've found a solution; I'll share it here in case anyone is interested.
Instead of transforming my obtained results into an IEnumerable<SelectListItem>, I simply transform this into an IEnumerable<CustomDTO>.
The CustomDTO class looks like this:
public class CustomDTO
{
public int Value { get; set; }
public string Text { get; set; }
public int Age { get; set; }
//Add whatever more properties you think you’ll need.
}
In my controller, I then do the following:
var result = _myService.GetData().ToList();
return Json(result, JsonRequestBehavior.AllowGet);
Where GetData() returns an IEnumerable<CustomDTO>.
Inside my View, I have an AutoCompleteFor() control to which I bind a client side
.Events(x => x.Select("onSelect") event handler.
The handler is defined like so:
function onSelect(e)
{
if (e.item == null) return;
var dataItem = this.dataItem(e.item.index());
var valueAttribute = dataItem.Value;
var textAttribute = dataItem.Text;
var ageAttribute = dataItem.Age; //This is how I get my additional value
//...code...
}
So that's it.
I am using a ViewModel Class to bind to a KendoUI grid and it call works well until I try to sort (or filter). It all works ok until I try sort on UserName. I am sure it is because UserName is not a property of my entity model (ErrorLog)
public ActionResult ListErrors([DataSourceRequest]DataSourceRequest request)
{
IQueryable<ErrorLog> errorLogs = (IQueryable<ErrorLog>)db.ErrorLogs.Include(e => e.User).OrderByDescending(e => e.ErrorLogId);
DataSourceResult result = errorLogs.ToDataSourceResult(request, errorLog => new ErrorLogViewModel
{
ErrorLogId = errorLog.ErrorLogId,
Message = errorLog.AdditionalMessage,
UserName = errorLog.User.UserName
});
return Json(result);
}
This scenario doesn't seem to covered in the Kendo MVC documentation.
Solved by invoking ToDataSourceResult after my db query had run:
public ActionResult ListErrors([DataSourceRequest]DataSourceRequest request)
{
IQueryable<ErrorLog> errorLogs = (IQueryable<ErrorLog>)db.ErrorLogs.Include(e => e.User).OrderByDescending(e => e.ErrorLogId);
DataSourceResult result = errorLogs.Select(errorLog => new ErrorLogViewModel
{
ErrorLogId = errorLog.ErrorLogId,
Message = errorLog.AdditionalMessage,
Timestamp = errorLog.Timestamp,
UserName = errorLog.User.UserName
}).ToDataSourceResult(request);
return Json(result);
}
Please try the KendoGridBinderEx project instead of [DataSourceRequest], together with AutoMapper this scenario should be work fine.
For a demo see here.
I have a model containing a couple of lists:
[Display(Name = "Facilities")]
public List<facility> Facilities { get; set; }
[Display(Name = "Accreditations")]
public List<accreditation> Accreditations { get; set; }
I populate these lists initially from my controller:
public ActionResult Register()
{
var viewModel = new RegisterModel();
viewModel.Facilities = m_DBModel.facilities.ToList();
viewModel.Accreditations = m_DBModel.accreditations.ToList();
return View(viewModel);
}
When they get to my view they are populated with the DB records (great). I then pass the model to the partial view which displays these lists as checkboxes, ready for user manipulation (I have tried based on another suggestion using for loop instead of foreach loop, made no difference):
#model LanguageSchoolsUK.Models.RegisterModel
#foreach (var item in Model.Facilities)
{
#Html.Label(item.name);
#Html.CheckBox(item.name, false, new { id = item.facility_id, #class = "RightSpacing", #description = item.description })
}
When I submit the form and it ends up back at my controller this time calling the overloaded register function on the controller:
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Do stuff
}
return View(model);
}
The problem is that the model parameter containing the lists (Facilities and Accreditations) is telling me that the lists are null.
Please can somebody tell me what I am doing wrong, why aren't they populated with the collections that I originally passed through and hopefully a way of asking whick ones have been checked?
Thanks.
I have tried based on another suggestion using for loop instead of
foreach loop, made no difference
Try again, I am sure you will have more luck this time. Oh and use strongly typed helpers:
#model LanguageSchoolsUK.Models.RegisterModel
#for (var i = 0; i < Model.Facilities.Count; i++)
{
#Html.HiddenFor(x => x.Facilities[i].name)
#Html.LabelFor(x => x.Facilities[i].IsChecked, Model.Facilities[i].name);
#Html.CheckBoxFor(
x => x.Facilities[i].IsChecked,
new {
id = item.facility_id,
#class = "RightSpacing",
description = item.description // <!-- HUH, description attribute????
}
)
}
Also you will undoubtedly notice from my answer that checkboxes work with boolean fields on your model, not integers, not decimals, not strings => BOOLEANS.
So make sure that you have a boolean field on your model which will hold the state of the checkbox. In my example this field is called IsChecked but obviously you could feel absolutely free to find it a better name.
I've been new to ASP.NET MVC. This is what I'm doing. I've 2 Controllers:Home and Customerservice.
Now I have a Customer list where when I click details gets redirected to the products he acquired.
So, I need to pass in the id so that the products of that customer can be displayed. So, my home consists of customer details. Now i need to pass that id to CustomerService controller ,Index action. This is what I've done in Home:
public ActionResult Customers()
{
var dc = new ServicesDataContext();
var query = (from m in dc.Customers
select m);
return View(query);
}
public ActionResult Details(int id)
{
var datacontext = new ServicesDataContext();
var serviceToUpdate = datacontext.Customers.First(m => m.CustomerId == id);
ViewData.Model = serviceToUpdate;
// return View();
return Redirect("/CustomerService");
}
[HttpPost]
public ActionResult Details(FormCollection form)
{
var id = Int32.Parse(form["CustomerID"]);
var datacontext = new ServicesDataContext();
var service = datacontext.Customers.First(m => m.CustomerId == id);
return Redirect("Customers");
}
}
Now I'm not sure whether I need to pass an id as parameter for index in CustomerService. SO can you please guide me in finishing this?
If you are using any Redirect (such as RedirectToAction) you can use TempData to store any parameters. The semantics have slightly changed in MVC 3 but TempData is designed to pass data between actions in a POST-Redirect-GET scenario.
Passing it as a parameter is probably your best option. Try using something like return RedirectToAction(ActionName, ControllerName, RouteValues);.