Inline HTML data-role <> script jquery: Kendo Widget Initialization - javascript

Using Kendo there are two ways to initialize a Kendo Widget:
one:
<span id=”UniqueID” /></span>
<script>
$(“#UniqueID”).KendoWidget();
</script>
two:
<span id=”UniqueID” data-role=”Widget” /></span>
<script>
Kendo.init($(“#UniqueID”));
</script>
Does anybody know the pro's and con's of there two methods?
I want to make sure I am aware of the implications of any specific direction.
and if it's more of less equal, which is the most commonly found mechanism, dev's follow.
Kind Regards,
Flippie

I use both. It depends on the complexity of the configuration for that widget, and in some cases, it's not possible (or at least very difficult) to initialize a widget within the HTML due to data context issues; thus, it's easier to initialize it in code. Other times, it's simply personal preference.
For all widgets, I'll start by declaring them in the HTML, like so:
<div id="cases"
data-role="grid"
data-bind="source: cases"
data-pageable="{ refresh: true }"
data-sortable="{ mode: 'multiple' }"
data-filterable="{
extra: false,
operators: { string: { contains: 'Contains', eq: 'Is equal to' } }
}"
data-columns="[
{ title: '', template: kendo.template($('#editColumnTemplate').html()), sortable: false, filterable: false, width: 42 },
{ field: 'number', title: 'Number', width: 160 },
{ field: 'subject', title: 'Subject' },
{ field: 'contact', title: 'POC', width: 200 },
{ field: 'referral', title: 'Referred By', width: 100 },
{ field: 'opened', title: 'Opened', format: '{0:d}', filterable: false, width: 120 },
{ field: 'closed', title: 'Closed', format: '{0:d}', filterable: false, width: 120 }
]">
</div>
I prefer doing it this way because all of the widget's configuration is declared inline with it's location in the HTML. It's similar in the way that you have to bind data to your view using MVVM frameworks like Kendo and Knockout, so, I like to be consistent. For me, it's easier to maintain because everything is defined in one place and it looks clean. Now, if I run into data context problems where I can't bind a particular observable or data element, say within this grid's columns definition, then I move it all to code.
Either way is more or less equal. I couldn't tell you which is more common. I imagine most developers do it the same way I do - mixing both methods.

Related

Extjs4 fieldset.show() and fieldset.hide() is not a function issue

I have a problem with fieldsets show and hide functions.
In my app at the left side I have a combobox with change listener. At the right side I have several different textfields which are showing and hiding according as chosen value in combobox.
Every hide and show functions are working with fieldsets, but if I can't to show/hide fieldset. Fieldset reference is visible, I can list this component with console.log() function.
Here's a piece of my code:
var rigthPanelLeftContainer = {
flex: 1,
minWidth: 200,
defaults: {
xtype: 'textfield',
minWidth: 180,
anchor: '100%'
},
items: [
//some working textfields here
{
xtype: 'fieldset',
labelWidth: 160,
anchor: '100%',
height: 40,
itemId: 'remarkId',
title: 'title'],
hidden : !ifHideIt, //boolean
items: [{
xtype: 'text',
height: 25,
text: 'sometext']
}]
}
]};
var comboBoxConnectors = {
xtype: 'combobox',
fieldLabel: Ext.translations.map['field.label.common'],
store: Ext.state.Manager.get('conTypes'),
editable: false,
queryMode: 'local',
name: 'conType',
itemId: 'conTypeField',
value: connObj === null ? conTypes[0] : connObj.type,
labelWidth: 160,
anchor: '100%',
listeners: {
change: function(obj, newValue, oldValue) {
//many hide/show working on textfield functions
var remarkId = me.query('#remarkId');
console.log(remarkId); //returns my fieldset element
remarkId.hide(); //returns remarkId.hide is not a function
}
}
}
I really need your help guys, whats wrong with this?
In your code, you have a comment that says that me.query( '#remarkId' ) returns your fieldset element. This is not technically correct. Assuming that me.query() is a component query, what you are actually getting in return is an array of matched components. So then, you're getting the undefined function error because, most definitely, an array does not have a hide() method. If you access the first element in the array and then call the hide() method, it should work.
However, you should probably also consider going about this a bit differently. Instead of getting an array of elements with query() (which may always be one, but not necessarily...), you could use the built in traversal methods to find the correct component. For example, assuming that the combobox and the fieldset are both children of the same form panel, you could do something like this: mycombobox.up( 'form' ).down( 'fieldset#remarkId' ). This basically instructs the code to traverse up the component hierarchy to the nearest form, then to drill down to the first descendant of the form that is a fieldset with the itemId of "remarkId". This will only ever give you a single component as a result, so you don't have to bother with accessing a component out of an array of components.

