I am new to Javascript and trying to use Gridster with Knockout. I have a database with items, and I use knockout foreach to bind them to a UL. The UL is styled with the Gridster library. Everything works great unless I try to add additional elements to the UL via the ObservableArray in the viewmodel.
Can anyone help me understand the scope and order of operations here? It feels like the Gridster library isn't doing its styling to the new widgets.
This jsfiddle shows a working demo of the issue. Notice when you double click on a widget, it creates a new one but doesn't place it in the grid. Instead, it just kind of hangs out behind.
Here is the HTML
<div class="gridster">
<ul data-bind="foreach: myData">
<li data-bind="attr:{
'data-row':datarow,
'data-col':datacol,
'data-sizex':datasizex,
'data-sizey':datasizey
},text:text, doubleClick: $parent.AddOne"></li>
</ul>
</div>
Here is the Javascript
//This is some widget data to start the process
var gridData = [ {text:'Widget #1', datarow:1, datacol:1, datasizex:1, datasizey:1},
{text:'Widget #2', datarow:2, datacol:1, datasizex:1, datasizey:1},
{text:'Widget #3', datarow:1, datacol:2, datasizex:1, datasizey:1},
{text:'Widget #4', datarow:2, datacol:2, datasizex:1, datasizey:1}];
// The viewmodel contains an observable array of widget data to be
// displayed on the gridster
var viewmodel = function () {
var self = this;
self.myData = ko.observableArray(gridData);
//AddOne adds an element to the observable array
// (called at runtime from doubleClick events)
self.AddOne = function () {
var self = this;
myViewModel.myData.push({
text: 'Widget Added After!',
datarow: 1,
datacol: 1,
datasizex: 1,
datasizey: 1
});
};
};
var myViewModel = new viewmodel();
ko.applyBindings(myViewModel);
$(".gridster ul").gridster({
widget_margins: [5, 5],
widget_base_dimensions: [140, 140]
});
Here is a full example in JSfiddle. Here, I have highlighted just the delete function
The work of removing the element from the observable array is done inside the remove_widget callback. See gridster's documentation. Consequently, the removeGridster hook executed before a widget is removed, does no longer need to do the actual remove_widget call.
Here's a working solution that I think is more in line with the MVVM pattern:
http://jsfiddle.net/Be4cf/4/
I still need to think about the remove and move events (a move in gridster should update the item's x and y values in the viewmodel). I started using knockout yesterday, so any help would be appreciated.
I couldn't find a cdn for the latest version of gridster. JSFiddle points to a temporary website I've added in Azure, I'll leave it up for a few days, but feel free to update it with your own link.
/------------------------------ UPDATE ----------------------------------/
I've updated my code to support deletions and moving widgets (http://jsfiddle.net/Be4cf/11/) but there's a small caveat: there's an open issue (https://github.com/knockout/knockout/issues/1130) that knockout cleans out jquery data before calling the beforeRemove event. This causes gridster to crash since the data needed to move the other items around is kept in a data element. A workaround could be to keep a copy of the data and to re-add it to the element later, but I've chosen the lazy way and commented the offending line in knockout.
Add class="gs_w" to ur li in gridster it should work
You should do something like below.
addNewGridElement
is called - with the rendered DOM element which is important in Gridster's case asgridster.add_widget
accepts a DOM element as its first argument - once you've added something to the Knockout observable. After this, it's just a matter of then addingdomNode
to Gridster.view.html:
view.js: