Reputation: 532
function Employee() {
var self = this;
self.name = ko.observable("John");
}
ko.bindingHandlers.test = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// implementation
}
}
<div data-bind="test: name"></div>
Is there a way to get the observable name? not the value of the observable.
TIA.
Update:
This is the code snippet.
function ViewModel() {
var self = this;
$.ajax({
type: type,
url: url,
success: function (data) {
ko.mapping.fromJS(data, {} , self);
}
});
self.item = ko.observable(self.my_item);
self.selectedItem = ko.observable();
}
ko.bindingHandlers.item = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
$el = $(element);
var propName = allBindings().name;
var val = ko.unwrap(valueAccessor());
$el.attr("src", val);
$el.click(function () {
viewModel.selectedItem(propName);
});
},
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
$el = $(element);
var ops = allBindings().name;
var val = ko.unwrap(valueAccessor());
$el.attr("src", val);
}
};
ko.bindingHandlers.selectItem = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
$el = $(element);
$el.attr("src", valueAccessor());
$el.click(function () {
bindingContext.$data.item()[ko.unwrap(bindingContext.$data.selectedItem)](valueAccessor());
});
}
};
<img height="25" width="25" data-bind="item: item().img1, name: 'img1'" />
<img height="20" width="20" data-bind="selectItem: '/images/myimage1.png'" />
<img height="20" width="20" data-bind="selectItem: '/images/myimage2.png'" />
<img height="20" width="20" data-bind="selectItem: '/images/myimage3.png'" />
When you click images that has selectItem
the first image should replaced its src
attribute. If you have better way to do this please suggest.
FYI, the properties inside items
observables are link of images.
TIA.
Upvotes: 1
Views: 3276
Reputation: 410
<div data-bind="foreach: {data: skills, as: 'skill'}" >
<div data-bind="foreach: Object.keys(skill)" >
<a data-bind="text: $data"></a> : <a data-bind="text: skill[$data]"></a>
</div>
</div>
v = new function AppViewModel() {
this.skills = [{rates:"sdfdcvxcsd", cat: 2, car:55}, {color:"sdfdcvxcsd", zoo: 2,boat:55}];
}
ko.applyBindings(v);
Upvotes: 1
Reputation: 338128
You are getting ahead of yourself with the custom binding.
The bottom line is: You don't need a custom binding for what you want to do. It's easy - if you don't make it complicated:
function loadImages() {
// return $.get(url);
// mockup Ajax response, in place of a real $.get call
return $.Deferred().resolve({
items: [
{height: 20, width: 20, src: 'http://placehold.it/150/30ac17', title: 'image 1'},
{height: 20, width: 20, src: 'http://placehold.it/150/412ffd', title: 'image 2'},
{height: 20, width: 20, src: 'http://placehold.it/150/c672a0', title: 'image 3'}
]
}).promise();
}
function ImageList() {
var self = this;
// data
self.items = ko.observableArray();
self.selectedItem = ko.observable();
// init
loadImages().done(function (data) {
ko.mapping.fromJS(data, {}, self);
});
}
ko.applyBindings(new ImageList())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<div data-bind="with: selectedItem">
<img data-bind="attr: {height: 25, width: 25, src: src}">
</div>
<div data-bind="foreach: items">
<img data-bind="attr: {height: height, width: width, src: src}, click: $root.selectedItem" />
</div>
<hr>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
Note how I use selectedItem
as a click event handler. This is possible because in event handlers, knockout passes the relevant object (in this case, an image object from the array) as the first argument. Conveniently, observables set their value to the first argument you call them with. And presto: You have click event handler that sets the last clicked object.
EDIT
"I need multiple selected item then my items are just my context menu not just one selected item."
function loadImages() {
// return $.get(url);
// mockup Ajax response, in place of a real $.get call
return $.Deferred().resolve({
items: [
{height: 20, width: 20, src: 'http://placehold.it/150/30ac17', title: 'image 1'},
{height: 20, width: 20, src: 'http://placehold.it/150/412ffd', title: 'image 2'},
{height: 20, width: 20, src: 'http://placehold.it/150/c672a0', title: 'image 3'}
]
}).promise();
}
function ImageList() {
var self = this;
// data
self.items = ko.observableArray();
self.selectedItems = ko.observableArray();
// init
loadImages().done(function (data) {
ko.mapping.fromJS(data, {}, self);
});
self.selectItem = function (item) {
var pos = ko.utils.arrayIndexOf(self.selectedItems(), item);
if (pos === -1) self.selectedItems.push(item);
};
self.deselectItem = function (item) {
var pos = ko.utils.arrayIndexOf(self.selectedItems(), item);
if (pos !== -1) self.selectedItems.remove(item);
};
}
ko.applyBindings(new ImageList())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<div data-bind="foreach: selectedItems">
<img data-bind="attr: {height: 25, width: 25, src: src}, click: $root.deselectItem">
</div>
<div data-bind="foreach: items">
<img data-bind="attr: {height: height, width: width, src: src}, click: $root.selectItem" />
</div>
<hr>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
Upvotes: 1
Reputation: 7308
This will get you the observable name.
This converts the valueAccessor
(function(){return name }
) to a string which is then split to remove the observable name
.
ko.bindingHandlers.GetObservableName = {
init: function (element, valueAccessor) {
var observableName = String(valueAccessor).split(' ')[1];
alert(observableName);
}
};
function Employee() {
var self = this;
self.name = ko.observable("John");
}
<div data-bind="GetObservableName: name"></div>
Here is a JSFiddle
The index of the split
method in the fiddle is different to the one in the example above. The above works for me in Visual Studio 2013.
Thanks
Upvotes: 0
Reputation: 6045
Try something like this
view:
<div data-bind="test:name,propertyName:'name'"></div>
viewModel:
ko.bindingHandlers.test = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var propertyName = allBindings().propertyName; //property name here
ko.bindingHandlers.text.update(element, valueAccessor);
alert(propertyName)
}
};
function Employee() {
var self = this;
self.name = ko.observable("John");
}
ko.applyBindings(new Employee());
working fiddle here
Upvotes: 0