kendo ui grid batch editing, set focus

I working on a kendo ui grid. The grid is not-editable as default.
In the toolbar is a 'edit' button. When the user clicks on it, the grid should be editable in batch mode like this.
The only solution to get this work is remove and recreate the grid/datasource with new properties (editable:true etc).
This works as expected. Now I want to set the focus on the first row/cell, so that the user can see that the grid is editable now (in the example below the row becomes an input field).
Any suggestions for this?
Here is a fiddle for this.
$('.k-grid-edit').on('click', function (e) {
e.preventDefault();
// remove old grid
$('#grid').html('');
// recreate grid with edit: true and new datasource
$('#grid').kendoGrid({
dataSource: dataSourceInEdit,
editable: true,
columns: [{
field: 'TableId',
title: 'Id',
width: 50
}, {
field: 'Area',
title: 'Area'
}, {
field: 'Table',
title: 'Table',
width: 60
}, {
command: 'destroy',
title: ' ',
width: 100
}]
}).data("kendoGrid");
}); // end edit
Okay, I got it:
These 2 lines make it happen:
var grid = $("#rt_tableGrid").data("kendoGrid");
grid.editRow($("#rt_tableGrid tr:eq(1)"));
Certainly only on my local script, in the Fiddle I cant´t get it to work.
Although in the Docu is written: Requires "inline" or "popup"
Documentation here

Using Kendo Grid with knockoutjs row template make filtering impossible

I'm currently building an application using knockoutjs for the MVVM pattern, and Kendo Web for the controls.
I have somme issues with filtering/grouping the data in the kendo grid.
I need to have highly customizable rows, and so I choose to use row template according to this sample :
http://rniemeyer.github.io/knockout-kendo/web/Grid.html
I also need to have a two way binding with the grid, cause I need to add/remove/update items.
The grid :
<div data-bind="kendoGrid: {
data: LienActionIndicateurPourFicheCollection,
widget: indicateurWidget,
rowTemplate: 'indicateurRowTmpl',
useKOTemplates: true,
dataSource : {
schema: {
model: {
fields: {
Code: { type: 'string' },
Titre: { type: 'string' },
Note: { type: 'number' }
}
}
},
},
columns: [
{ title: '#', width: 30 },
{ field: 'Code', title: 'Code', width: 80 },
{ field: 'Titre', title: 'Titre', width: 150 },
{ field: 'Note', title: 'Note', width: 80 }]
}">
</div>
The row template :
<script id="indicateurRowTmpl" type="text/html">
<tr">
<td>
<button data-bind="visible: $root.isInEditMode, click: removeIndicateur"
class="common-button delete-button"></button>
</td>
<td data-bind='text: Code'></td>
<td data-bind='text: Titre'></td>
<td data-bind='text: Note'></td>
</tr>
</script>
When I'm using the grid, it works fine, expect when I use grouping/filtering : it's like the grid is using the observable objet instead of the value to perform the operations.
Example : When I'm grouping on 'Note' integer value :
To prevent that, I have replaced in columns definition "field: 'Note'" by "field: 'Note()'" : the grouping works fine now, since grid use the integer value instead of a function.
But the filtering remain impossible : the column filter menu has changed from number filter to string filter when I have make the 'Note()' change.
I suppose it's because the fields entry key 'Note' does not match the columns entry key 'Note()' anymore !
I've tried to replace 'Note' by 'Note()' in fields definition : does not work.
I've replace Note observable by a non observable variable in my item model : all is working fine, but i'm not enable to edit those values anymore, and I want to.
Thanks for your help !
EDIT : here a jsfiddle reproducting the bug : http://jsfiddle.net/camlaborde/htq45/1/
EDIT#2 here's the final solution, thanks to sroes : http://jsfiddle.net/camlaborde/htq45/7/
EDIT#3 final solution plus inline grid edition : http://jsfiddle.net/camlaborde/8aR8T/4/
It works if you create a computed which returns the items as a plain JS object:
this.items.asJS = ko.computed(function() {
return ko.toJS(this.items());
}, this);
http://jsfiddle.net/htq45/2/
The reason why putting ko.toJS(this.items) directly in the binding doesn't work is because the way kendo tracks individual options in the bindings. Knockout.js man RP Niemeyer taught me this: Dynamically enable/disable kendo datepicker with Knockout-Kendo.js
I solved this issue by using Knockout ES5. Then, when assigning my data to my model, I used knockout-mapping with a mapping object like this:
var dataMapper = {
create: function(o) {
return ko.track(o.data), o.data;
}
};
ko.mapping.fromJS(json, dataMapper, self.data);
This makes the filtering and sorting work out of the box for the knockout kendo grid.

