Passing in an observableArray as a function parameter-Collection of common programming errors
What I’m trying to achieve: A form with one text input field(Name), two select fields with some options(Type & Column) with a submit button that creates a Widget with it’s title set to Name, data-type set to Type and Column – being it’s position in the page.
Type in this case has a couple of different options defined in the view, it works just dandy so I won’t go into how I got that working, for now.
As of now I have a page with three columns, each as it’s own observableArray – like so:
self.col0 = ko.observableArray([]);
self.col0.id = 'col0'
The same goes for col1 and col2. My goal here is to get the select field to point to these arrays. Atleast that’s what I think I need to do.
I have a createWidget function, that looks at the Name and Type values in the DOM (Correct me if I’m wrong here, this is the very first thing I’m creating with KnockOut) and creates a new Widget from that data – like so:
var Widget = function(name, type) {
var self = this;
self.name = name;
self.type = type;
};
var ViewModel = function() {
var self = this;
self.newWidgetName = ko.observable();
self.newType = ko.observable();
// Unrelated code in between
self.createWidget = function(target) {
newName = self.newWidgetName();
newType = self.newType();
widget = new Widget(newName, newType);
target.unshift(widget)
self.newWidgetName("");
};
The input/select elements in the DOM
input.widget-name type="text" placeholder="wName" data-bind="value: newWidgetName"
select data-bind="value: newType"
option value="calendar" Calendar
option value="article" Article
option value="document" Document
select.colPick data-bind="value: colPick"
option value="col0" Column 1
option value="col1" Column 2
option value="col2" Column 3
And my click handler for the createWidget function – like so:
a.btn.create-widget data-bind="click: function(){ createWidget(col0); }"
Shazam, it works!
However, this will only ever output the new Widget into the first col (col0), it won’t take the value of the column select field into account and unshift the new widget into the correct column. The errors I’m getting after much trial and error pretty much boils down to:
1) “Cannot call method unshift of undefined”
2) “Uncaught TypeError: Object function observable() …. has no method ‘unshift’
So as of right now the code looks like the example above, It’s not ideal by any means but with the different columns connected with knockout-sortable, it’s not a huge deal if this functionality has to get scrapped. The user can still move the Widgets around from col0 to col2 and vice versa.
If anyone has a resource that would point me in the right direction, or the answer up their sleeve – feel free to share!
All the best, Kas.
Edit: Followup questions for Tyrsius
With the code you supplied I now have the three columns working in the select box, however I am struggling a bit when it comes to outputting the Widgets into view.
With my previous code, this is what the view looked like:
What I'm working with right now is this:
My first question, I realised I wasn't thinking at the time so skip that one.
Question #2: How would I now get these Widgets bound to the col that I picked in the form? Would I do this?
Or am I way off? :)
-
I would keep a collection of the items on the column as a type, which would look like this:
var Column = function(header) { this.header = ko.observable(header); this.items = ko.observableArray([]); };
The trick would be to bind the column
select
straight to the list of columns on your viewmodel: