Kendo Treeview Binding parent and children - asp.net-mvc

I'm trying to follow this example here
http://docs.telerik.com/kendo-ui/getting-started/using-kendo-with/aspnet-mvc/helpers/treeview/ajax-binding
However, whenever I try to modify their code, I get an error saying
Error 2 'Kendo.Mvc.UI.Fluent.ReadOnlyDataSourceBuilder' does not contain a definition for 'Model' and no extension method 'Model' accepting a first argument of type 'Kendo.Mvc.UI.Fluent.ReadOnlyDataSourceBuilder' could be found (are you missing a using directive or an assembly reference?) c:\Users\Michael\Google Drive\Work\Companies\Clickable Community\dhvs\Clickable Community\Development\Portal\ClickableCommunity.Web\Views\Shared_Layout.cshtml 34 ClickableCommunity.Web
Here is my code
#(Html.Kendo().TreeView()
.Name("treeview")
// The property that specifies the text of the node
.DataTextField("Name")
.DataSource(dataSource => dataSource
.Model(model => model
// The property that uniquely identieis a node.
// The value of this property is the argument of the action method
.Id("Id")
// the boolean property that tells whether a node has children
.HasChildren("HasChildren")
)
.Read(read => read
// The action method which will return JSON
.Action("ReadCats", "Home")
)
)
)
and what I'm doing in my controller
public JsonResult ReadCats()
{
var categories = _entityLogic.GetActiveCategories();
var jsonResult = categories.Select(cat => new
{
Id = cat.Id,
Name = cat.Name,
HasChildren = categories.Where(c => c.ParentCategory == cat.Id).Any(),
ParentId = cat.ParentCategory
}).ToList();
return Json(jsonResult, JsonRequestBehavior.AllowGet);
}
Basically, I have a table that stores and ID, name, and parentcategory (the id of the parent category) and I'm trying to bind a treeview to all my parent child nodes. Thanks in advance.
Edit
So I still cannot get this. I keep getting the same error. I can't put #model namespace because it gives me an error saying it is a namespace but used like a type. Here is my entire code. Thanks,
#model ClickableCommunity.Web.Models.Public.HomeModel
#using ClickableCommunity.Core.Models.Data
#using Kendo.Mvc.UI
#{
ViewBag.Title = "Home Page";
}
<h2>#ViewBag.Message</h2>
#(Html.Kendo().TreeView()
.Name("treeview")
// The property that specifies the text of the node
.DataTextField("Name")
.DataSource(dataSource => dataSource
.Model(model => model
// The property that uniquely identieis a node.
// The value of this property is the argument of the action method
.Id("Id")
// the boolean property that tells whether a node has children
.HasChildren("HasChildren")
)
.Read(read => read
// The action method which will return JSON
.Action("ReadCats", "Home")
)
)
)
<ul>
#foreach (var item in Model.CategoryEntities)
{
<li>
#item.Name
</li>
}
</ul>
And here is my controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using ClickableCommunity.Core.Contracts.Logging;
using ClickableCommunity.Core.Contracts.Logic;
using ClickableCommunity.Web.Models.Public;
namespace ClickableCommunity.Web.Controllers
{
public class HomeController : BaseController
{
private readonly IEntityLogic _entityLogic;
private readonly IGeogrpaphyLogic _geoLogic;
private readonly IUserLogic _userLogic;
public HomeController(ISystemLogger logger, IEntityLogic entityLogic, IUserLogic userLogic, IGeogrpaphyLogic geoLogic) : base(logger)
{
_entityLogic = entityLogic;
_userLogic = userLogic;
_geoLogic = geoLogic;
}
public ActionResult Index()
{
var catEnts = new List<HomeModel.CategoryEntitiesList>();
var model = new HomeModel
{
AvailableCategories = _entityLogic.GetActiveCategories()
, Entities = _entityLogic.GetActiveEntities()
, States = _geoLogic.GetAllStates()
};
var tempCe = new HomeModel.CategoryEntitiesList();
foreach (var i in model.AvailableCategories.Where(c => c.ParentCategory == null))
{
tempCe = new HomeModel.CategoryEntitiesList();
tempCe.Name = i.Name;
tempCe.ParentCategory = i.ParentCategory;
tempCe.Id = i.Id;
tempCe.HasChildren = model.AvailableCategories.Where(a => a.ParentCategory == i.Id).Any();
catEnts.Add(tempCe);
}
model.CategoryEntities = catEnts;
return View(model);
//return View();
}
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
public JsonResult GetChildTreeViewData(int? id)
{
var categories = _entityLogic.GetActiveCategories();
if (id != null)
{
categories = categories.Where(c => c.ParentCategory == id);
}
var jsonResult = categories.Select(cat => new
{
Id = cat.Id,
Name = cat.Name,
HasChildren = categories.Where(c => c.ParentCategory == cat.Id).Any(),
ParentCategory = cat.ParentCategory
}).ToList();
return Json(jsonResult, JsonRequestBehavior.AllowGet);
}
}
}

