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
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.
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.
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 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 });
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)