How do I display Kendo Grid inside Kendo Grid cell? - kendo-ui

I am using Kendo Grid in my MVC application to display data. It works perfectly fine. But I would like to show another grid inside grid cell. I have done my research and tried different things, but I didn't find any solution. Please suggest.
Here is my code.
#(Html.Kendo().Grid<TimeSheetManagement.Models.ClientView>()
.Name( "Clients" )
.Columns( columns =>
{
columns.Bound( e => e.Name );
columns.Bound( e => e.Address );
columns.Bound( e => e.City );
columns.Bound( e => e.State );
columns.Bound( e => e.ZipCode );
columns.Template( e => e.Contacts ).ClientTemplate( "#= buildContactsGrid(data) #" );
columns.Bound( e => e.CreatedDate );
columns.Bound( e => e.CreatedBy );
columns.Bound( e => e.UpdatedDate );
columns.Bound( e => e.UpdatedBy );
columns.Bound( "" ).ClientTemplate( #Html.ActionLink( "Edit" , "Create" , new { clientId = "#=Id#" } , new { title = "Edit Client" } ).ToHtmlString() );
} )
.Pageable().Sortable().Filterable()
.AutoBind( true )
.DataSource( source => source.Ajax()
.PageSize( 20 )
.Read( read => read.Action( "GetClients" , "Client" ) )
)
)
Here is my JavaScript function.
<script>
function buildContactsGrid(client)
{
var htmlContacts = '';
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: '#Url.Action( "GetJsonContactsByClientId" )',
data: JSON.stringify({
'sClientId': client.Id
}),
dataType: "json",
async: false,
success: function (response) {
htmlContacts += "<table style='border:1px solid black;'><tr><th>First Name</th><th>Last Name</th><th>Role</th></tr><tr>";
$(response).each(function (index, item) {
htmlContacts +="<td>"+ item.FirstName +"</td><td>"+ item.LastName+"</td><td>"+item.Role +"</td></tr>";
});
htmlContacts += "</table>";
}
});
return htmlContacts;
}
</script>
I was able to build a table in JavaScript function and display in grid cell, but I would like to display Kendo Grid.

After spent some days on google by doing some research, I found this post link, they explained why client template not being bound on load.
Here is my grid inside grid cell:
columns.Template( e => "" ).Title("Contacts").ClientTemplate(
Html.Kendo().Grid<TimeSheetManagement.Models.ContactView>()
.Name( "Clients_#=Id#" )
.Columns( c =>
{
c.Bound( e1 => e1.FullName );
c.Bound( e1 => e1.Role );
c.Bound( e1 => e1.Email );
c.Bound( e1 => e1.PhoneNumber );
} )
.AutoBind( true )
.DataSource( source1 => source1.Ajax()
.PageSize( 5 )
.Read( read1 => read1.Action( "GetContactsByClientId" , "Client" , new { sClientId = "#=Id#" } ) )
)
.ToClientTemplate()
.ToHtmlString()
);
And I have this event on the grid.
.Events( e => e.DataBound( "onGridDataBound" ) )
And finally I added this code in the script.
function onGridDataBound(e)
{
$('#Clients script').appendTo(document.body);
}
Here is the output as I expected. Let me know if you have any questions.

Related

ReferenceError: server is not defined - CkEditor5

I tried using CKEditor5 for my project and when I activated insert image and tried using it, It says ReferenceError: server is not defined. Here is the code:
class MyUploadAdapter {
constructor( loader ) {
this.loader = loader;
}
upload() {
server.onUploadProgress( data => {
loader.uploadTotal = data.total;
loader.uploaded = data.uploaded;
} );
return loader.file
.then( file => server.upload( file ) );
}
abort() {
// Reject the promise returned from the upload() method.
server.abortUpload();
}
_initRequest() {
const xhr = this.xhr = new XMLHttpRequest();
xhr.open( 'POST', '{{ route('ck5_store')}}',true );
xhr.setRequestHeader('X-CSRF-TOKEN',$('meta[name="csrf-token"]').attr('content'));
xhr.responseType = 'json';
}
_initListeners( resolve, reject, file ) {
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = `Couldn't upload file: ${ file.name }.`;
xhr.addEventListener( 'error', () => reject( genericErrorText ) );
xhr.addEventListener( 'abort', () => reject() );
xhr.addEventListener( 'load', () => {
const response = xhr.response;
if ( !response || response.error ) {
return reject( response && response.error ? response.error.message : genericErrorText );
}
resolve( {
default: response.url
} );
} );
if ( xhr.upload ) {
xhr.upload.addEventListener( 'progress', evt => {
if ( evt.lengthComputable ) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
} );
}
}
_sendRequest( file ) {
const data = new FormData();
data.append( 'upload', file );
this.xhr.send( data );
}
}
function SimpleUploadAdapterPlugin( editor ) {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
return new MyUploadAdapter( loader );
};
}
ClassicEditor
.create( document.querySelector( '#tab-content-{{$MODULE}} form#{{$MODULE}}_form textarea[id=form_{{$MODULE}}_details]') ,
{
extraPlugins: [ SimpleUploadAdapterPlugin ],
})
.then( editor => {
console.log( editor );
} )
.catch( error => {
console.error( error );
} );
Any idea on what is the problem? Already tried looking for solutions but cannot find anywhere else. Thank you in advance.
I was having the same issue. My solution:
// Starts the upload process.
upload() {
return this.loader.file
.then( file => new Promise( ( resolve, reject ) => {
this._initRequest();
this._initListeners( resolve, reject, file );
this._sendRequest( file );
} ) );
}
// Aborts the upload process.
abort() {
if ( this.xhr ) {
this.xhr.abort();
}
}
I found this solution following documentation.

convert rxjs5 operators into rxjs6

