Reputation: 34830
Lets say I have a bound span
<span data-bind="MyBinding: Name"></span>
And I have a custom binding
ko.bindingHandlers.MyBinding = {
init: function (element, valueAccessor, allBindings, viewModel, context) {
// I want to get the string "Name" here. NOT the value of Name.
},
};
How do i get a string with the value of the binding expression inside the handler? ie how do i get "Name" not "Value of name".
I also need the expression so passing the string "Name" is not feasible.
<span data-bind="MyBinding: 'Name'"></span>
Upvotes: 5
Views: 1580
Reputation: 10966
Actually, Knockout does have a built-in way to do this. You do need to adapt your custom binding a little (namely, it becomes an object instead of a string value). Knockout allows you, along with the init
and update
properties, to specify a preprocess
property. For example, suppose we have the following viewModel:
var app = { data: ko.observable('Hello World') };
And a simple binding that would convert the string passed to it fully to lowercase, and output both the binding's name and value (the property passed in the view obviously being data
):
ko.bindingHandlers.lower = {
update: function(elem, value) {
var obj = ko.unwrap(value());
elem.textContent = 'Name: ' + ko.unwrap(obj.name) +
' - Value: ' + ko.unwrap(obj.data).toLowerCase();
},
preprocess: function(value, bindingName) {
return '{data:' + value + ', name:\'' + bindingName + '\'}';
}
};
It's as simple as stringifying the value
property passed to it & transforming the binding's value into an object with 2 keys (name & value here). Have a look. See Binding preprocessing for more info.
Upvotes: 2
Reputation: 4805
I like what pavel-chervov said above. In a similar vein if you don't mind using a bit of jQuery:
<span data-binding-name="Name" data-bind="MyBinding: Name"></span>
ko.bindingHandlers.MyBinding = {
init: function (element, valueAccessor, allBindings, viewModel, context) {
var nameOfProp = $(element).data('binding-name');
},
};
Upvotes: 1
Reputation:
I propose to transfer the name of the property with use another binding.
<div data-bind="myBinding: content, nameOfProp:'content'"></div>
ko.bindingHandlers.myBinding = {
init: function(element, valueAccessor, allBindings, viewModel, context) {
var nameOfProp = allBindings.get("nameOfProp");
};
}
Upvotes: 1
Reputation: 1024
I'm a bit late to the party on this, but here's what I did, and it works like a charm:
JS:
ko.bindingHandlers.myHandler = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var regex = /return ([^\s]+)\s*}/;
//accessor will contain whatever expression was used in data-bind
//so in this example it will be "myProp.childProp"
var accessor = regex.exec(valueAccessor.toString())[1];
//...
},
//...
HTML:
<div data-bind="myHandler: myProp.childProp"></div>
So the value of accessor (in case you missed the comment) will be "myProp.childProp"
Upvotes: 0
Reputation: 460
You could do the following, so you won't need the eval.
<span data-bind="MyBinding: 'Name.More.AndMore'"></span>
ko.bindingHandlers.MyBinding = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var value = valueAccessor();
var sp = value.split('.');
var current = viewModel;
for(var i=0;i<sp.length;i++) {
var nNode = current[sp[i]];
if ( nNode ) {
current = nNode;
}
}
$(element).html(current());
}
};
As nemesv already explained, you need to give the Name as string value in your binding. After that you can use this to step through your viewmodel to retrieve the value. To display the value in the element I've added
$(element).html(current());
Here the current()
is at the deepest level in my viewmodel so it can be called and the return value can be used to update the html.
Upvotes: 1
Reputation: 139748
You need to pass in Name
as string and not as a reference:
<span data-bind="MyBinding: 'Name'"></span>
ko.bindingHandlers.MyBinding = {
init: function (element, valueAccessor, allBindings, viewModel, context) {
var myBinding = valueAccessor(); // will contain 'Name';
var valueOfmyBinding = viewModel[myBinding]; //value of the Name property
},
};
You can still use your expression as a string because in Javascript you can eval altough eval()
is a dangerous function: here is a sample JSFiddle.
Or if you only need to support simple property expression like Child.Name
you can write your own parser where you split the string on the dots and foreach on the accessors.
Upvotes: 2