dgrid in a custom widget - javascript

I have a custom widget to which I pass data from backend. Grid shown on the correct place but not showing data on it. I tried with hardcoded data but only the headers are shown. Grid has height and width set.
Here is the code snippet. I would appreciate any help. thanks.
define(["dojo/_base/declare", "dijit/_WidgetBase",
"dijit/_TemplatedMixin", "dijit/_WidgetsInTemplateMixin",
"dijit/_OnDijitClickMixin",
GridWidget.js
define(["dojo/_base/declare", "dijit/_WidgetBase",
"dijit/_TemplatedMixin", "dijit/_WidgetsInTemplateMixin",
"dijit/_OnDijitClickMixin", "dojo/text!./templates/GridWidget.html",
"dgrid/Grid","dgrid/Keyboard", "dgrid/Selection", "dgrid/extensions/DijitRegistry", "dstore/Memory", "dstore/Trackable"], function(declare, _WidgetBase,
_TemplatedMixin, _WidgetsInTemplateMixin,
_OnDijitClickMixin, template, Grid, Keyboard, Selection, DigitRegistry, Memory, Trackable) {
return decalare("GridWidget", [_WidgetBase, _OnDijitClickMixin, _TemplatedMixin, _WidgetsInTemplateMixin], {
widgetsInTemplate: true,
baseClass: 'GridWidget',
templateString: template,
data: null,
store: null,
grid: null,
columns: null,
constructor: function(data) {
this.data = data;
},
_setData: function(input) {
if (input) {
this._set("data", input);
}
},
getData: function() {
return this.data;
},
postCreate : function() {
this.inherited(arguments);
var StandardGrid = declare([Grid, Selection, Keyboard, DijitRegistry]);
this.store = new (declare([Trackable, Memory]))({
data : this.data,
idProperty : "isbn"
});
this.columns = {
bookTitle : "Title",
first : "First Name",
last : "Last Name",
releaseDate : "Release Date"
};
this.grid = new StandardGrid({
collection : this.store,
columns : this.columns,
cellNavigation : false,
noDataMessage : "No results.",
loadingMessage : "Loading Data...",
}, this.gridNode);
}
startup: function() {
if (this._started) return;
this.inherited(arguments);
if (this.grid) {
this.grid.startup();
}
}
});
});
GridWidget.html
<div class="${baseClass}">
<div class="${baseClass}Grid"data-dojo-attach-point="gridNode"></div>
</div>
testGridWidget.html
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test: Dgrid 0.4</title>
<link rel="stylesheet" href="style.css" media="screen">
<link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css" media="screen">
<script>
//var startTime = new Date();
var CONTEXT_ROOT = 'DtossApp';
var djConfig = (function(){
var base = location.href.split("/");
base.pop();
base = base.join("/");
return {
parseOnLoad: true,
isDebug: true,
packages: [{
name: CONTEXT_ROOT,
location: base + "/widget"
}]
};
})();
</script>
</head>
<body class="claro">
<script>
function showGrid() {
require([
CONTEXT_ROOT + '/GridWidget',
'dojo/dom-construct',
'dojo/dom',
'dijit/layout/ContentPane',
], function (GridWidget, domConstruct, dom, ContentPane) {
var testWidget = new GridWidget({ data: createData()});
var cp = new ContentPane({
title : "Book List",
content : testWidget});
var ref = dom.byId('grid');
domConstruct.place(cp.domNode, ref);
testWidget.startup();
//Copied from dgrid laboratory sample..
function createData () {
var data = [];
var column;
var i;
for (i = 0; i < 50; i++) {
data.push({});
for (column in { first: 1, last: 1, bookTitle: 1, releaseDate: 1 }) {
data[i].isbn = i;
data[i][column] = column + '_' + (i + 1);
}
}
return data;
}
});
}
</script>
<h1>Test: Dgrid 0.4</h1>
<div id="buttonContainer">
<button class="action" onClick="showGrid1()">Show Grid</button>
</div>
<div id="grid"></div>
<!-- load dojo and provide config via data attribute -->
<script src="dojo/dojo/dojo.js"></script>
</body>
</html>
GridWidget.css
.GridWidgetGrid {
height: 300px;
width: 80%;
}

Dgrid tutorial shows the following note:
When using the basic Grid module, the grid will be empty until you call renderArray. The more advanced store-based implementations like OnDemandGrid will populate themselves from the store automatically.
I changed my Grid to OnDemandGrid which picks data from store automatically.
Also calling renderArray in startup method populates data for Grid.

Related

why addEvent from Fullcalendar does not work

Hi I am following the https://fullcalendar.io/ v4 to build my js calendar. I try to crate a new event by clicking on the calendar then call the function addEvent. where and how can I call the function addEvent can you put an example please ? I have the same question about remove an event. here is what I did, for each click I addd an event, just to see if it works. It does not work.
var event1 = [
{
title: 'MyEvent',
start: '2020-03-03T13:00:00',
end:'2020-03-03T14:00:00'
},
]
var calendar = new FullCalendar.Calendar(calendarEl, {
eventClick: function (info) {
calendar.addEvent( event1)
},
plugins: ["interaction", "timeGrid"],
header: {
left: "prev,next today",
center: "title",
right: "dayGridMonth,timeGridWeek,timeGridDay,listMonth",
},
defaultDate: currentDate,
navLinks: true,
businessHours: {
startTime: "08:00",
endTime: "18:00",
},
editable: true,
weekends: false,
allDaySlot: false,
locale: "en",
events:
[
{
title: 'MyEvent',
start: '2020-03-03T13:00:00',
end:'2020-03-03T14:00:00'
},
]
});
calendar.render();
I looked at the function addEvent from main.js, it looks like id did nothing , tuple got nul and the function (addEvent) returns nul as well !
Calendar.prototype.addEvent = function (eventInput, sourceInput) {
if (eventInput instanceof EventApi) {
var def = eventInput._def;
var instance = eventInput._instance;
// not already present? don't want to add an old snapshot
if (!this.state.eventStore.defs[def.defId]) {
this.dispatch({
type: 'ADD_EVENTS',
eventStore: eventTupleToStore({ def: def, instance: instance }) // TODO: better util for two args?
});
}
return eventInput;
}
var sourceId;
if (sourceInput instanceof EventSourceApi) {
sourceId = sourceInput.internalEventSource.sourceId;
}
else if (sourceInput != null) {
var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
if (!sourceApi) {
console.warn('Could not find an event source with ID "' + sourceInput + '"'); // TODO: test
return null;
}
else {
sourceId = sourceApi.internalEventSource.sourceId;
}
}
var tuple = parseEvent(eventInput, sourceId, this);
if (tuple) {
this.dispatch({
type: 'ADD_EVENTS',
eventStore: eventTupleToStore(tuple)
});
return new EventApi(this, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
}
return null;
};
Do you have any example on how to use addEvent function
Your problem here is that event1 is an array, not an object. The addEvent function expects a single object as input, not a list / array.
Change it to a plain object:
var event1 =
{
title: 'MyEvent',
start: '2020-03-03T13:00:00',
end:'2020-03-03T14:00:00'
}
(without the [ and ] which wrap the object inside an array) and your original code should work fine.
Well, I took the example from the fullcalendar site, and it works:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>
Add an event dynamically - Demos | FullCalendar
</title>
<link href='/assets/demo-to-codepen.css' rel='stylesheet' />
<style>
html, body {
margin: 0;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 900px;
margin: 40px auto;
}
</style>
<link href='https://unpkg.com/#fullcalendar/core#4.4.0/main.min.css' rel='stylesheet' />
<link href='https://unpkg.com/#fullcalendar/daygrid#4.4.0/main.min.css' rel='stylesheet' />
<script src='/assets/demo-to-codepen.js'></script>
<script src='https://unpkg.com/#fullcalendar/core#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/daygrid#4.4.0/main.min.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'dayGrid' ],
defaultView: 'dayGridMonth',
header: {
center: 'addEventButton'
},
customButtons: {
addEventButton: {
text: 'add event...',
click: function() {
var dateStr = prompt('Enter a date in YYYY-MM-DD format');
var date = new Date(dateStr + 'T00:00:00'); // will be in local time
if (!isNaN(date.valueOf())) { // valid?
calendar.addEvent({
title: 'dynamic event',
start: date,
allDay: true
});
alert('Great. Now, update your database...');
} else {
alert('Invalid date.');
}
}
}
}
});
calendar.render();
});
</script>
</head>
<body>
<div class='demo-topbar'>
<button data-codepen class='codepen-button'>Edit in CodePen</button>
Click the "add event..." button
</div>
<div id='calendar'></div>
</body>
</html>

