Set Kendo grid height to match its container - asp.net-mvc

I've got a Kendo grid:
<section class="main-window">
#model IEnumerable<SustIMS.Models.ModelTest>
<div class="clear-both">
<div class="field-value" style="height: 30px; border-bottom: 1px solid black">
</div>
<div id="datagrid">
#(Html.Kendo().Grid(Model)
.Name("datagrid_Concessoes")
.Columns(columns =>
{
columns.Bound(c => c.Id).Width(70);
columns.Bound(c => c.Code);
columns.Bound(c => c.Description);
columns.Bound(c => c.CreationDate);
columns.Bound(c => c.CreationUser);
})
.Scrollable()
.Sortable()
.Selectable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetAutoEstradas", "MasterData"))
)
)
</div>
</div>
</section>
Here's the section CSS:
.main-window
{
border: 2px solid gray;
border-radius: 2px;
width: 95%; height: 70%;
background-color: White;
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
box-sizing: border-box;
}
I want the Kendo grid to have the height of its container. I've tried the
.Scrollable(s => s.Height(200))
but it only accepts values in pixels, not in percentage.
How can I set the Kendo grid to fit its container div/section?
PS: I've checked this question but didn't find a solution for me

I was able to get it work by setting height in the onDataBound event handler, like so:
<div id="datagrid">
#(Html.Kendo().Grid<Model>()
.Name("datagrid_Concessoes")
.Columns(columns =>
{
columns.Bound(c => c.Id).Width(70);
columns.Bound(c => c.Code);
columns.Bound(c => c.Description);
columns.Bound(c => c.CreationDate);
columns.Bound(c => c.CreationUser);
})
.Scrollable()
.Sortable()
.Selectable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetAutoEstradas", "MasterData"))
)
.Events(events => events.DataBound("grid1_onDataBound"))
)
function grid1_onDataBound(e) {
$("#datagrid .k-grid-content").attr("style", "height: auto");
}

Remove the .Scrollable() method. Scrollable() forces a fixed height on the grid.

Remove height propery from grid. Sample GridID = #grid
Add DataBound Event to grid;
Events(j=>j.DataBound("DataBound"))
Add Css;
html, body { margin:0; padding:0; height:100%; }
#grid { height: 100%; }
#outerWrapper{ background-color: red; overflow: hidden; }
.k-grid td { white-space: nowrap; overflow: hidden; }
Add Javascript;
function resizeGrid() {
$(".k-grid-content").css({ height: $(".k-grid-content")[0].scrollHeight });
}
setTimeout(function () {
resizeGrid();
}, 150);
i have 10 row grid and content within the grid has a calculated height.

In the grid you can set the height via the htmlattributes section something like this:
.HtmlAttributes(new { style = "height:600px;" })
or
.HtmlAttributes(new { class= "main-window" })
Having tested this on my grid this should work for you:
$(document).ready(function () {
//Get the current window height
var windowHeight = $(window).height();
//record the value of the height to ensure it is showing correctly.
console.log("Original Height" + windowHeight);
//multiply this height by a percentage e.g. 70% of the window height
windowHeight = windowHeight * 0.7;
//record the new modified height
console.log("Modified Height" + windowHeight);
//find my grid and the grid content and set the height of it to the new percentage
$("#baseGrid .k-grid-content").height(windowHeight);
});

I derived my solution from David Shorthose's above. I also needed my grid to resize when the window resized. My page also has a header and footer section which is 225px, so I subtract that out rather than using a percentage. Here is the script I added to my page:
<script>
$(function () {
resizeGrid();
});
$(window.onresize = function () {
resizeGrid();
})
function resizeGrid() {
$("#gridname").height($(window).height() - #Settings.TopBottomMarginHeight);
}
</script>
I moved the 225px into a settings class for easy re-use, which looks like this:
namespace Website
{
public static partial class Settings
{
public static int TopBottomMarginHeight => 225;
}
}

Related

Revert draggable after a different draggable is dropped

I have a 2x2 grid of droppable areas [[A,B][C,D]] and under the grid is a 1x4 grid of draggables. I only want certain draggables next to each other. So for example, if there is a draggable in B, and I drag a different draggable into A, is there a way to make the draggable in B revert? The draggables have data-row and data-col so that I can grab the draggable in the prev/next column if I need to.
$(".draggable").draggable({
scroll: false,
snap: ".snaptarget",
snapMode: "inner",
stack: ".draggable",
revert: function (event, ui) {
var $draggable = $(this);
$draggable.data("uiDraggable").originalPosition = {
top: 0,
left: 0
};
return !event;
}
});
$(".snaptarget").droppable({
accept: ".draggable",
drop: function (event, ui) {
var $draggable = $(ui.draggable);
var $droppable = $(this);
// This droppable is taken, so don't allow other draggables
$droppable.droppable('option', 'accept', ui.draggable);
ui.draggable.position({
my: "center",
at: "center",
of: $droppable,
using: function (pos) {
$draggable.animate(pos, "fast", "linear");
}
});
// Disable prev or next droppable if the pagewidth == 1
if ($droppable.data("col") == 1) {
$droppable.next().droppable("option", "disabled", true);
var nextDrag = $(".draggable[data-row='" + $droppable.data("row") + "'][data-col='2']");
if (nextDrag.length) {
// I need to revert nextDrag if there is one.
// I've tried this but it doesn't seem to work
nextDrag.data("uiDraggable").originalPosition = {
top: 0,
left: 0
}
}
}
},
tolerance: "pointer"
});
Took a little bit of work, I am never good with offsets and positioning. Here's the key:
function returnItem(item, target) {
// Get Origin
var oPos = item.data("uiDraggable").originalPosition;
// Adjust Postion using animation
item.position({
my: "top left",
at: "top left+" + oPos.left,
of: target,
using: function(pos) {
item.animate(pos, "fast", "linear");
}
});
}
Here is a working example based on the Draggable Snap to element grid example:
https://jsfiddle.net/Twisty/a4ucb6y3/6/
HTML
<div id="target">
<div class="snaptarget ui-widget-header" data-col="1" data-row="1" style="top: 0; left: 0;">
</div>
<div class="snaptarget ui-widget-header" data-col="2" data-row="1" style="top: 0; left: 80px;">
</div>
<div class="snaptarget ui-widget-header" data-col="1" data-row="2" style="top: 80px; left: 0;">
</div>
<div class="snaptarget ui-widget-header" data-col="2" data-row="2" style="top: 80px; left: 80px;">
</div>
</div>
<br style="clear:both">
<div id="source">
<div id="drag-A" class="draggable ui-widget-content" style="left: 0;">
<p>Drag A</p>
</div>
<div id="draggable2" class="draggable ui-widget-content" style="left: 80px;">
<p>Drag B</p>
</div>
<div id="draggable3" class="draggable ui-widget-content" style="left: 160px;">
<p>Drag C</p>
</div>
<div id="draggable4" class="draggable ui-widget-content" style="left: 240px;">
<p>Drag D</p>
</div>
</div>
CSS
.draggable {
width: 80px;
height: 80px;
font-size: .9em;
position: absolute;
top: 0;
}
.draggable p {
text-align: center;
height: 1em;
margin-top: 30px;
}
#source {
width: 320px;
height: 80px;
position: relative;
}
#target {
width: 160px;
height: 160px;
position: relative
}
.snaptarget {
width: 80px;
height: 80px;
position: absolute;
}
jQuery
$(function() {
function returnItem(item, target) {
// Get Origin
var oPos = item.data("uiDraggable").originalPosition;
// Adjust Postion using animation
di.position({
my: "top left",
at: "top left+" + oPos.left,
of: target,
using: function(pos) {
item.animate(pos, "fast", "linear");
}
});
}
$(".draggable").draggable({
scroll: false,
snap: ".snaptarget",
snapMode: "inner",
stack: ".draggable",
revert: "invalid",
start: function(e, ui) {
var off = $("#source").position();
ui.helper.data("uiDraggable").originalPosition = {
top: ui.position.top,
left: ui.position.left
};
}
});
$(".snaptarget").droppable({
accept: ".draggable",
drop: function(event, ui) {
var $draggable = $(ui.draggable);
var $droppable = $(this);
// This droppable is taken, so don't allow other draggables
$droppable.droppable('option', 'accept', ui.draggable);
// Disable prev or next droppable if the pagewidth == 1
if ($droppable.data("col") == 1) {
$droppable.next().droppable("option", "disabled", true);
var nextDrag = $(".draggable[data-row='" + $droppable.data("row") + "'][data-col='2']");
if (nextDrag.length) {
// I need to revert nextDrag if there is one.
returnItem(nextDrag, $("#source"));
}
}
},
tolerance: "pointer"
});
});
In draggable, when we start to drag, we want to record the original position (in case we need to later revert). The revert option is set to invalid in case the user drags it off some other place weird.
We add the position to data of the dragged item so that it can be read later.
When that item is dropped is when the magic happens. You had done all the checking, just needed to return the item if it didn't fit. if nextDrag exists, we return it to it's source.
Going forward, you may want to consider appending, cloning, and removing the elements in the start/stop events. As it is now, we're really only adjust the positioning of the elements, not their hierarchy in the DOM. Depending on what your needs are, this may not matter.

