Hi Stefan:
Thanks for suggesting the use of a custom .click handler. I find that it my handler is not invoked when the transfer buttons are clicked. I am adding the handler in $() ready script block. Are the list box toolbar click handlers updated by the component internals at a time other than widget initialization ? I ask because I am using the list boxes in a single page web app and perform ajax to obtain new items for a data source and then distributing the items to the connected list boxes based on a state field in the model.
An additional issue is that .click() is not part of the event stream if the keyboard is used to execute toolbar commands. Do you have any suggestions for handling those events ?
An MVC helper in cshtml is used to define a data source
@(Html.Kendo().DataSource<LabReportSpecItemViewModel>()
.Name(
"dataSource2"
)
.Custom(custom => custom
.Batch(
true
)
.PageSize(750)
.Transport(t => t
.Read(R => R @* { lot: the-lot-to-read } must be passed at .read() *@
.Action(
"Spec_Read"
,
"LabReport"
)
.ContentType(
"application/json"
)
.DataType(
"json"
)
.Type(HttpVerbs.Post)
)
.Update(U => U
.Action(
"Spec_Update"
,
"LabReport"
)
.ContentType(
"application/json"
)
.DataType(
"json"
)
.Type(HttpVerbs.Post)
)
.ParameterMap(
"ds2_parameterMap"
)
)
.Schema(s => s
.Data(
"Data"
).Total(
"Total"
).Errors(
"Errors"
)
.Model(model => model.Id(p => p.SpecificationID))
)
.Events(e => e.Change(
"ds2_change"
))
.Sort(s => { s.Add(
"Seq"
); s.Add(
"Name"
); s.Add(
"Revision"
); })
)
)
which in turn renders as this kendoui
dataSource2 =
new
kendo.data.DataSource({
"transport"
:{
"read"
:{
"url"
:
"/LabReport/Spec_Read"
,
"dataType"
:
"json"
,
"type"
:
"POST"
,
"contentType"
:
"application/json"
},
"update"
:{
"url"
:
"/LabReport/Spec_Update"
,
"dataType"
:
"json"
,
"type"
:
"POST"
,
"contentType"
:
"application/json"
},
"parameterMap"
:ds2_parameterMap},
"pageSize"
:750,
"page"
:0,
"total"
:0,
"sort"
:[{
"field"
:
"Seq"
,
"dir"
:
"asc"
},{
"field"
:
"Name"
,
"dir"
:
"asc"
},{
"field"
:
"Revision"
,
"dir"
:
"asc"
}],
"change"
:ds2_change,
"schema"
:{
"data"
:
"Data"
,
"total"
:
"Total"
,
"errors"
:
"Errors"
,
"model"
:{
"id"
:
"SpecificationID"
,
"fields"
:{
"Lot"
:{
"type"
:
"string"
},
"SpecificationID"
:{
"type"
:
"number"
},
"Name"
:{
"type"
:
"string"
},
"Revision"
:{
"type"
:
"string"
},
"Material"
:{
"type"
:
"string"
},
"LabReportSpecID"
:{
"type"
:
"number"
,
"defaultValue"
:
null
},
"Seq"
:{
"type"
:
"number"
,
"defaultValue"
:
null
}}}},
"batch"
:
true
});
A search term is entered and then the datasource is read() and the datasource change handler repopulates the data of two connected list boxes.
function
ds2_change(e) {
console.log(
"ds2_change:"
+ e.action);
if
(!e.action) {
var
data =
this
.data();
if
(!labReport_specLb1) {
labReport_specLb1 = $(
"#listbox1"
).data(
"kendoListBox"
);
}
if
(!labReport_specLb2) {
labReport_specLb2 = $(
"#listbox2"
).data(
"kendoListBox"
);
}
labReport_specLb1.dataSource.data([]);
labReport_specLb2.dataSource.data([]);
for
(
var
i = 0; i < data.length-10; i++) {
if
(data[i].Seq ==
null
) {
labReport_specLb1.add(data[i]);
}
else
{
labReport_specLb2.add(data[i]);
}
}
if
(labReport_specLb2.dataSource.data().length >= LB2_MAX_ITEM_COUNT) {
$(
'.dual-listbox1 [data-command="transferTo"]'
).css(
'visibility'
,
'hidden'
);
}
return
;
}
}
The list boxes themselves are defined via MVC helpers and followed by a jQuery() ready to install the custom additional toolbar button click handlers.
<div
class
=
"dual-listbox-container"
>
<div
class
=
"dual-listbox1"
>
<label
for
=
"listbox1"
>Chemistry Specs</label><br />
@(Html.Kendo().ListBox()
.Name(
"listbox1"
)
.HtmlAttributes(
new
{ title =
"Chemistry Specs"
})
.DataTextField(
"Name"
)
.DataValueField(
"SpecificationID"
)
.TemplateId(
"spec-item-template"
)
.Draggable(draggable => draggable.Placeholder(
"specItemDndPlaceholder"
))
.DropSources(
"listbox2"
)
.ConnectWith(
"listbox2"
)
.Toolbar(toolbar =>
{
toolbar.Position(Kendo.Mvc.UI.Fluent.ListBoxToolbarPosition.Right);
toolbar.Tools(tools => tools
.TransferTo()
.TransferFrom()
);
})
.Events(e => e
.Drop(
"lb1_drop"
)
.Remove(
"lb1_remove"
)
.Add(
"lb1_add"
)
.DragStart(
"lb_dragstart"
)
.DragEnd(
"lb1_dragend"
))
.BindTo(
new
List<dynamic>())
)
</div>
<div
class
=
"dual-listbox2"
>
<label
for
=
"listbox2"
>Lab Report Specs (3 max.)</label><br/>
@(Html.Kendo().ListBox()
.Name(
"listbox2"
)
.HtmlAttributes(
new
{ title =
"Lab Report Specs"
})
.DataTextField(
"Name"
)
.DataValueField(
"SpecificationID"
)
.TemplateId(
"spec-item-template"
)
.Draggable(draggable => draggable.Placeholder(
"specItemDndPlaceholder"
))
.DropSources(
"listbox1"
)
.ConnectWith(
"listbox1"
)
.Toolbar(toolbar =>
{
toolbar.Position(Kendo.Mvc.UI.Fluent.ListBoxToolbarPosition.Right);
toolbar.Tools(tools => tools
.MoveUp()
.MoveDown()
);
})
.Events(e => e
.Remove(
"lb2_remove"
)
.Reorder(
"lb2_reorder"
)
.Add(
"lb2_add"
)
.DragStart(
"lb_dragstart"
)
.DragEnd(
"lb2_dragend"
))
.BindTo(
new
List<dynamic>())
)
</div>
</div>
<script id=
"spec-item-template"
type=
"text/x-kendo-template"
>
<h3 data-spec-id=
"#:data.SpecificationID#"
><span
class
=
"dirty-mark # if (data.dirty) { #dirty-item# } #"
></span>#:data.Name# rev. #:data.Revision#</h3>
<p
class
=
"spec-material"
>#:data.Material#</p>
</script>
<script>
function specItemDndPlaceholder(draggedItem) {
return
draggedItem
.clone()
.addClass(
"custom-placeholder"
)
.removeClass(
"k-ghost"
);
}
jQuery(function () {
$(
"#listbox1"
).closest(
".k-listbox"
).find(
"[data-command='transferTo']"
).click(lb1_click_TransferTo);
$(
"#listbox1"
).closest(
".k-listbox"
).find(
"[data-command='transferFrom']"
).click(lb1_click_TransferFrom);
});
</script>
Prior to the list boxes are the functions for the custom click handling. For now I just want to log the event be handled. The messages don't appear in the developer tools console log window :( so I presume the widget is somehow causing additional handlers from being invoked (maybe a preventDefault going down within the widget internals?).
function
lb1_click_TransferTo(e) {
console.log(arguments.callee.name);
}
function
lb1_click_TransferFrom(e) {
console.log(arguments.callee.name);
}