Hi,
I have a TreeView for a filter on a dashboard, and it's not processing the click on the checkbox the second time. I've attached a screen shot with more details.
I'm not sure what I have wrong.
Creating the TreeView:
How it's used in my program, including several variations on binding.
I have a TreeView for a filter on a dashboard, and it's not processing the click on the checkbox the second time. I've attached a screen shot with more details.
I'm not sure what I have wrong.
Creating the TreeView:
/* Topics illustrated in this file:
* How to define a custom widget
* How to configure options from base
* How to define and access custom options
* How to capture scope
* How to manipulate the DOM of "this"
* How to expose custom methods
* How to expose an event handler delegate
*/
define([
'jquery'
,
'underscore'
,
'utils/helpers'
,
'text!views/schoolFilterItem.html'
,
'kendoui/kendo.treeview.min'
,
],
function
($, _, Helpers, schoolFilterItemTemplate) {
var
schoolData;
// This defines a Kendo widget object
var
TreeView = kendo.ui.TreeView.extend({
init:
function
(element, options) {
// Assigning this to another variable name captures the context of init, which is "this TreeView"
var
me =
this
;
options.dataSource = {
transport: {
read:
function
(options) {
$.getJSON(Helpers.toServicesUrl(
"/GetfltSchoolByDistrict"
),
{
// If you tried to use "this" in here, it would refer to the dataSource instead of the TreeView
userName: me.options.userName,
districtId: me.options.districtId,
schoolCodes: me.options.schoolCodes
},
function
(data) {
options.success([]);
schoolData = data.GetfltSchoolByDistrictResult.RootResults;
schoolData = [
{
text:
"Schools"
,
expanded:
false
,
items: _(schoolData)
.chain()
.groupBy(
"SchoolTypeName"
)
.map(
function
(groupItems, groupKey) {
return
{
SchoolTypeName: groupKey,
items: groupItems,
expanded:
false
}
})
.value()
}
];
me.dataSource.data(schoolData);
});
}
},
schema: {
model: {
children:
"items"
}
}
};
options.dataBound =
function
(e) {
me.element.find(
"input:checkbox:first"
).prop(
"disabled"
,
true
);
me.element.find(
"input:checkbox"
).on(
"change"
,
function
(e) {
var
parentItems = $(e.target).parents(
".k-item"
);
var
node = parentItems.eq(0);
var
parentNode = parentItems.eq(1);
// Toggle children to match parent
node.find(
"input:checkbox"
).prop(
"checked"
, e.target.checked);
// Update parent's state
var
parentCheckBox = parentNode.find(
"input:checkbox:first"
);
if
(!parentCheckBox.prop(
"disabled"
)) {
var
hasChecked = parentNode.find(
".k-group input:checked"
).length > 0;
var
hasUnchecked = parentNode.find(
".k-group input:not(:checked)"
).length > 0;
parentCheckBox.prop(
"checked"
, hasChecked);
parentCheckBox.prop(
"indeterminate"
, hasChecked && hasUnchecked);
}
// The rest is unchecking other SchoolTypes if a different SchoolType is checked. If "this" is unchecked, no further action required.
if
(!e.target.checked)
return
;
var
dataItem = me.dataItem(node);
if
(!dataItem.SchoolTypeName) {
e.target.checked =
false
;
return
;
}
me.element.find(
"input:checked"
).each(
function
() {
var
eachDataItem = me.dataItem($(
this
).closest(
".k-item"
))
if
(eachDataItem.SchoolTypeName !== dataItem.SchoolTypeName) {
this
.checked =
false
;
this
.indeterminate =
false
;
//lah testing adding something here.
// me.schoolTypeChanged(e);
me.onSchoolChange(e);
}
//gmo when school names don't match
if
(eachDataItem.SchoolName !== dataItem.SchoolName) {
this
.checked =
false
;
me.onSchoolChange(e);
}
});
});
}
kendo.ui.TreeView.fn.init.call(
this
, element, options);
},
options: {
// This is what determines the name of the custom method, e.g. .kendoSchoolFilterTreeView
name:
"TreeViewSchoolFilterSingle"
,
// Declare new options with default values. Options must be declared here in order to be accepted and passed through to init().
userName:
""
,
districtId: 0,
schoolCodes:
function
() {
return
""
},
// Anything else you pass in options will get passed to the base widget
dataTextField: [
"text"
,
"SchoolTypeName"
,
"SchoolName"
],
checkboxes:
true
},
getSelectedSchoolType:
function
() {
var
me =
this
;
return
_(
this
.element.find(
"input:checked"
).closest(
".k-item"
))
.chain()
// .map(function (item) { return ktvSchoolFilter.dataItem(item).SchoolType; })
.map(
function
(item) {
return
me.dataItem(item).SchoolType; })
.filter(
function
(item) {
return
item; })
.value()[0];
},
// This is how to get the selected school from the radio group
getSelectedSchoolCodes:
function
() {
var
me =
this
;
return
_(
this
.element.find(
"input:checked"
).closest(
".k-item"
))
.chain()
// .map(function (item) { return ktvSchoolFilter.dataItem(item).SchoolCode; })
.map(
function
(item) {
return
me.dataItem(item).SchoolCode; })
.filter(
function
(item) {
return
item; })
.value()
.join(
","
);
},
onSchoolChange:
function
(e) {
return
;
},
schoolTypeChanged:
function
(e) {
return
;
}
});
// This is what registers the custom widget and adds the kendo* method to the jQuery object
kendo.ui.plugin(TreeView);
});
How it's used in my program, including several variations on binding.
ktvSchoolFilter = $(
"#schoolFilterTree"
).kendoTreeViewSchoolFilterSingle({
userName: WSIPCContext.UserName,
districtId: WSIPCContext.DistrictId,
schoolCodes: WSIPCContext.SchoolCodes,
onSchoolChange: schoolCodeChanged,
change: schoolCodeChanged,
schoolTypeChanged: schoolCodeChanged,
checkbox: {
onClick: schoolCodeChanged
}
}).data(
"kendoTreeViewSchoolFilterSingle"
);
//This code allows the grade level and risk categories to change when a checkbox
//is selected, not just the label.
ktvSchoolFilter.dataSource.bind(
"change"
, schoolCodeChanged);
ktvSchoolFilter.dataSource.bind(
"select"
, schoolCodeChanged);
ktvSchoolFilter.dataSource.bind(
"selecting"
, schoolCodeChanged);
ktvSchoolFilter.dataSource.bind(
"navigate"
, schoolCodeChanged);
ktvSchoolFilter.bind(
"change"
, schoolCodeChanged);
ktvSchoolFilter.bind(
"select"
, schoolCodeChanged);
ktvSchoolFilter.bind(
"selecting"
, schoolCodeChanged);
ktvSchoolFilter.bind(
"navigate"
, schoolCodeChanged