i have following code written in rxjs5 and it broke with rxjs6
can some one help me with write in rxjs 6
its failing mergemap receiving groupedObserable which does not have count method and along also filter method does not exist.
list [
{id: '1', type: 't1', name: 'f1', des:'d1', selected: true},
{id: '2', type: 't1', name: 'f2', des:'d2', selected: false},
{id: '3', type: 't1', name: 'f11', des:'d11', selected: false},
{id: '4', type: 't1', name: 'f22', des:'d22', selected: true},
]
Observable.from(list)
.filter(a => a.name != null)
.groupBy(i => i.type)
.mergeMap(list => {
let count = list.count;
let selectedCount = 0;
list.filter( f => f.selected).count.subscribe(c => selectedCount = c)
return count.map(count => {
{
key: list.key,
totalCount: count,
selected: selectedCount
}
}
}).reduce((x, y) => {
x.isValid = x.selectedCount > 0
return x;
}).subscribe(r => {
console.log(r + 'any item selected')
}
)
when i tried to write in rxjs6 only progress i was able to made till here
thanks in advance.
from(list)
.pipe(
filter( s=> s.name != null) ,
groupBy(i => i.type),
mergeMap( (value, index) => {
value.count // that's where it starts to fail
}
))
The equivalent rxjs6 code should be like this:
from(list)
.pipe(
filter(a => a.name != null),
groupBy(i => i.type),
mergeMap((p) => {
return p.pipe(
filter(f => f.selected),
count(),
mergeMap(c => {
return p.pipe(
count(),
map(totalCount => {
return {
key: p.key,
totalCount: totalCount,
selected: c
};
})
);
})
);
}),
reduce((x, y) => {
//please adjust your code here as i could not see isValid on x
x.isValid = x.selectedCount > 0;
return x;
})
).subscribe(r => {
console.log(r + 'any item selected')
}
)
Hope it gives an idea of how to proceed.

ckeditor with placeholder plguin enhancement double click issue

I need a placeholder/variable that takes name, defaultValue, tooltip/description. I created a plugin and it is working fine in the editor/create mode. When placeholder is created, it is adding the following tags to source
<var class="cke_placeholder" name="varName" title="varToolTip">[[varDefaultValue]]</var>
Image that depicts create & edit mode differences
When I save the html content with placehoder in db and trying to load it back to ckeditor, I am not able to get the + symbol and hence not able to launch the editor.
Here is my ckeditor/plugins/var/plguin.js
'use strict';
( function() {
CKEDITOR.plugins.add( 'var', {
requires: 'widget,dialog',
icons: 'var', // %REMOVE_LINE_CORE%
hidpi: true, // %REMOVE_LINE_CORE%
onLoad: function() {
CKEDITOR.dialog.add( 'var', this.path + 'dialogs/var.js' );
},
init: function( editor ) {
this.registerWidget( editor );
editor.ui.addButton && editor.ui.addButton( 'Var', {
label: 'Create Variable',
command: 'var',
toolbar: 'insert',
icon: 'var'
} );
},
registerWidget: function(editor){
var that = this;
// Put ur init code here.
editor.widgets.add( 'var', {
// Widget code.
dialog: 'var',
pathName: 'var',
// We need to have wrapping element, otherwise there are issues in
// add dialog.
template: '<var class="cke_placeholder">[[]]</var>',
downcast: function() {
return new CKEDITOR.htmlParser.text( '<var class="cke_placeholder" name="'+this.data.name+'" title="'+this.data.description+'">[[' + this.data.defaultValue + ']]</var>' );
},
init: function() {
this.setData( 'defaultValue', this.element.getText().slice( 2, -2 ) );
this.setData( 'name', this.element.getAttribute("name") );
this.setData( 'description', this.element.getAttribute("title") );
},
data: function() {
this.element.setText( '[[' + this.data.defaultValue + ']]' );
this.element.setAttribute('name', this.data.name );
this.element.setAttribute('title', this.data.description );
}
} );
},
afterInit: function( editor ) {
this.registerWidget( editor );
/*var placeholderReplaceRegex = /\[\[([^\[\]])+\]\]/g;
editor.dataProcessor.dataFilter.addRules( {
text: function( text, node ) {
var dtd = node.parent && CKEDITOR.dtd[ node.parent.name ];
// Skip the case when placeholder is in elements like <title> or <textarea>
// but upcast placeholder in custom elements (no DTD).
if ( dtd && !dtd.span )
return;
return text.replace( placeholderReplaceRegex, function( match ) {
// Creating widget code.
var widgetWrapper = null,
innerElement = new CKEDITOR.htmlParser.element( 'span', {
'class': 'cke_placeholder'
} );
// Adds placeholder identifier as innertext.
innerElement.add( new CKEDITOR.htmlParser.text( match ) );
widgetWrapper = editor.widgets.wrapElement( innerElement, 'placeholder' );
// Return outerhtml of widget wrapper so it will be placed
// as replacement.
return widgetWrapper.getOuterHtml();
} );
}
} );*/
}
} );
} )();
Here is my ckeditor/plugins/var/dialogs/var.js
'use strict';
CKEDITOR.dialog.add( 'var', function( editor ) {
//var lang = editor.lang.var,
//generalLabel = editor.lang.common.generalTab,
var generalLabel = 'General',
validRegex = /^[^\[\]<>]+$/,
emptyOrInvalid = ' can not be empty. It can not contain any of following characters: [, ], <, >',
invalid = ' can not contain any of following characters: [, ], <, >';
return {
title: 'Variable properties',
minWidth: 300,
minHeight: 80,
contents: [
{
id: 'info',
label: generalLabel,
title: generalLabel,
elements: [
// Dialog window UI elements.
{
id: 'name',
type: 'text',
style: 'width: 100%;',
label: 'Name',
'default': '',
required: true,
validate: CKEDITOR.dialog.validate.regex( validRegex, 'name'+emptyOrInvalid ),
setup: function( widget ) {
this.setValue( widget.data.name );
},
commit: function( widget ) {
widget.setData( 'name', this.getValue() );
}
},
{
id: 'defaultValue',
type: 'text',
style: 'width: 100%;',
label: 'Default Value',
'default': '',
required: true,
validate: CKEDITOR.dialog.validate.regex( validRegex, 'Default Value'+emptyOrInvalid ),
setup: function( widget ) {
this.setValue( widget.data.defaultValue );
},
commit: function( widget ) {
widget.setData( 'defaultValue', this.getValue() );
}
},
{
id: 'description',
type: 'text',
style: 'width: 100%;',
label: 'Description',
'default': '',
required: true,
validate: CKEDITOR.dialog.validate.regex( validRegex, 'Description'+invalid ),
setup: function( widget ) {
this.setValue( widget.data.description );
},
commit: function( widget ) {
widget.setData( 'description', this.getValue() );
}
}
]
}
]
};
} );

How to access a Model property in a TreeView on Telerik MVC TreeView (Kendo UI)

How do I access the ID property of the model when I select one of the treeview nodes? (I want to display the details based on ID next to the treeview)
#(Html.Kendo().TreeView()
.Name("OrganizationTree")
.HtmlAttributes(new { #class = "demo-section" })
.DataTextField("Name")
.DragAndDrop(true)
.ExpandAll(true)
.Events(events => events
.Select("onOrgSelect")
.Drop("onOrgDrop")
)
.DataSource(dataSource => dataSource
.Model(m=> m
.Id("ID")
.HasChildren("HasChildren")
)
.Read(read => read
.Action("Organizations_Read", "Organizations")
)
)
)
Here's the javascript function:
function onOrgSelect(e)
{
var id = $("#" + e.node.id).?????;
GetOrganization(id);
}
Check the common operations topic here.
function onSelect(e) { // this refers to the TreeView object var dataItem = this.dataItem(e.node);
console.log("Selected node with id=" + dataItem.id);
}
$("#treeview").kendoTreeView({ dataSource: [ { id: 1, text: "Item 1", items: [ { id: 3, text: "Item 3" } ] }, { id: 2, text: "Item 2" } ], select: onSelect });

Kendo grid update issue

i'm new to Kendo Grid.Can anyone help me.In Grid if Data is not given onclick of update button validation is raised.but the row gets updated.Update shouldn't happen
#(Html.Kendo().Grid<Project.Models.EmployeeDetail>()
.Name("EmployeeGrid")
.Columns(col =>
{
col.Bound(p => p.EName).Width("15%").Title("Name")
col.Bound(a => a.Address).Title("Address").Width("15%");
col.Command(a => { a.Edit(); }).Width("10%").Title("Edit");
col.Command(a => {a.Destroy();}).Title("Delete").Width("10%");
}
)
.Pageable()
.ToolBar(toolbar => toolbar.Create().Text("Add"))
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(source => source
.Ajax()
.PageSize(4)
.Model(a => a.Id(b => b.Name))
.Read(read => read.Action("EmpGrid", "Employee"))
.Create(create => create.Action("EmpGridCreate", "Employee"))
.Update(update => update.Action("EmpGridUpdate", "Employee"))
.Destroy(del => del.Action("EmpGridDelete", "Employee"))
)
.Events(e =>
{
e.Save("SaveDetails");
e.Edit("EditDetails");
}))
Save Event Code:
function SaveDetails(e)
{
var result=true;
writeMultipleMessage("error", "", "EName");
var EmpName = $("#EName").val();
if(EmpName ==""|| EmpName == null || EmpName ==undefined)
{
writeMultipleMessage("error", "Please Provide Employee Name", "EName");
e.preventDefault();
result = false;
}
else
{
e.model.EName=EName;
}
writeMultipleMessage("error", "", "Address");
var AddressDet=$("#Address").val();
if (AddressDet == "" || AddressDet == null || AddressDet == undefined) {
writeMultipleMessage("error", "Please provide Address", "Address");
e.preventDefault();
result = false;
}
else {
e.model.Address = Address;
}
var Grid = $("#EmployeeGrid").data("kendoGrid");
Grid.refresh();
}
I have shown my code above
Update is Hitting Save Event.Row is updated though validation is thrown.Row should not get updated
Can anyone Suggest some idea.Thanks in Advance.Sorry if it is a repeated Question.
The issue is that $("#EmpName").val() isn't valid to the row you are trying to update. You have to look in the DOM object for the Kendo Grid row for your Column value. We can use $(e.cell).find() to locate the column you need to get for that row.
Try your JavaScript like this:
function SaveDetails(e)
{
var result=true;
writeMultipleMessage("error", "", "EName");
var EmpName = $(e.cell).find("#EName").val();
if(EmpName ==""|| EmpName == null || EmpName ==undefined)
{
writeMultipleMessage("error", "Please Provide Employee Name", "EName");
e.preventDefault();
result = false;
}
else
{
e.model.EName=EName;
}
writeMultipleMessage("error", "", "Address");
var AddressDet = $(e.cell).find("#Address").val();
if (AddressDet == "" || AddressDet == null || AddressDet == undefined) {
writeMultipleMessage("error", "Please provide Address", "Address");
e.preventDefault();
result = false;
}
else {
e.model.Address = Address;
}
var Grid = $("#EmployeeGrid").data("kendoGrid");
Grid.refresh();
}
Here is Kendo UI's treasure trove of examples for the Kendo UI Grid for further assistance:
Kendo UI Grid Demo projects (MVC version)
Kendo UI Grid Demo projects (HTML5/JS version)

Resources