I am using the MVC grid helper to display my grid with a pop up editor. The grid is showing a subset of fields but the editor shows all the fields which forces the popup editor to be scrollable.
Is there a way to keep the update/cancel button always visible on the screen.
Please see the attached images for an explanation of what I am trying to achieve.
Thanks in advance for any help.
9 Answers, 1 is accepted
I tried to reproduce the same behavior on your side, however the Window widget doesn't overflow with scrolling as demonstrated in the provided screenshots (most probably custom CSS styles are applied to the widget?). With the default settings you can enable the desired behavior by wrapping the current PopUp editor content in a "div" element with CSS overflow set to "scroll":
<div style=
"overflow:scroll; height: 400px"
>
.... More data
</div>
Vladimir Iliev
Telerik
Index.cshtml
@(Html.Kendo().Grid<
Project.ViewModels.ConfigurationSetting
>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(a => a.Name);
columns.Bound(a => a.ServiceName).Title("Service<
br
/>Name");
columns.Bound(a => a.TestMode).Title("Is in<
br
/>Test Mode?");
columns.Bound(a => a.JobSourceItem).Title("Job Source").ClientTemplate("#=JobSourceItem.JobSourceName#").Width(200);
columns.Bound(a => a.DatabaseLiveConnection).Title("Live Database<
br
/>Connection");
columns.Bound(a => a.DatabaseTestConnection).Title("Test Database<
br
/>Connection");
columns.Bound(a => a.Timer).Title("Timer Settings (ms)");
columns.Command(command => command.Edit());
})
.Editable(edit =>
edit.Mode(GridEditMode.PopUp)
.Window(window =>
window.Animation(true)
.Scrollable(true)
.Resizable(resize => resize.Enabled(true))
.Width(650)
.Height(600)
)
.TemplateName("ConfigurationSettingEditor")
)
.Pageable()
.Pageable(c => c.PageSizes(new int[] { 10, 20, 50, 100 }))
.Sortable()
.HtmlAttributes(new { style = "height:600px;" })
.Events(events => events.DataBound("onDataBound"))
.Scrollable()
.Resizable(c => c.Columns(true))
.ClientDetailTemplateId("template")
.Events(e => e.Edit("onEdit"))
.ToolBar(toolBar =>
{
toolBar.Create();
})
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("ConfigurationSetting_Read", "Home"))
.Update(update => update.Action("ConfigurationSetting_Update", "Home"))
.Create(create => create.Action("ConfigurationSetting_Create", "Home"))
.Events(events => events.Error("error_handler"))
.Model(model =>
{
model.Id(a => a.ConfigurationSettingID);
model.Field(a => a.JobSourceItem).DefaultValue(new Project.ViewModels.JobSourceSetting());
})
)
)
<
script
id
=
"template"
type
=
"text/kendo-tmpl"
>
@(Html.Kendo().Grid<
Project.ViewModels.ConfigurationSettingItem
>()
.Name("Grid_#=ConfigurationSettingID#")
.Columns(columns =>
{
columns.Bound(b => b.KeyName);
columns.Bound(b => b.KeyValue).HtmlAttributes(new { style = "overflow: hidden;text-overflow: ellipsis;white-space:nowrap;" }).EditorTemplateName("ConfigurationSettingItemEditor");
columns.Bound(b => b.SqlDBType);
columns.Bound(b => b.Enabled);
columns.Command(command =>
{
command.Edit();
});
}
)
.Sortable()
.Pageable(c => c.PageSizes(new int[] { 10, 20, 50, 100 }))
.Scrollable()
.ToolBar(toolBar =>
{
toolBar.Create();
}
)
.Editable(edit =>
{
edit.Mode(GridEditMode.InLine);
edit.Enabled(true);
}
)
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(datasource => datasource
.Ajax()
.PageSize(10)
.ServerOperation(true)
.Read(read => read.Action("ConfigurationItem_Read", "Home", new { configurationSettingID = "#=ConfigurationSettingID#" }))
.Update(update => update.Action("ConfigurationItem_Update", "Home"))
.Create(create => create.Action("ConfigurationItem_Create", "Home", new { configurationSettingID = "#=ConfigurationSettingID#" }))
.Events(events => events.Error("error_handler"))
.Model(model =>
{
model.Id(q => q.ID);
model.Field(q => q.KeyValue).Editable(true);
model.Field(q => q.Enabled).DefaultValue(true);
})
)
.ToClientTemplate()
)
</
script
>
<
script
type
=
"text/javascript"
>
function error_handler(e) {
if (e.errors) {
var message = "Errors:\n";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
alert(message);
}
}
function onEdit(e) {
//attach validator to the PopUp window
$("[data-role=window]").kendoValidator();
}
function onDataBound() {
this.expandRow(this.tbody.find("tr.k-master-row").first());
}
function resizeGrid() {
var gridElement = $("#Grid");
var dataArea = gridElement.find(".k-grid-content");
var newGridHeight = $(document).height() - 200;
var newDataAreaHeight = newGridHeight - 85;
dataArea.height(newDataAreaHeight);
gridElement.height(newGridHeight);
$("#Grid").data("kendoGrid").refresh();
}
$(document).ready(function () {
resizeGrid();
});
</
script
>
-----------------------------------------------------------
ConfigurationSettingEditor.cshtml
@model Project.ViewModels.ConfigurationSetting
@Html.HiddenFor(cs => cs.ConfigurationSettingID)
<
div
class
=
"container"
>
<
div
class
=
"col-xs-12 col-sm-12 col-md-12 col-lg-12"
>
<
div
class
=
"form-horizontal"
>
<
div
class
=
"panel panel-primary"
>
<
div
class
=
"panel-heading"
>Standard Settings</
div
>
<
div
class
=
"panel-body"
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.Name, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label " })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.ServiceName, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.ServiceName, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.JobSourceItem, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8"
>
@(
Html.Kendo().DropDownListFor(m => m.JobSourceItem)
.DataValueField("JobSourceSettingID")
.DataTextField("JobSourceName")
.HtmlAttributes(new { style = "width:100%;" })
.DataSource(
data => data.Read("Get_JobSources", "Home")
).AutoBind(false)
.OptionLabel("Select Source Name....")
)
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.TestMode, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.CheckBoxFor(m => m.TestMode)
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.Timer, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.Kendo().NumericTextBoxFor(m => m.Timer).Format("#").Step(10000).Min(60000)
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.Enabled, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.CheckBoxFor(m => m.Enabled)
</
div
>
</
div
>
</
div
>
</
div
>
<
div
class
=
"panel panel-primary"
>
<
div
class
=
"panel-heading"
>Database Settings</
div
>
<
div
class
=
"panel-body"
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.DatabaseLiveConnection, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.DatabaseLiveConnection, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.DatabaseTestConnection, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.DatabaseTestConnection, new { @class = "form-control" })
</
div
>
</
div
>
</
div
>
</
div
>
<
div
class
=
"panel panel-primary"
>
<
div
class
=
"panel-heading"
>File Server Settings</
div
>
<
div
class
=
"panel-body"
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.LiveFileServer, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.LiveFileServer, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.TestFileServer, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.TestFileServer, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.SuccessFolder, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.SuccessFolder, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.MonitoringFolder, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.MonitoringFolder, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.ErrorFolder, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.ErrorFolder, new { @class = "form-control" })
</
div
>
</
div
>
</
div
>
</
div
>
<
div
class
=
"panel panel-primary"
>
<
div
class
=
"panel-heading"
>Email Settings</
div
>
<
div
class
=
"panel-body"
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.MailServer, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.MailServer, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.DeveloperEmail, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.DeveloperEmail, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.ErrorEmail, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.ErrorEmail, new { @class = "form-control" })
</
div
>
</
div
>
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.FromEmail, new { @class = " col-xs-4 col-sm-4 col-md-4 col-lg-4 control-label" })
<
div
class
=
"col-xs-8 col-sm-8 col-md-8 col-lg-8 "
>
@Html.TextBoxFor(m => m.FromEmail, new { @class = "form-control" })
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
I would suggest to disable the Window "Scrollable" option, remove the "Height" option and wrap the content of the editor template in a "div" element with CSS "oveflow" style set to "scroll". That way the content will be scrollable and the "Update" / "Cancel" buttons will be always visible.
e.g.:
.Window(window =>
window.Animation(
true
)
.Resizable(resize => resize.Enabled(
true
))
.Width(650)
))
<
div
style
=
"overflow: scroll; height: 600px"
>
content of the EditorTemplate
</
div
>
Vladimir Iliev
Telerik
On another issue. Is there a way to force the nested grid to display a pop up window for editing rather than in cell.
I would like to keep this control consistent and have all editing done within the pop up windows rather than having pop-window for the main grid and then in line editing for the nested grid.
You can change the edit mode to PopUp the same way you change the edit mode of the parent Grid. If you experience difficulties changing the edit mode of the nested Grid I would suggest to open a new support ticket/form post and provide your current Grid setup.
Vladimir Iliev
Telerik
It is using the same code above.
No JS error or anything else happen. The system just does nothing with the update/ add button on the child grids.
From the provided information it's not clear for us what is the exact reason for current behavior. Could you please download this demo from our CodeLibrary and check if adding the following code to all Grids enables the PopUp editing (please check this screencast):
.Editable(e => e.Mode(GridEditMode.PopUp))
Kind Regards,
Vladimir Iliev
Telerik
Uncaught Error: Invalid template:
'<div class="editor-label"><label for="Enabled">Enabled</label></div><div class="editor-field"><input checked="checked" class="check-box" data-val="true" data-val-required="The Enabled field is required." id="Enabled" name="Enabled" type="checkbox" value="true" /><input name="Enabled" type="hidden" value="false" /> <span class="field-validation-valid" data-valmsg-for="Enabled" data-valmsg-replace="true"></span></div><div class="editor-label"><label for="KeyName">Setting Name</label></div><div class="editor-field"><input class="k-textbox form-control" data-val="true" data-val-required="The Setting Name field is required." id="KeyName" name="KeyName" type="text" value="" /> <span class="field-validation-valid" data-valmsg-for="KeyName" data-valmsg-replace="true"></span></div><div class="editor-label"><label for="KeyValue">Setting Value</label></div><div class="editor-field"><textarea class="text-box multi-line" data-val="true" data-val-required="The Setting Value field is required." id="KeyValue" name="KeyValue"></textarea> <span class="field-validation-valid" data-valmsg-for="KeyValue" data-valmsg-replace="true"></span></div><div class="editor-label"><label for="SqlDBType">SQL Data Type </label></div><div class="editor-field"><input class="k-textbox form-control" data-val="true" data-val-required="The SQL Data Type field is required." id="SqlDBType" name="SqlDBType" type="text" value="" /> <span class="field-validation-valid" data-valmsg-for="SqlDBType" data-valmsg-replace="true"></span></div>'
Generated code:
'var o,e=kendo.htmlEncode;with(data){o='
<div class=
"editor-label"
><label
for
=
"Enabled"
>Enabled</label></div><div class=
"editor-field"
><input checked=
"checked"
class=
"check-box"
data-val=
"true"
data-val-required=
"The&';32;Enabled&;o+='32;field&';32;is&;o+='32;required."
id=
"Enabled"
name=
"Enabled"
type=
"checkbox"
value=
"true"
/><input name=
"Enabled"
type=
"hidden"
value=
"false"
/> <span class=
"field-validation-valid"
data-valmsg-
for
=
"Enabled"
data-valmsg-replace=
"true"
></span></div><div class=
"editor-label"
><label
for
=
"KeyName"
>Setting Name</label></div><div class=
"editor-field"
><input class=
"k-textbox&';32;form-control"
data-val=
"true"
data-val-required=
"The&;o+='32;Setting&';32;Name&;o+='32;field&';32;is&;o+='32;required."
id=
"KeyName"
name=
"KeyName"
type=
"text"
value=
""
/> <span class=
"field-validation-valid"
data-valmsg-
for
=
"KeyName"
data-valmsg-replace=
"true"
></span></div><div class=
"editor-label"
><label
for
=
"KeyValue"
>Setting Value</label></div><div class=
"editor-field"
><textarea class=
"text-box&';32;multi-line"
data-val=
"true"
data-val-required=
"The&;o+='32;Setting&';32;Value&;o+='32;field&';32;is&;o+='32;required."
id=
"KeyValue"
name=
"KeyValue"
></textarea> <span class=
"field-validation-valid"
data-valmsg-
for
=
"KeyValue"
data-valmsg-replace=
"true"
></span></div><div class=
"editor-label"
><label
for
=
"SqlDBType"
>SQL Data Type </label></div><div class=
"editor-field"
><input class=
"k-textbox&';32;form-control"
data-val=
"true"
data-val-required=
"The&;o+='32;SQL&';32;Data&;o+='32;Type&';32;&;o+='32;field&';32;is&;o+='32;required."
id=
"SqlDBType"
name=
"SqlDBType"
type=
"text"
value=
""
/> <span class=
"field-validation-valid"
data-valmsg-
for
=
"SqlDBType"
data-valmsg-replace=
"true"
></span></div>
';}return o;'
It would seem that others have had this same issue as well.
http://www.kendoui.com/forums/kendo-ui-complete-for-asp-net-mvc/grid/hierarchical-grid-example-invalid-template-error.aspx#boENQq6aG2OF1P8AAFTdxQ
https://gist.github.com/advancedrei/5724537
Although I haven't got this bit of code working.
making the following change to the webconfig has helped as a temporary fix:
<
system.web
>
<
compilation
debug
=
"true"
targetFramework
=
"4.5"
>
<
assemblies
>
<
add
assembly
=
"System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
/>
</
assemblies
>
</
compilation
>
<!--<httpRuntime targetFramework="4.5" encoderType="System.Web.Security.AntiXss.AntiXssEncoder, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />-->
<
httpRuntime
targetFramework
=
"4.5"
/>
If you need more info please let me know.
Please note that issues related to AntiXssEncoder are not directly related to KendoUI as we cannot prevent encoding of the template output. I can only suggest to either turn-off the encoder or try to implement the linked solution in Github.
Vladimir Iliev
Telerik