How to display icon as a value on a Kendo Grid cell?

I have a table called Priority and it has a column called IconUrl that is used to store the path of the icons as shown below:
| ID | Priority | IconUrl
------------------------------------------------------------|
| 0 | Normal | /../../Content/icons/normal.png |
| 1 | Urgent | /../../Content/icons/urgent.png |
| 2 | Blocker | /../../Content/icons/blocker.png |
I want to display icons according to the IconUrl values for each records on the Kendo Grid. I tried some methods as shown below, but none of them was solved the problem yet. How to manage to display just icon images?
columns.Bound(c => c.Priority).ClientTemplate("<img src='" + Url.Content("~/") + "#=IconUrl#' height='62' width='62'/>");
or
columns.Bound(c => c.Priority).ClientTemplate("<img src='" + Url.Content("#=Model.IconUrl#") + "'/>'");
The problem could be caused by the '/../../' at the start of your url.
Open your browsers developer tools, look at the cell can see what url is there.
If your content folder is in your home or project directory then recreating the url with the text from Priority col might work.
columns.Bound(c => c.Priority).ClientTemplate("<img src='" + Url.Content("~/Content/icons/") + "#=Priority.toLowerCase()#.png' height='62' width='62'/>");
The Url.Content function is used to map virtual paths. For example having apps inside other apps. If there is not a tilde at the start of the string passed to the function it will just return the url string unchanged.
So in your second example calling "<img src='" +Url.Content("#=IconUrl#") + "'/>'" will produce the same result as <a src='#=IconUrl#'>
As mentioned on Grid / Basic usage on Telerik page, you can display the image as shown below:
#(Html.Kendo().Grid<Kendo.Mvc.Examples.Models.CustomerViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.PriorityDescription)
.ClientTemplate(#"<div class='grid-icon' style='background-image:
url(#:data.IconUrl#);'></div>").Width("40px");
columns.Bound(c => c.ContactTitle).Width(190);
columns.Bound(c => c.CompanyName);
columns.Bound(c => c.Country).Width(110);
})
.HtmlAttributes(new { style = "height: 380px;" })
.Scrollable()
.Groupable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("Customers_Read", "Grid"))
)
)
<style>
.customer-photo {
display: inline-block;
width: 32px;
height: 32px;
border-radius: 50%;
background-size: 32px 35px;
background-position: center center;
vertical-align: middle;
line-height: 32px;
box-shadow: inset 0 0 1px #999, inset 0 0 10px rgba(0,0,0,.2);
margin-left: 5px;
}
.customer-name {
display: inline-block;
vertical-align: middle;
line-height: 32px;
padding-left: 3px;
}
</style>

Display Custom Command Button Kendo UI Grid in MVC with Conditional Authorization Role

