0

I am new to knockout. I am trying to use observable arrays to track the changes from UI. The UI is loading with the initial data which is stored in the array. And i am trying to add new object into the array dynamically from another screen.

Now i am able to add new object into the array. But UI is not getting reflected with new changes in the array. Below is my html and javascript code.

Am i missing something.

<html>
<head>
    <link rel="stylesheet" href="bootstrap.css" type="text/css" />
    <link rel="stylesheet" href="bootstrap-theme.css " type="text/css" />
    <script src="jquery.js" type="text/javascript"></script>
    <link rel="stylesheet" href="prodconfig.css " type="text/css" />    
    <script src="jquery.mobile.min.js" type="text/javascript"></script>
    <link rel="stylesheet" href="cordys.min.css" type="text/css" />
    <link rel="stylesheet" href="jquery.mobile.structure.min.css" type="text/css" />
    <script src="knockout.js" type="text/javascript"></script>
    <script src="prodconfig.js" type="text/javascript"></script>
</head>
<body>
    <div data-role="page" id="productsPage" class="dataContainer">
        <div id="productDetails">
            <div data-role="content" id="productTable">
                <table data-role="table" class="ui-responsive table">
                    <thead>
                        <tr>
                          <th data-priority="6">Product Name</th>
                          <th data-priority="1">Description</th>
                          <th data-priority="2">Parent?</th>
                        </tr>
                    </thead>
                    <tbody id="pBody"  data-bind="foreach: products">
                        <tr class="success">
                          <td><span data-bind="text: name"></span></td>
                          <td><span data-bind="text: desc"></span></td>
                          <td></td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
        <div id="prodButtons">
            <button id="addProdProduct">Add Product</button>
            <button id="addProdChar">Add Characteristics</button>
            <button id="prodButton">Next</button>
        </div>
    </div>  
    <div id="addProductPage" data-role="page" >
        <span><h3>Product Name</h3></span><input type="text" id="prodNameId"></input>
        <span><h3>Product Desc</h3></span><input type="text" id="prodDescId"></input>
        <span><h3>Is Parent</h3></span><input type="text" id="prodIsParentId"></input>
        <button id="addProdButton">OK</button>
    <div>
</body>

var configArray = new Array();
var products = [];
var services = new Array();
var chars = [];
var prd;



for(var i=0;i<2;i++){
    var product = new Object();
    product["name"] = "prod"+i+"Name";
    product["desc"] = "prod"+i+"Desc";
    product["isParent"] = "prme";

    for(var j=0;j<2;j++){
            var charr = new Object();
            charr["name"] = "prod"+i+"char"+j;
            charr["val"] = "prod"+i+"char"+j+"val";
            chars[j] = charr;
    }
    product["chars"] = chars;
    products[i] = product;

}

var ProductViewModel =  function(items) {
    this.items = ko.observableArray(items);
    this.itemToAdd = ko.observable("");
    this.addItem = function() {
        if (this.itemToAdd() != "") {
            this.items.push(this.itemToAdd()); 
            this.itemToAdd(""); 
        }
    }.bind(this);  
};

$(function(){
    $('#addProdProduct').click(function() {
        window.location.href = "#addProductPage";
    });
    $('#addProdButton').click(function() {
        addProduct();
    });
    prd = new ProductViewModel(products);
    ko.applyBindings(prd);

});

function addProduct(){
    var product = new Object();
    product["name"] = $('#prodNameId').val();
    product["desc"] = $('#prodDescId').val();
    product["isParent"] = $('#prodIsParentId').val();
    prd.itemToAdd(product);
    prd.addItem();
    window.location.href = '#';
}
0

2 Answers 2

3

You are binding to the products variable instead of to the items field on your viewmodel.

Change your binding to:

<tbody id="pBody"  data-bind="foreach: items">
Sign up to request clarification or add additional context in comments.

2 Comments

Aah...i missed that part as it was working for the initial content.
that's because you in initial for loop you are assigning data to products which is plane variable of array type (non-observable) .
0

The code below shown a sample procedure for inserting data using knockoutjs MVVM pattern. Here i using bootstrap Modal Popup for inserting Data.

HTML

<div class="row">
<button type="button" class="btn btn-primary pull-right" data-bind="click:add" data-toggle="modal" data-target="#myModal1">
    <i class="fa fa-plus"></i> Add New Data
</button>
<table class="table">
    <thead>
        <tr>
            <th>Name</th>
            <th>Action</th>
        </tr>
    </thead>
    <tbody data-bind="template:{name:'item-view-template',foreach:products}"></tbody>
</table>
</div>
<script type="text/html" id="item-view-template">
<tr>
    <td class="text-left" data-bind="text:ProductName"></td>
    <br />
/tr>
</script>
<div class="modal fade" id="myModal1" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">Add Data</h4>
            </div>
            <div class="modal-body" data-bind="template:{name:'item-create-template',data:selectedData}">
                <div class="row">
                    <div class="col-md-12"></div>
                </div>
            </div>
        </div>
    </div>
</div>
  <script type="text/html" id="item-create-template">
   <form>
    <fieldset>
        <div class="form-group col-md-6">
            <label>Name</label>
            <input type="text" class="form-control" data-bind="value:ProductName" />
        </div>
        <button class="btn btn-primary" data-bind="click:$parent.save">Save</button>
        <button class="btn btn-default" data-dismiss="modal">Cancel</button>
    </fieldset>
   </form>
  </script>
  <script type="text/javascript">
    var vm = new ProductViewModel();
    ko.applyBindings(vm);
    vm.init();
  </script>

View Model Js File

function ProductViewModel() {
var self = {};
self.data = ko.observableArray();
self.products = ko.observableArray();
self.selectedData = ko.observable(Product({}));

self.init = function () {
    $.get('/MyController/GetAll', function (data) {
        $.each(data, function (key, value) {
            self.products.push(Product(value));
        });
    });
};
self.add = function () {
    self.selectedData(Product({}));
};
self.save = function() {
    if (self.selectedData()) {
        var jsonData = ko.toJS(self.selectedData);
        $.post('/MyController/Create', jsonData, function(data) {
            if (data.Status == true) {
                $('#myModal1').modal('hide');
                bootbox.alert("Product created successfully", function() {
                    self.Products.removeAll();
                    $.get('/MyController/GetAll', function (result) {
                        $.each(result.Products, function (key, value) {
                            self.Products.push(Product(value));
                        });
                    });
                });
            } else {
                bootbox.alert("Duplicate values not allowed..!!");
            }
        });
    } else {
       bootbox.alert("Error!!");
    }
};
return self;
}

And the Model

function Product(product) {
var self = {};
self.Id = ko.observable(product.Id || '');
self.ProductName = ko.protectedObservable(product.Name || '');
return self;
}

I think this will help you

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.