Your View should define a Model in order for this to work
Add this line to the top of your View:
#model categories //or whatever namespace your Entity categoies are in
this should work fine!!

Related

Multiple Checkbox with Model returns null

after I read data from my database, I try to show those datas in Html.Helper checkbox and I do that. But later when I try to get checked values back to the controller, model always returns null. Here's my controller part:
[HttpGet]
public ActionResult NewClient()
{
HizmetModel hizmetModel = new HizmetModel();
hizmetModel.hizmet = db.Hizmet.ToList<Hizmet>();
return View(hizmetModel);
}
[HttpPost]
public ActionResult NewClientPost(string name, string lastname, string telephone, string plate, HizmetModel hizmet)
{
Musteri musteri = new Musteri();
if (!db.Musteri.Where(x => x.plaka == plate).Any())
{
musteri.isim = name;
musteri.soyisim = lastname;
musteri.telefon = telephone;
musteri.plaka = plate;
db.Musteri.Add(musteri);
db.SaveChanges();
}
Islem islem = new Islem();
IslemHizmet islemhizmet = new IslemHizmet();
islem.giristarihi = DateTime.Now;
islem.plaka = plate;
var selectedHizmet = hizmet.hizmet.Where(x => x.isChecked == true).ToList<Hizmet>();
db.Islem.Add(islem);
db.SaveChanges();
var onprocessplate = db.Islem.Where(x => x.plaka == plate).FirstOrDefault();
foreach (var item in selectedHizmet)
{
islemhizmet.islem_id = onprocessplate.islem_id;
islemhizmet.hizmet_id = item.hizmet_id;
db.IslemHizmet.Add(islemhizmet);
db.SaveChanges();
islemhizmet = new IslemHizmet();
}
TempData["Success"] = "Müşteri başarıyla eklendi...";
return RedirectToAction("CurrentClients", "Admin");
}
This is my model for the list:
public class HizmetModel
{
public List<Hizmet> hizmet { get; set; }
}
I use this model in the cshtml file:
#model otoyikama.Models.Model.HizmetModel
And this is the loop for displaying checkboxes
#for (int i = 0; i < Model.hizmet.Count; i++)
{
<li>
<label>#Model.hizmet[i].hizmetisim</label>
#Html.CheckBoxFor(m => m.hizmet[i].isChecked)
#Html.HiddenFor(m => m.hizmet[i].hizmet_id)
#Html.HiddenFor(m => m.hizmet[i].hizmetisim)
</li>
}
I couldn't figure what's the problem here, my get action works fine, I can see all the data from database but I can't pass them back to controller.
As a first think , u need to create a object in your controller parameters such as like List<int> serviceIDs or List<Service> services so you can keep more data than one.
The html part:
#foreach(item in Model.Service)
{
<label>#item.ServiceName</label><br>
<input type="checkbox" name="services" value="#item.ServiceID">
<input type="hidden" name="services" value="#item.ServiceName">
}
The backend part:
[HttpPost]
public ActionResult NewClientPost(string name, string lastname, string telephone, string plate, List<Service> services)
{
}
when u do in that way, u will able to hold more services than to one and i think u can pass them the controller more easly.
when i face with that stuation, im taking those services ID's and calling them on the controller side like bellow;
The html part:
#foreach(item in Model.Service)
{
<label>#item.ServiceName</label><br>
<input type="checkbox" name="serviceIDs" value="#item.ServiceID">
}
The backend part:
[HttpPost]
public ActionResult NewClientPost(string name, string lastname, string telephone, string plate, List<int> serviceIDs)
{
List<Service> services= new List<Service>();
foreach(var item in serviceIDs)
{
var service=db.Service.Where(x => x.ServiceID == item).Any()
if(service.Count!=0)
{
services.Add(service);
}
}
}

Access data from Viewbag Dropdown