Kendo UI Grid in MVC with Conditional Au Custom Command Button
How Conditionally display Destroy or Custom Command button Base on Authorization
I wanna display a Custom Command in kendo MVC grid For users that have Role="Admin"
Like
#if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if (HttpContext.Current.User.IsInRole("Admin"))
{
In my Kendo Grid
#(Html.KendoGrid<Management.Models.Users.UserModel>("dgvUser", "PartialCustomUserModel", false)
.Columns(c => c.Command(cc =>
{
cc.Custom("delete").HtmlAttributes(new
{
#style = #"
color : transparent;
background-position: center center;
background-image: url('../Content/themes/base/images/blue/imgEditUser.png');
background-size: contain;
background-repeat: no-repeat;
height: 28px;
cursor: pointer;"
}).Click("deleteUser");
What can I do?
You can use the following
#(Html.Kendo()
.Grid<YourModel>()
.Name("Grid")
.Columns(columns =>
{
columns.Command(command =>
{
if (User.IsInRole("Admin"))
{
command.Custom("delete").Click("deleteUser");
}
}).Title("Commands");
}))
or easily, instead of adding custom button, just add the destroy button
hope this will help you

Columns in Kendo Grid MVC Multiline

I have kendo grid MVC like this:
#(Html.NFSGrid<dynamic>("PortfolioGrid")
.Name("PortfolioGrid")
.EnableCustomBinding(true)
//.Selectable()
.BindTo(Model)
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(countpaging)
.Model(m =>
{
foreach (var Allcoulms in (List<HtmlHelperGridBuilder.GridCol>)ViewData["ViewDataGridfildes"])
{
if (Allcoulms.ColumnName == "Id")
{
m.Id(Allcoulms.ColumnName);
}
else
{
m.Field(Allcoulms.ColumnName, Type.GetType("System.String")).Editable(true);
}
}
})
.ServerOperation(true)
.Read(read => read.Action("Read", "Portfolio").Data("portFolioNameSpace.additionalInfo")
)
)
.HtmlAttributes(new { style = "width:2000;" })
.Columns(columns =>
{
columns.Template(p => { }).ClientTemplate("<input name='selectedIds' type='checkbox' value=\"#=Id#\" class='check_row' onchange='portFolioNameSpace.changeChk(event,this.checked,this);'/>")
.HeaderTemplate("<div style='background=#C7CA21 ;width= 40%'><input type='checkbox' style='outline: 2px solid #cfbe62' class='selectAll' onclick='portFolioNameSpace.buttonclick(event)'/></div>")
.HeaderHtmlAttributes(new { style = "text-align:center;" })
.Width(30);
columns.Template(#<text></text>).Title(T("روند").ToString()).Width(30).ClientTemplate("<a onclick='portFolioNameSpace.onclickFlowFPortfolio(event)'><i class='iconmain-showall'></i></a>");
columns.Template(#<text></text>).Title(T("اصل سند").ToString()).Width(50).ClientTemplate("<a onclick='portFolioNameSpace.GetFormData(event)'><i class='iconmain-Accepted'></i></a>");
foreach (var Allcoulms in (List<HtmlHelperGridBuilder.GridCol>)ViewData["ViewDataGridfildes"])
{
if (Allcoulms.ColumnName == "Id")
{
columns.Bound(Allcoulms.ColumnName).Visible(false);
}
else if (Allcoulms.ColumnName == "Subject")
{
columns.Bound(Allcoulms.ColumnName).Width(Allcoulms.ColumnWidth).Title(T(Allcoulms.ColumnTitle).ToString()).HtmlAttributes(new { style = "text-align:center;" });
}
else if (Allcoulms.ColumnName == "Comment")
{
columns.Bound(Allcoulms.ColumnName).Width(200).Title(T(Allcoulms.ColumnTitle).ToString()).HtmlAttributes(new { style = "text-align:center;" }).ClientTemplate("<input type=\"text\" id=\"#=Id#\" value=\"#=Comment#\"/>");
}
else if (Allcoulms.ColumnName == "notViewdRows")
{
}
else
{
columns.Bound(Allcoulms.ColumnName).Width(Allcoulms.ColumnWidth).Title(T(Allcoulms.ColumnTitle).ToString()).HtmlAttributes(new { style = "text-align:center;" }).HeaderHtmlAttributes(new { style = "text-align:center;" });
}
}
})
.Pageable(pager => pager.Enabled(true))
.Scrollable()
.Filterable()
.Resizable(resize => resize.Columns((true)))
.Reorderable(reorder => reorder.Columns(true))
.Events(e => e
.DataBound("portFolioNameSpace.gridDataBound")
)
)
so the problem is when the lengh of a coulmn is more than what i set in width it makes 2line like this picture so how can i make it 1ine without set specific width?
Add the CSS attributes overflow: hidden; white-space: nowrap; to the column definition, something like this:
columns.Bound(Allcoulms.ColumnName).Width(Allcoulms.ColumnWidth).Title(T(Allcoulms.ColumnTitle).ToString()).HtmlAttributes(new { style = "text-align:center; overflow: hidden; white-space: nowrap;" }).HeaderHtmlAttributes(new { style = "text-align:center;" });
I tested and it works, see if it works for you too.
EDIT
Since you're using column templates, you also have the option of adding the CSS properties directly in your CSS file or even inline (although the latter isn't a good practice)

Kendo UI Grid in a Splitter

I've got a splitter in my layout, to display informations.
My display is good, but when I had my grid in my index.html (which is called in my layout by #RenderBody() ) , my splitter isn't well displayed anymore ...
Everything is on a single page, without splitter ...
Any ideas ?
EDIT :
Yes sorry .
There's my Controller :
public class HomeController : Controller
{
private static string path = #"C:\LogIngesup\log.xml";
public ActionResult Index()
{
DataTable logs = Write_Log.Read.loadXML(path);
return View(logs);
}
}
There my layout :
<body>
#(Html.Kendo().Splitter()
.Name("vertical")
.Orientation(SplitterOrientation.Vertical)
.Panes(verticalPanes =>
{
verticalPanes.Add()
.HtmlAttributes(new { id = "middle-pane" })
.Scrollable(false)
.Collapsible(false)
.Content(
Html.Kendo().Splitter()
.Name("horizontal")
.HtmlAttributes(new { style = "height: 100%;" })
.Panes(horizontalPanes =>
{
horizontalPanes.Add()
.HtmlAttributes(new { id = "left-pane" })
.Size("230px")
.Resizable(false)
.Collapsible(true)
.Content(#<div>#RenderPage("~/Views/Home/Calendrier.cshtml")</div>);
horizontalPanes.Add()
.HtmlAttributes(new { id = "center-pane" })
.Content(#<div class="pane-content">
<section id="main">
#RenderBody()
</section>
</div>);
horizontalPanes.Add()
.HtmlAttributes(new { id = "right-pane" })
.Collapsible(true)
.Size("220px")
.Content(#<div class="pane-content">
#RenderPage("~/Views/Home/XML.cshtml")
</div>);
}).ToHtmlString()
);
verticalPanes.Add()
.Size("70px")
.HtmlAttributes(new { id = "bottom-pane" })
.Resizable(false)
.Collapsible(true)
.Content(#<div class="pane-content" style="text-align:center">
<p>Application développée par : Dan</p>
</div>);
}))
</body>
And eventually my index.html :
#{
ViewBag.Title = "LogApp";
}
#model System.Data.DataTable
#(Html.Kendo().Grid(Model)
.Name("Grid")
.Columns(columns => {
foreach (System.Data.DataColumn column in Model.Columns)
{
columns.Bound(column.DataType, column.ColumnName);
}
})
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
)
I'm aware about any suggestion on my code :)
Furthermore I've got an issue :
When I try to add this in my grid (index.html):
.DataSource(datasource=>datasource
.Ajax()
.PageSize(10)
)
.Selectable(selectable => selectable.Mode(GridSelectionMode.Single))
I can't go to other page, and can't select a row ... Can you help me ?
(It works when I write directly the url : localhost\?Grid-page=2)
I had the same problem when putting a Kendo UI Splitter inside a Kendo UI Tabcontrol.
When the Tabcontrol was made before the Splitter it was making this problem, but when I just reversed the order it worked fine.
i.e I changed from:
$(document).ready(function ()
{
$("#ManagementMenu").kendoTabStrip();
$("#splitter").kendoSplitter({
panes: [
{ size: "200px", resizable: false},
{ size: "500px", collapsible: false}
],
});
}
to
$(document).ready(function ()
{
$("#splitter").kendoSplitter({
panes: [
{ size: "200px", resizable: false},
{ size: "500px", collapsible: false}
],
});
$("#ManagementMenu").kendoTabStrip();
}
and the problem was fixed.

Resources