Reputation: 67
I am bumped into another problem connected with KnockoutJS and jCanvas. My model and ViewModel:
eventsModel = function () {
var self = this;
self.events = ko.observableArray([]);
}
eventItemViewModel = function(o) {
var self = this;
self.BeginInMinutes = ko.observable(o.BeginInMinutes);
self.EventDuration = ko.observable(o.EventDuration);
self.Type = ko.observable(o.Type);
self.ReferenceNumber = ko.observable(o.ReferenceNumber);
self.FullDescription = ko.computed(function () {
var eventType = self.Type() == '0' ? 'Driving' : 'Resting';
var hour = Math.floor(self.BeginInMinutes() / 60);
var minutes = Math.floor(self.BeginInMinutes() % 60) < 10 ? '0' + Math.floor(self.BeginInMinutes() % 60) : Math.floor(self.BeginInMinutes() % 60);
return hour + ':' + minutes + " " + eventType + " " + self.EventDuration();
}, this);
};
var events = new eventsModel();
ko.applyBindings(events);
I think this should be enough for now. Basically, I want to show this FullDescription above my canvas, but the problem is that it is included in an array. In canvas I have some drawings and this all properties are connected with rectangles in canvas. I want to do something like: on mouseover event of rectangle in jCanvas I want to show fullDescription for example in plain text above the canvas.
I show some information in table using knockout data-bind foreach etc., but for now I want to show this one specified information from whole collection. I tried if binding but it wasn't working.
My canvas:
<canvas id="myCanvas" width="1000" height="300"></canvas>
And maybe my previous question have some valueable information: Knockout observablearray of observables with arrayMap function
I'm sure that it should be some simple way to get only specified field from an array.
Thank you.
Upvotes: 1
Views: 66
Reputation: 448
This is actually pretty straightforward with Knockout. You simply need to put your canvas in a Knockout foreach, and then all the usual Javascript events are available as Knockout bindings (like mouseover). A simple example is this:
HTML:
<div data-bind="foreach: { data: items, afterRender: itemRendered}">
<span data-bind="text: description"></span><br />
<canvas data-bind="event: {mouseover: $parent.doSomething}, attr: { id: itemId }" style="background-color: blue"></canvas><br />
</div>
Javascript:
var MyViewModel = function () {
var self = this;
self.items = ko.observableArray(
[
{ itemId: 1, description: "Item #1" },
{ itemId: 2, description: "Item #2" },
{ itemId: 3, description: "Item #3" }
]
);
self.doSomething = function (selectedItem) {
alert("You hovered over " + selectedItem.description);
};
self.itemRendered = function (o, renderedItem) {
console.log("Initialize your jCanvas here for canvas id: MyCanvas"
+ renderedItem.itemId);
};
};
As you can see, the act of iterating through your data items in the observableArray actually attaches that item as a data context to each canvas, so that when you do some event on one of the rendered canvases it can be received in the handler function and you have access to all the properties and functions of that particular item. In this case I called the passed item "selectedItem".
Now, as far as hooking up jCanvas to your canvas tags, you can use the afterRender callback of the foreach binding, which will pass an array of DOM elements in the rendered item (which we can ignore for now), and the data item itself. We can take the id of that data item using the "attr" binding to attach it to the canvas, and then programmatically initialize each individual jCanvas in our itemRendered handler function.
This now gives you all the flexibility in the world to define how each canvas will be rendered (shape, color, etc.) and that can all be driven by the data in each individual item.
Here is a JSFiddle to try it out:
https://jsfiddle.net/snydercoder/wkcqr76L/
Also, reference the Knockout docs for "foreach" and "attr" bindings.
Upvotes: 1