I am getting the value from dropdown to controller but when it goes back to View it returns Null
SCREENSHOT OF VIEW:-
SCREENSHOT OF CONTROLLER:-
public ActionResult Index(int departmentID)
{
ViewBag.dropdowndetail = null;
var strDDLValue = departmentID;
if (strDDLValue == null)
{
return HttpNotFound();
}
else
{
var emp = db.employees.ToList().FirstOrDefault(x=>x.depId==departmentID);
return View(emp);
}
}
ERROR:
I get it right
My viewbag was not getting any value in Post method so that why in View it was getting null Exception
I call my viewbag in Post method and give it the value.
change the following code with this.
public ActionResult Index(int departmentID)
{
var strDDLValue = departmentID;
if (strDDLValue == null)
{
return HttpNotFound();
}
else
{
var emp = db.employees.Where(x=>x.depId==departmentID).ToList();
ViewBag.dropdowndetail = db.departments.Distinct().ToList();
return View(emp);
}
}
You can use keyvalue approach in controller
ViewBag.dropdowndetail = db.departments.Distinct().Select(x => new KeyValuePair<int, string>(x.depid, x.DepartmentName));
and in View use ViewBag like this
#Html.DropDownListFor(model => model.depid, new SelectList((IEnumerable<KeyValuePair<int, string>>)ViewBag.dropdowndetail , "key", "value"), "--Select Departments--")

Sequence contains no elements errror - MVC (Models and Data Access)

I'm trying to follow the MVC Music Store tutorial , but I got an error which I can't handle. I've created the action:
public ActionResult Browse(string category)
{
using (OnlineStoreDbContext db = new OnlineStoreDbContext())
{
// Get category and its associated products
var categoryModel = db.Categories.Include("Products")
.Single(c => c.Title == category);
return View(categoryModel);
}
}
Than I created and the respective View:
#model OnlineStoreMVC.Core.Models.Category
#{
ViewBag.Title = "Browse";
}
<h2>Browse Category: #Model.Title</h2>
<ul>
#foreach (var product in Model.Products)
{
<li>
#product.Title
</li>
}
</ul>
But when I try to open: http://localhost:51642/Store/Browse?cat=Action, I get error:
"Sequence contains no elements" regarding this line:
var categoryModel = db.Categories.Include("Products")
.Single(c => c.Title == category);
I've alredy tried to replace Single with SingleOrDefault, but then the error was
"Object reference not set to an instance of an object." regarding that line in the View: "<h2>Browse Category: #Model.Title</h2>"
The problem is that you're passing cat as key in you're url and it should be category. So you should call http://localhost:51642/Store/Browse?category=Action
About the the error "Object reference not set to an instance of the object" you have to change you Action method to:
public ActionResult Browse(string category)
{
using (OnlineStoreDbContext db = new OnlineStoreDbContext())
{
// Get category and its associated products
var categoryModel = db.Categories.Include("Products")
.SingleOrDefault(c => c.Title == category);
if (categoryModel == default(Category))
{
categoryModel = new Category();
categoryModel.Products = new List<Product>();
}
return View(categoryModel);
}
}

MVC dropdownlist : Setting the value and text based upon table in database

I have a table in database
I've been able to show the list of TypeName in my dropdownlist in my View
Currently i'm doing this is my controller
[HttpGet]
public ActionResult CreateModule()
{
var moduleTypes = _db.ModuleTypes.Select(moduleType => moduleType.TypeName).ToList();
var model = new CreateModule
{
TypeNames = moduleTypes.Select(m => new SelectListItem
{
Value = m,
Text = m,
})
};
return View(model);
}
and in view
<div class ="input-block-level">#Html.DropDownListFor(model => model.SelectedModuleTypeName, Model.TypeNames)</div>
That results to something like this
based upon my code, I'll get the TypeName from the view in my controller's post method.
How I can I change my code in order to access Id of the TypeName in controller?
Modify your Action:
public ActionResult CreateModule()
{
var moduleTypes = _db.ModuleTypes.Select(moduleType => new { TypeName = moduleType.TypeName, Id = moduleType.Id }).ToList();
var model = new CreateModule
{
TypeNames = moduleTypes.Select(m => new SelectListItem
{
Value = m.Id.ToString(),
Text = m.TypeName,
})
};
return View(model);
}
Select multiple items instead of single
var moduleTypes = _db.ModuleTypes
.Select(
moduleType => new {
Id = moduleType.Id
TypeName = moduleType.TypeName}
).ToList();
var model = new CreateModule
{
TypeNames = moduleTypes.Select(m => new SelectListItem
{
Value = m.Id.ToString(),
Text = m.TypeName,
})
};
The first statement is creating anonymous object using linq, and second statement is using it to create CreateModule

MVC with Kendo treeview - remote data JSON or XML

I'm trying to create a Kendo treeview that gets populated from my controller (PropertyController).
The part I'm stuck at is how to format my data in the controller. How could I create a treeview three items deep and pass that to my view to be displayed in the treeview?
#(Html.Kendo().TreeView()
.Name("treeview")
.Events(events => events
.DragStart("PartnershipPage.OnDragStart")
.Drop("PartnershipPage.OnDrop")
.DragEnd("PartnershipPage.OnDragEnd")
)
.HighlightPath(true)
.DragAndDrop(true)
.DataSource(dataSource => dataSource
.Read(read => read
.Action("Index","Tree")
)
)
)
I've included the controller to see if I'm doing it correctly. All that is happening so far is the JSON is being displayed on the screen as text.
Controller:
public ActionResult Index()
{
var org = new Entities();
var eList = new List<Entity>();
var entity1 = new Entity
{
Id = 1,
Name = "LLC-A",
parentId = 0
};
eList.Add(entity1);
var entity2 = new Entity
{
Id = 2,
Name = "LLC-B",
parentId = 0
};
eList.Add(entity2);
var entity3 = new Entity
{
Id = 1,
Name = "LLC-C",
parentId = 2
};
eList.Add(entity3);
var entity4 = new Entity
{
Id = 1,
Name = "LLC-D",
parentId = 2
};
eList.Add(entity4);
org.Entity = eList;
var test = from x in org.Entity
where (x.Name != null)
select new
{
Id = x.Id,
Name = x.Name,
parentId = x.parentId
};
;
return Json(test, JsonRequestBehavior.AllowGet);
}
From: Kendo Site
<%= Html.Kendo().TreeView()
.Name("TreeView")
.BindTo(Model, mapping => mapping
.For<Customer>(binding => binding
.Children(c => c.Orders) // The "child" items will be bound to the the "Orders" property
.ItemDataBound((item, c) => item.Text = c.ContactName) // Map "Customer" properties to TreeViewItem properties
)
.For<Order<(binding => binding
.Children(o => null) // "Orders" do not have child objects so return "null"
.ItemDataBound((item, o) => item.Text = o.OrderID.ToString()) // Map "Order" properties to TreeViewItem properties
)
)
%>
You could put your entities into a list called for example, "myEntities" and return that from the controller to the view:
public ActionResult Index()
{
var ents = getMyEntities(); // some method you have to return the list of your entities
return ents;
}
Then in your view, you can loop through all the Entities in your Model:
#(Html.Kendo().TreeView()
.Name("TreeView")
.Items(treeview =>
{
foreach (var entity in Model)
{
var entityName = entity.Name;
var children = entity.Children;
treeview.Add().Text(entityName ).Expanded(false).Items(branch =>
{
if (children != null)
{
foreach (var child in children)
{
branch.Add().Text(child);
}
}
});
}
}
)
)
I used children because I found it easier to use than parent and so I would change my Entities to something like this:
var entity4 = new Entity
{
Id = 1,
Name = "LLC-D",
Children = <list of children names ... >
};
You can see how I did mine here: Populate KendoUI Treeview with RavenDB Documents
Hope this helps.
Edit in response to: How can I display children of children?
I ran into the same problem as you describe (displaying children of children). Here is how I did it after I had the problem of displaying children of children:
I used EntityFramework:
The DB context class:
public class EntityDBContext : DbContext
{
public DbSet<MyEntity> Entities { get; set; }
}
Controller:
public JsonResult EntitiesForTreeView(int? id)
{
// Here I am using EntityFramework
var entitiesContext = new EntityDBContext();
var myEntity= from e in entitiesContext.Entities
where (id.HasValue ? e.Parent == id : e.Parent == null)
select new
{
id = e.Id,
Name = e.Name,
hasChildren = e.Id
};
return Json(myEntity, JsonRequestBehavior.AllowGet);
}
And the View:
#(Html.Kendo().TreeView()
.Name("treeview")
.DataTextField("Name")
.LoadOnDemand(true)
.HighlightPath(true)
.DataSource(dataSource => dataSource
.Read(read => read
.Action("EntitiesForTreeView", "SiteMap")
)
)
.Checkboxes(true)
)
Hope this helps. Sorry if there is something stupid - I've only been doing web development for 3 months so unmark as answer if needed. Let me know if I can help further. PS: I should mention that after implementing the solution I have shown above, I noticed that the nodes on my tree all have the "+" sign... regardless of whether or not they have any children. If you know how to fix this, please let me know :)

Resources