DOM Node Count Increasing - .off() .empty()

I am using an external JS Widget library called jqWidgets mainly for their feature rich GRIDS. I am building a Single Page Application that adds and removes LOTS of grids throughout the use of the application. I am having a problem with the DOM Node Count increasing, I've managed to make a dent in the Event Listener Count, although that is slowly creeping up as well. Example:
Javascript:
$(document).ready(function () {
$("#runTest").on('click', function(){
$("#testGrid").jqxGrid({
width: 795,
selectionmode: 'singlecell',
editable: true,
sortable: true,
filterable: true,
rowsheight: 20,
height: 200,
columns: [
{text: 'Activity ID', datafield: 'activity_id', width: 150},
{text: 'Description', datafield: 'activity_description', width: 150},
{ text: 'Notes ⁄ Comments', datafield: 'activity_notes'}
]
});
});
$("#destroyGrid").on('click', function(){
$("#runTest").off('click');
$("#testGrid").jqxGrid('destroy');
$("#testDiv").remove();
});
});
HTML:
<div id='testDiv'>
<div id='testGrid'></div>
</div>
<input type="button" value="click me" id="runTest" />
<input type="button" value="destroy" id="destroyGrid" />
When click the runTest button to create the grid, my DOM Node Count goes from 318 to 880 and Event Listener Count from 8 to 132.
After I click the destroy button (and Garbage Collection occurs), the DOM Node Count goes from 880 to 645and Event Listener Count from 132 to 32.
Theoretically shouldn't the values return to the original state? Am I missing something here? I've read through tons of posts on this subject and I seem to be following the standard practices so I am tempted to think this is an issue with the jqWidget library and not my code, any help or advice is appreciated.
I've tried empty() and remove() with the same results.

get checkbox value without using Ext.getCmp

I am trying to get value of this checkbox
Ext.define('myRoot.myExtApp.myForm', {
extend: 'Ext.form.Panel',
layout: {
type: 'vbox',
align: 'stretch'
},
scope: this,
constructor: function() {
this.callParent(arguments);
this.myFieldSet = Ext.create('Ext.form.FieldSet', {
scope: this,
columnWidth: 0.5,
collapsible: false,
defaultType: 'textfield',
layout: {
type: 'hbox', align: 'stretch'
}
});
this.mySecondForm = Ext.create('myRoot.myExtApp.myForm2', {
scope: this,
listener: this,
margin: '1 3 0 0'
});
this.myCheckBox = Ext.create('Ext.form.Checkbox', {
scope: this,
//id: 'myCheckBox',
boxLabel: 'Active',
name: 'Active',
checked: true,
horizontal: true
});
this.myFieldSet.add(this.mySecondForm);
this.myFieldSet.add(this.myCheckBox);
this.add(this.myFieldSet);
}
});
As you can see I have another form
Ext.define('myRoot.myExtApp.myForm2', {
where I have a handler, that should get the value of the checkbox from "myForm"
How can I get the value of my checkbox from Form2 without using Ext.getCmp? I know I can get the value of the checkbox if I do
Ext.getCmp('myCheckBox').getValue();
but using
this.myCheckBox.getValue();
gives me undefined error.
UPDATE - with Wared suggestion I tried this inside myForm2
this.temp=Ext.create('myRoot.myExtApp.myForm'), {});
var tempV = this.temp.myCheckBox.getValue();
I was able to get the value but I get the same true value even if I uncheck the box
I assume you worry about performance loss due to excessive use of component queries. A nice trick to minimize component queries could be to define a new method inside a closure in order to cache the result of the first getCmp call. Wrapping the definition of the method inside a closure allows to avoid using global scope or a useless class property.
getMyCmp: function (cmp) {
// "cmp" does not exist outside this function
return function () {
return cmp = cmp || Ext.getCmp('#myCmp');
};
}()
One solution could be :
myRoot.myExtApp.myForm.myCheckBox.getValue();
Beware, wrong answer. See comments below for a valid solution.

Categories