user81642
user81642

Reputation: 109

KnockoutJS Grid to add items

I currently have a form that will let the users to add item to the submission, since I am very new to KnockoutJS I just made this form to accept the one Product for the submission

<script type="text/html" id="page4-template">
<h4>Strain Information : </h4>
<table>
    <tr>
        <td class="firstCol">Stock number : </td>
        <td><span id="SummaryP1_StockNum" data-bind="text: stockNumber"></span></td>
    </tr>
    <tr>
        <td class="firstCol">Product Needed : </td>
        <td>
            <span id="SummaryP1_pdtNeeded" data-bind="text: pdtNeeded"></span>
            <span data-bind="visible: pdtNeeded() == 'Other'">
                <span id="SummaryP1_pdtNeededPleaseExplain" data-bind="text: pdtNeededPleaseExplain"></span>
            </span>
        </td>
    </tr>
    <tr>
        <td class="firstCol">Requested Ship Date : </td>
        <td><span id="SummaryP1_RequestedShipDate" data-bind="text: requestedShipDate"></span></td>
    </tr>
    <tr>
        <td class="firstCol">Aditional Information : </td>
        <td><span id="SummaryP1_AdditionalInformation" data-bind="text: additionalInformation"></span></td>
    </tr>

</table>
<hr>
</script>

If I need to make this form to allow users to add more item to the submission dynamically, what should I be using here, I am little confused as thee are dynamic bootstrapping, Overservable Array and all. Can anyone please suggest what could I do to simple to allow users to dynamically add item.

Upvotes: 0

Views: 143

Answers (2)

awj
awj

Reputation: 7949

I would suggest three steps:

The first step would be collect into one object all those observable properties which you bind to the table's elements:

createRowItem = function(data) {
    return {
        additionalInformation = ko.observable(data.additionalInformation),
        pdtNeeded = ko.observable(data.pdtNeeded),
        pdtNeededPleaseExplain = ko.obsevable(data.pdtNeededPleaseExplain),
        requestedShipDate = ko.observable(data.requestedShipDate),
        stockNumber = ko.observable(data.stockNumber),
    }
};

You would obtain an instance of a new rowItem...

var newRowItem = createRowItem(data);

The second step is to create an observableArray (documentation) in your existing view-model:

self.rowItems = ko.observableArray([]);

To populate that array with your collection of rowItem instances you could call self.rowItems.push(newRowItem) (documentation) but it's more efficient to obtain a reference to the inner array (i.e., the primitive array which the observableArray is watching), add the new instance to that, then tell the observableArray that its data has been updated. [The reason for this efficiency has to do with the way Knockout works internally, and tracks mutations.]

My suggestion would be to do this inside a public function on your view-model:

self.addRowItem = function(newRowItem) {
    var arr = ko.unwrap(self.rowItems);  // obtain the underlying array
    arr.push(newRowItem);  // add the new object to the underlying array
    self.rowItems.valueHasMutated();  // tell Knockout that the underlying array has been modified
};

The final step is to wrap your <tr> elements in a foreach binding (documentation):

<script type="text/html" id="page4-template">
<h4>Strain Information : </h4>
<table data-bind="foreach: rowItems">
    <tr>
        <td class="firstCol">Stock number : </td>
        <td><span id="SummaryP1_StockNum" data-bind="text: stockNumber"></span></td>
    </tr>
    ...
</table>

Upvotes: 1

Brother Woodrow
Brother Woodrow

Reputation: 6372

You will indeed want to use an observableArray to store multiple items. Then you loop through this array with the foreach binding and you add a method on your viewmodel to push new items to this array.

Something like this:

vm.row = ko.observableArray();

vm.addRow = function () {
    vm.row.push({
        stockNumber: ko.observable(1),
        pdtNeeded: ko.observable('Other'),
        pdtNeededPleaseExplain: ko.observable('Hello'),
        requestedShipDate: ko.observable(),
        additionalInformation: ko.observable()
    })
}

Fiddle: https://jsfiddle.net/thebluenile/2q8tbp5n/

For good measure, I also added an example of how you could remove the rows.

Upvotes: 1

Related Questions