I'm trying to create custom binding for CSS classes with switching by condition because the "style" binding isn't useful for my case. My cssClass binding uses "path with params " like "style" and "attr" bindings:
data-bind="cssClass: {condition: isEnabled, class1: style-red, class2: style-blue }"
In docs I see one example this.bindings["slide"].get() for simple path like data-bind:"slide:isEnabled"
What is the legit solution for processing this types of bindings (with complicated pathes)?
Please, take a look on my realisation CSS custom binding example
It works on page load but not works when isEnabled updated. I suspect that this behavior is due to the fact that I did not cal .get() function. But when I call that function I've got this error message: Uncaught TypeError: Object #<Object> has no method 'charAt'.
19 Answers, 1 is accepted
Thanks
I'm afraid that such bindings declaration is currently not supported. As a workaround in this specific case you may use similar to the following approach:
Rosen
the Telerik team
The only remaining problem for me is when using this within a template. I think this is related to my other question here: http://www.kendoui.com//forums/framework/mvvm/custom-binding-not-working-in-templates.aspx
What it seems to be is that when used within a template, such bindings look at the currently iterated object which is not the ViewModel itself.
For example, if I have such a ViewModel:
var vm = new kendo.observable({
products: [{name: 'Banana'}, {name: 'Apple'}, {name: 'Orange'}],
isEnabled: true //would be a function in real life
goToFolder: function() {...} // some function
});
and then use a source binding as this:
<ul data-template="product-template" data-bind="source: products"></ul>
<script id="product-template" type="text/x-kendo-template">
<li data-bind="click: goToFolder, cssClass: isEnabled, text: name" data-enabled-class="style-red" data-disabled-class="style-blue"></li>
</script>
the cssClass binding will look for the "isEnabled" property on the product object. I'd like it to look at the "parent" ViewModel instead. How could this be accomplished ?
On the other hand, the click binding does use the goToFolder function on the ViewModel, so I'm thinking it's possible to access the ViewModel, but I can't figure out how.
Thanks
EDIT: I'm using Kendo UI Complete v2012.1.406
As you are using an internal build, you may be able to use the parent method of the ObservableObject/ObservableArray to achieve similar to the desired behavior:
<li data-bind=
"click: goToFolder, cssClass: parent().parent().isEnabled, text: name"
data-enabled-class=
"style-red"
data-disabled-class=
"style-blue"
></li>
However, note that as this is an internal build the behavior may change in the feature.Greetings,
Rosen
the Telerik team
This seems to work so far, thanks.
I didn't know such syntax was allowed. Is that documented somewhere, or is it just a beta feature ?
Regards
This is more of undocumented workaround, which as I have mentioned may not function in feature versions.
Regards,Rosen
the Telerik team
Please believe me when I say I appreciate the efforts that the KendoUI team puts into helping us, but I hope you'll understand that as a developer, I can't rely on undocumented features. The reason is quite simple, as you put it yourself, it might not work in the future. I need features that won't break my code down the road.
Now, if I may go back to the reason why I have to jump through so many hoops to get this working is simply that kendoUI's bindings don't yet offer a css binding.
I know there is a style binding, but I refuse to use this as it places style information in my code and this is not where it belongs. Style should go in css files, and we should be able to conditionally apply style to our bound elements.
This is definitely a major concern for me, and for many others I'd think.
Regards
Indeed, the MVVM class binding is currently not supported. If you would like to be included in a future version of the library, you may submit your idea here.
All the best,Rosen
the Telerik team
I just entered the wish on the UserVoice site.
I know that KendoUI MVVM was only recently released, but I sure hope it will mature quickly to become at least at par with knockoutjs.
Regards
Out of curiosity I implemented the parent().parent().isEnabled workaround, and at first I thought it did work but now I realise it only works the first time the page is loaded.
Debugging shows that the refresh method of the binding is not called when the "isEnabled" value on my ObservableObject changes, even though I made sure to use the set() method to modify it.
I just thought I'd let you know.
The parent property is available in the latest internal build.
Regards,Rosen
the Telerik team
I have a problem with that build...it's throwing this error
"((f.event.special[s.origType] || {}).handle || s.handler).apply is not a function" in jquery.min 1.7.2
I have an element inside of a array template bound to this
data-bind="click: addItem"
Where addItem is a function in the viewModel
viewModel = kendo.observable({
addItem:
function
(campus) {
this
.selectedCampus = campus;
openAddNewWindow();
}
});
$.extend(viewModel, kendo.observable(data));
So "addItem" exists I guess technically in the parent()...so if I change it to
data-bind=
"click: parent().addItem"
data-bind=
"click: parent().parent().addItem"
- Am I missing something? Like the addItem viewModel function itself never gets called "When defined inside a template"
I'm afraid that this code will not work as you are extending the one viewModel with the other, however this will not set the correct parents. Instead of using extend you may loop over the other objects fields and add them to the ViewModel instance:
$(document).ready(
function
() {
var
data = { items: [{foo:
"foo"
}] };
var
viewModel = kendo.observable({
addItem:
function
() {
alert(
"Item is clicked"
);
}
});
for
(
var
field
in
data) {
viewModel.set(field, data[field]);
}
kendo.bind($(
"#container"
), viewModel);
});​
However, note that this will not work as expected with the current internal build and you should wait for the next one.
All the best,
Rosen
the Telerik team
I would like to respectfully say no to this solution :) You guys can come up with better...maybe a utility method or something.
Here's my model...it's more than a single array with "foo". Part of the idea of MVVM is to help save time and code, not have my model be a giant nested loop to re-set values. Atanas was the one who told me to use $.extend in the first place.
var
coredata = {
"BlockID"
: 14,
"ClerkshipID"
: 1,
"Cohort"
: 2013,
"Clerkship"
:
"Anesthesiology"
,
"IsSelective"
:
false
,
"StartDate"
:
"2011-12-05T00:00:00"
,
"EndDate"
:
"2011-12-19T00:00:00"
,
"Campuses"
: [{
"CampusID"
: 0,
"Campus"
:
"Hamilton"
,
"Released"
:
true
,
"AvailableToHamilton"
:
false
,
"Rotations"
: [{
"RotationID"
: 6,
"Rotation"
:
"Anesthesiology"
,
"Sites"
: [{
"SiteID"
: 2,
"Site"
:
"Chedoke Hospital"
,
"Min"
: 1,
"Max"
: 2},
{
"SiteID"
: 11,
"Site"
:
"Hamilton General Hospital"
,
"Min"
: 0,
"Max"
: 2},
{
"SiteID"
: 45,
"Site"
:
"Hamilton Health Sciences"
,
"Min"
: 1,
"Max"
: 4}]}]},
{
"CampusID"
: 1,
"Campus"
:
"Waterloo"
,
"Released"
:
true
,
"AvailableToHamilton"
:
false
,
"Rotations"
: [{
"RotationID"
: 6,
"Rotation"
:
"Anesthesiology"
,
"Sites"
: [{
"SiteID"
: 47,
"Site"
:
"Kitchener-Waterloo"
,
"Min"
: 3,
"Max"
: 3}]}]},
{
"CampusID"
: 2,
"Campus"
:
"Niagara"
,
"Released"
:
false
,
"AvailableToHamilton"
:
false
,
"Rotations"
: []}],
"AllReleased"
:
false
};
If you take a more close look at the ObservebleObject's set method, you may notice that it support setting objects thus it will make the whole passed in object observable. Therefore, the code from my previous post will work with the object you have shown as it is without modifications.
Regards,Rosen
the Telerik team
Perhaps
viewModel.load(data)
When can you get this internal build out?...
Most probably there will be a service pack available in the next week or two.
Greetings,Rosen
the Telerik team