How to Send Data to KendoWindow Close Event

I'm trying to open a Kendo UI kendoWindow from within an MVC View. I also use a Partial View as the content of the kendoWindow. Moreover, I use the Kendo UI MVVM pattern to bind my elements.
First let me to show you my main View and my pop-up Partial View (kendoWindow).
The important part of my main View (Parent) is as follows:
#{
ViewBag.Title = "My Main View";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="~/Scripts/ViewModel/main.js"></script>
<script src="~/Scripts/InitView/main.js"></script>
<script type="text/javascript">
var viewModel;
$(function () {
viewModel = initVm({
GetPartialContent_Url: '#Url.Action("GetPartialContent")'
});
initView(viewModel);
kendo.bind($("#container"), viewModel);
viewModel.Onread();
});
</script>
<div id="container">
<div id="Window-box"></div>
// Some other elements like the button which opens the kendoWindow are defined here.
</div>
My initVm is as follows:
function initVm(arg) {
var vm = kendo.observable({
onOpenKendoWindow: function () {
$("#Window-box").kendoWindow({
iframe: true,
content: arg.GetPartialContent_Url,
title: 'Some Title',
width: 500,
height: 'auto',
close: function (e) {
//Is it possible to get some data from kendoWindow (Partial View) here?
}
});
var dialog = $("#Window-box").data("kendoWindow");
dialog.maximize();
}
});
return vm;
}
Until now, I showed you the important parts of my main View. Now I want to show you the important parts of my kendoWindow (Partial View).
My Partial View which is used as the content of the kendoWindow is as follows:
#{
Layout = "~/Views/Shared/_PartialLayout.cshtml";
}
<script src="~/Scripts/ViewModel/partial.js"></script>
<script src="~/Scripts/InitView/partial.js"></script>
<script type="text/javascript">
var partialVM;
$(function () {
partialVM = initPartialVm({
GetTransactions_Url: '#Url.Action("GetTransactions", "Account")'
});
initPartialView(partialVM);
kendo.bind($("#container"), partialVM);
});
</script>
<div id="container">
<div id="gridTransactions"></div>
</div>
And my initPartialVm is as follows:
function initPartialVm(arg) {
var vm = kendo.observable({
onSelectTransaction: function () {
// KendoWindow should be closed here and passing some data from here to main View (close event of kendowWindow);
}
});
return vm;
}
Note: The 'gridTransactions' is a Kendo UI GridView (inside of kendoWindow - Partial View). Each rows of this grid has a select button and the 'onSelectTransaction' function is fired when each of these select buttons is clicked.
And finally, the main question is that, how can I close the kendowWindow by clicking each select button of the GridView and pass some data to the close event of the kendowWindow?
Yes it is possible. I found it much easier and a bit cleaner to wrap all the dialog functionality up into a dialog controller and extend it a bit in javascript.
Once the .js part is done it makes for a cleaner use. If you don't prefer to do this then look for the findDialog function below (it shows how get a handle to a dialog and call the close method on it).
As far as sending data on close, It would be easy to add a callback in the dialog to be called when the dialog is closed, supplied on invocation, then add a property in the widget to set the custom data to pass through in the dialogs close() back to the consumers event handler.
Also, please note I am no javascript expert, it took me longer than I would like to admit to work the bugs out of this but it has held up solidly for about 6 years. Feel free to offer suggestions.
In Bundle Config:
bundles.Add(new ScriptBundle("~/bundles/myCustom").Include(
...
"~/Scripts/MyCustom/MyCustomDialogs.js",
...
));
Where you register scripts:
#Scripts.Render("~/bundles/MyCustom")
In your index view or parent view :
<div id="_applicationDialogs"></div>
<div id="_mainAppContentLoadsHere"></div>
var _mainDialogController;
$(document).ready(function () {
...
_mainDialogController = $("#_applicationDialogs").kendoMyCustomDialogController().data("kendoMyCustomDialogController");
...
}
Where you want to invoke the dialog: SomePartial
function lnkDetailsOnClick(someID) {
_mainDialogController.createDialog({
dialogId: "frmUserDetail_" + someID,
modal: false,
title:"Daily Details",
pin: true,
height: 575,
width: 1025,
actions: ["Refresh", "Maximize", "Minimize", "Pin", "Close"],
url: '#Url.Action("SomePartialView", "SomeController")',
data:{
someID: someID,
dialogName:'frmUserDetail_'+ someID //NOTE : This will come back in the invoked partial as Model.DialogName so it can be dismissed with ease.
}
});
}
Dismissing the Dialog Inside of SomePartial :
#model MyModelThatHasTheDialogHandle
function btnClose_Click() {
var dialog = _mainDialogController.findDialog('#Model.DialogName');
dialog.close();
}
Now for the long .js file :
(function ($) {
var kendo = window.kendo,
ui = kendo.ui,
Widget = ui.Widget;
var MyCustomDialogController = Widget.extend({
init: function (element, options) {
var that = this;
Widget.fn.init.call(this, element, options);
that._create();
},
onResize: function () { },
options: {
modal: true,
dialogId: "dlgController1",
url: "",
data: null,
pin: false,
width: 300,
height: 300,
actions:["Close"],
title: "Information",
disableMaximize:false,
name: "MyCustomDialogController",
autosize: false,
onDialogClosed: null,
hideOnClose: false
},
_create: function () {
var that = this;
},
createDialog: function (options) {
var that = this;
var wrapperName = options.dialogId + "_wrapper";
that.element.append("<div id='" + wrapperName + "'></div>");
var wrapperElement = that.element.find("#" + wrapperName);
wrapperElement.kendo_MyCustomDialog(options);
},
findDialog: function (dialogId) {
that = this;
var wrapperName = dialogId+"_wrapper";
var dialog = $("#" + wrapperName);
//var dialog = wrapper.find("#" + dialogId);
return dialog.data("kendo_MyCustomDialog");
},
forceCloseAllDialogs: function ()
{
that = this;
$('.MyCustom-window').each(function () {
$(this).data("kendoWindow").close();
});
},
isModalWindowActive: function ()
{
that = this;
return $('.MyCustom-window-modal').length > 0;
},
currentModalWindow: function () {
that = this;
return that.findDialog($('.MyCustom-window-modal')[0].id);
}
});
ui.plugin(MyCustomDialogController);
})(jQuery);
(function ($) {
var kendo = window.kendo,
ui = kendo.ui,
Widget = ui.Widget;
var _MyCustomDialog = Widget.extend({
init: function (element, options) {
var that = this;
Widget.fn.init.call(this, element, options);
that._create();
},
onResize: function () { },
options: {
modal: true,
dialogId: "frmMain",
url: "",
data: null,
pin: false,
width: 300,
height: 300,
actions: ["Close"],
title: "Information",
name: "_MyCustomDialog",
disableMaximize:false,
autosize: false,
onDialogClosed: null,
hideOnClose:false
},
_create: function () {
var that = this;
that.isModalWindowActive = true;
that.modifiedData = false;
that.frmElement = $("#" + that.options.dialogId).data("kendoWindow");
if (that.frmElement == null) {
var template ;
if(that.options.modal)
template = kendo.template(that._templates.divModalFormWrapper);
else
template = kendo.template(that._templates.divFormWrapper);
that.wrapper = $(template(that.options));
that.element.append(that.wrapper);
if (that.options.autosize)
{
that.options.height =null;
that.options.width = null;
}
that.frmElement = that.wrapper.kendoWindow({
title: "Loading...",
modal: that.options.modal,
visible: that.options.autosize,
draggable: true,
resizeable:!that.options.disableMaximize,
width: that.options.width,
height: that.options.height,
resizeable: true,
pinned:that.options.pin,
resize: function () {
that.onResize();
},
content: {
url: that.options.url,
data: that.options.data,
type: "POST",
datatype: "json",
traditional: true
},
refresh: function () {
that.frmElement.title(that.options.title);
if (that.options.autosize) {
that.frmElement.center();
}
},
actions: that.options.actions,
close: function (e) {
that.IsModalWindowActive = false;
if (that.options.hideOnClose == false) {
if (that.frmElement != null)
that.frmElement.destroy();
this.destroy();
that.wrapper.remove("#" + that.options.dialogId);
that.wrapper.empty();
}
if (that.options.onDialogClosed) {
that.options.onDialogClosed(that.modifiedData);
}
}
}).data("kendoWindow");
}
if (that.options.autosize)
that.frmElement.center().open();
else if (that.options.hideOnClose == true)
that.frmElement.open();
else
that.frmElement.center().open();
if (that.options.pin)
that.frmElement.pin();
},
setModifiedFlag:function(modified)
{
var that = this;
that.modifiedData = modified;
},
close: function () {
var that = this;
that.frmElement.close();
},
show: function () {
var that = this;
that.wrapper.show();
that.frmElement.open();
},
setTitle: function (title) {
var that = this;
that.frmElement.title(title);
},
height: function () {
var that = this;
var wtfHeight = that.frmElement.options.height;
if (isNaN(wtfHeight)) {
if (wtfHeight.indexOf("px") >= 0)
wtfHeight = wtfHeight.replace("px", "");
}
return wtfHeight;
},
_templates: {
divModalFormWrapper: "<div id='#=dialogId#' class='MyCustom-window MyCustom-window-modal'></div>",
divFormWrapper: "<div id='#=dialogId#' class='MyCustom-window'></div>"
}
});
// add the widget to the ui namespace so it's available
ui.plugin(_MyCustomDialog);
})(jQuery);

Dynamic template with dynamic scope compilation

I have a very specific need that cannot realy be solved with standard data-binding.
I've got a leaflet map that I want to bind with a vue view-model.
I succeeded to display geojson features kinda bounds to my view, but I'm struggling at displaying a popup bound with vue.js
The main question is : "How to open a popup (possibly multiple popups at the same time) and bind it to a view property "
For now I've come to a working solution, but this is aweful :
map.html
<div id="view-wrapper">
<div id="map-container"></div>
<div v-for="statement in statements" id="map-statement-popup-template-${statement.id}" style="display: none">
<map-statement-popup v-bind:statement="statement"></map-statement-popup>
</div>
</div>
<!-- base template for statement map popup -->
<script type="text/template" id="map-statement-popup-template">
{{ statement.name }}
</script>
map.js
$(document).ready(function() {
var map = new L.Map('map-container');
map.setView(new L.LatLng(GLOBALS.MAP.STARTCOORDINATES.lng, GLOBALS.MAP.STARTCOORDINATES.lat), GLOBALS.MAP.STARTZOOM);
var osm = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
osm.addTo(map);
//Initialize map dynamic layers
var mapLayers = {};
//View-model data-bindings
var vm = new Vue({
el: '#view-wrapper',
data: {
statements: []
},
methods: {
getStatements: function() {
return $.get('api/statements');
},
updateStatements: function() {
var that = this;
return that.getStatements().then(
function(res) {
that.statements = res.data;
}
);
},
refreshStatements: function() {
mapLayers.statements.layer.clearLayers();
if(this.statements && this.statements.length){
var geoJsonStatements = geoJsonFromStatements(this.statements);
mapLayers.statements.layer.addData(geoJsonStatements);
}
},
handleStatementFeature: function(feature, layer) {
var popupTemplateEl = $('#map-statement-popup-template-' + feature.properties.statement.id);
layer.bindPopup(popupTemplateEl.html());
var statementIndex = _.findIndex(this.statements, {statement:{id: feature.properties.statement.id}});
if(feature.geometry.type === 'LineString') {
this.statements[statementIndex].layer = {
id: L.stamp(layer)
};
}
},
openStatementPopup: function(statement) {
if(statement.layer) {
var featureLayer = mapLayers.statements.layer.getLayer(statement.layer.id);
featureLayer.openPopup();
}
}
},
created: function() {
var that = this;
//Set dynamic map layers
var statementsLayer = L.geoJson(null, {
onEachFeature: this.handleStatementFeature
});
mapLayers.statements = {
layer: statementsLayer
};
map.addLayer(mapLayers.statements.layer);
this.updateStatements().then(this.refreshStatements);
this.$watch('statements', this.refreshStatements);
},
components: {
'map-statement-popup': {
template: '#map-statement-popup-template',
props: {
statement: null
}
}
}
});
function geoJsonFromStatementsLocations(statements){
var geoJson = {
type: "FeatureCollection",
features: _.map(statements, function(statement) {
return {
type: "Feature",
geometry: {
type: "LineString",
coordinates: statement.coordinates
},
properties: {
statement: statement
}
};
});
};
return geoJson;
}
});
This seems pretty aweful to me, because I have to loop over statements with a v-for, render a div for my custom element for every statement, hide it, then use it in the popup, grabbing it with a dynamic id technique.
I would like to do something like this :
map.html
<div id="view-wrapper">
<div id="map-container"></div>
</div>
<!-- base template for statement map popup -->
<script type="text/template" id="map-statement-popup-template">
{{ statement.name }}
</script>
map.js
$(document).ready(function() {
[...]
//View-model data-bindings
var vm = new Vue({
el: '#view-wrapper',
data: {
statements: []
},
methods: {
handleStatementFeature: function(feature, layer) {
var popupTemplateEl = $('<map-statement-popup />');
var scope = { statement: feature.properties.statement };
var compiledElement = this.COMPILE?(popupTemplateEl[0], scope);
layer.bindPopup(compiledElement);
}
},
components: {
'map-statement-popup': {
template: '#map-statement-popup-template',
props: {
statement: null
}
}
}
});
function geoJsonFromStatementsLocations(statements){
var geoJson = {
type: "FeatureCollection",
features: _.map(statements, function(statement) {
return {
type: "Feature",
geometry: {
type: "LineString",
coordinates: statement.coordinates
},
properties: {
statement: statement
}
};
});
};
return geoJson;
}
});
... but I couldn't find a function to "COMPILE?" based on a defined scope. Basically I want to :
Create a custom element instance
Pass it a scope
Compile it
EDIT : Actually, I could find $compile function. But it's often used to compile appended child to html. I don't want to append it THEN compile it. I'd like to compile it then let leaflet append it for me.
Would this work for you? Instead of using a component, you create a new element to be passed to bindPopup, and you new Vue on that element, with your data set appropriately.
new Vue({
el: 'body',
data: {
popups: [1, 2, 3],
message: "I'm Dad",
statements: []
},
methods: {
handleFeature: function(id) {
const newDiv = document.createElement('div');
const theStatement = {
name: 'Some name for ' + id
};
newDiv.innerHTML = document.getElementById('map-statement-popup-template').innerHTML;
new Vue({
el: newDiv,
data: {
statement: theStatement
},
parent: this
});
// Mock call to layer.bindPopup
const layerEl = document.getElementById(id);
this.bindPopup(layerEl, newDiv);
},
bindPopup: function(layerEl, el) {
layerEl.appendChild(el);
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div class="leaflet-zone">
<div v-for="popup in [1,2,3]">
<button #click="handleFeature('p-' + popup)">Bind</button>
<div id="p-{{popup}}"></div>
</div>
</div>
<template id="map-statement-popup-template">
{{ statement.name }} {{$parent.message}}
</template>
I think you could do the same thing with $compile, but $compile is poorly (really un-) documented and intended for internal use. It is useful for bringing a new DOM element under control of the current Vue in the current scope, but you had a new scope as well as a new DOM element, and as you noted, that binding is exactly what Vue is intended to do.
You can establish a parent chain by specifying the parent option as I have updated my snippet to do.

dojo data grid in custom widget is not rendering

hi all i have created a custom widget which in the future will contain more than a data grid however i have had considerable difficulty trying to get the data grid to render.
I have no errors and all the following seems to be being called as i suspect; perhaps it is an asynch issue?
Any help on this would be great, my code as followed.
AssetGridWidget.js
define([
"dojo/_base/declare",
"dojo/_base/fx",
"dojo/_base/lang",
"dojo/dom-style",
"dojo/mouse",
"dojo/on",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dojo/text!./templates/AssetGridWidget.html",
"dojox/grid/DataGrid",
"dojo/data/ItemFileWriteStore",
"dojo/store/Memory",
"dojo/data/ObjectStore"]
, function(declare, baseFx, lang, domStyle, mouse, on, _WidgetBase, _TemplatedMixin, template, DataGrid,ifilereadstore, Memory, ObjectStore){
return declare([_WidgetBase, _TemplatedMixin], {
widgetInTemplate : true,
templateString: template,
postCreate: function(){
this.layout =
[
{ name: 'Name', field: 'name', width: '100px' },
{ name: 'Color', field: 'color', width: '100px' }
];
this.data = {
data :
{items :[
{ name : 'John Doe', color: 'green' },
{ name : 'Jane Doe', color: 'red' }
],
label:'name',
identifier:'color'
}
};
this._employeeStore = new Memory({data: this.data, idProperty: "name"});
this._dataStore = ObjectStore({objectStore: this._employeeStore});
this.grid = new DataGrid
(
{
noDataMessage: "Hazza",
store: this._dataStore,
query: { id: "*" },
autoRender : true,
structure: this.layout
},
"grid"
);
this.inherited(arguments);
},
startup: function() {
this.grid.startup();
}
});
});
my template is as follows:
AssetGrididget.html
<div>
<div data-dojo-attach-point="grid" style="width: 800px; height: 800px;"></div>
</div>
finally the page i am calling it from
Index.html
<head>
<script type="text/javascript" src="js/dojo/dojo.js"></script>
</head>
<body>
<div id="gridContainer" style="width: 300px; height: 300px;"></div>
<script>
require(["dojo/request", "dojo/dom", "dojo/_base/array", "tartarus/widget/AssetGridWidget", "dojo/domReady!"],
function(request, dom, arrayUtil, AssetGridWidget){
var gridly = new AssetGridWidget();
gridly.placeAt("gridContainer");
gridly.startup();
});
</script>
</body>
I have been smacking my head against a brick wall for hours on this so any help is greatly appreciated!
You are passing "grid" as the second argument to the DataGrid constructor. This will attempt to find a DOM node in the document with the ID grid and replace that with the grid.
However, based on your template, it looks like what you're actually intending to do is to replace your grid attach point with the grid instead. Instead of "grid", your second argument to the constructor should be this.grid.
(I might also suggest naming the attach point gridNode instead to distinguish it, since you are immediately assigning the actual grid instance to this.grid thereafter.)

How to tell what has been destroyed by the destroy command in a kendo UI grid?

I'm using Kendo UI 2013.2.716 and JQuery 2.0.3 and I am placing a grid on my page, and my question is:
Does anyone know how to tell what has been destroyed by the destroy command from the grid?
For example:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<link href="kendo.common.min.css" rel="stylesheet" />
<link href="kendo.default.min.css" rel="stylesheet" />
<script type="text/javascript" src="jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<script type="text/javascript">
$(document).ready(function() {
var products = [];
for(var i = 1; i <= 40; i++) {
products.push({
ProductId: i,
ProductName: "Product " + i
});
}
$("#grid").kendoGrid({
dataSource: {
data: products,
schema: {
model: {
id: "ProductId",
fields: {
ProductName: { type: "string" },
}
}
},
requestEnd: function (e) {
if (e.type === "destroy") {
alert("OK, so something got destroyed, but what??");
}
}
},
editable: "inline",
columns: [
"ProductName",
{ command: "destroy", title: " ", width: "100px" }
]
});
});
</script>
</body>
</html>
I found the requestEnd callback in the documentation but I am totally flummoxed as to know where the item that was destroyed would be. I just need the ID of the item really so that I can update other parts of my page appropriately.
I am wondering if I need to capture it somehow beforehand.
You need to configure the transport object on your datasource. In your current configuration, does anything really get destroyed? Sure, the item may disappear from your grid, but I wonder if it's still there in the datasource. Maybe that's what you intended.
http://docs.kendoui.com/api/framework/datasource#configuration-transport.destroy
If you're just looking for a way to get at the data that's being destroyed, hook into the parameterMap() function of the transport object. In there you can manipulate the object being deleted before the operation is executed.
http://docs.kendoui.com/api/framework/datasource#configuration-transport.parameterMap
Thanks to #Brett for pointing out the destroy property on the transport. This code does the trick - allowing me to capture what was being destroyed (see the transport.destroy part):
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<link href="kendo.common.min.css" rel="stylesheet" />
<link href="kendo.default.min.css" rel="stylesheet" />
<script type="text/javascript" src="jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<script type="text/javascript">
$(document).ready(function() {
$("#grid").kendoGrid({
dataSource: {
schema: {
model: {
id: "ProductId",
fields: {
ProductName: { type: "string" },
}
}
},
transport: {
read: function (options) {
var products = [];
for(var i = 1; i <= 40; i++) {
products.push({
ProductId: i,
ProductName: "Product " + i
});
}
options.success(products);
},
destroy: function (options) {
var data = $("#grid")
.data("kendoGrid").dataSource.data();
var products = [];
for(var i = 0; i < data.length; i++) {
if (data[i].ProductId !== options.data.ProductId) {
products.push(data[i])
}
}
options.success(products);
alert("Woo hoo - the product with the ID: "
+ options.data.ProductId + " was destroyed!");
}
}
},
editable: "inline",
columns: [
"ProductName",
{ command: "destroy", title: " ", width: "100px" }
]
});
});
</script>
</body>
</html>

Categories