0

I am developing an app using HTML5, Knockouk and Jquery.

The UI presents a list of Orders. At first it will show 5 orders, and when a user clicks on a "Show More" button, the next 5 orders will show.

When an Order is clicked, I will show all the activities that are related to that Order and I will be showing the first 10 activites and so on when the user clicks on the "More" button.

I have created a small example based on the requirements. I have created the first step, but I'm not able to create step 2. I am unsure how to create a nested observable array. I have added a sample, which is working for step but not for the second step.

<h1>Using Observable Arrays<br /></h1>

<div id="divActivites">
    <!-- ko foreach: Activities -->
        <div data-bind="click:$root.showDesc, attr:{'name':name,'id':id}">
            <td><span data-bind="text:name"></span></td>
            <td><span data-bind="text:id"></span></td>
        </div>
    <!-- /ko -->
    <input type="button" value="Show More" data-bind="click:addData" />
</div>
<div id="divActDec" data-bind="with:selectedData ">
    <span data-bind="text:id"></span><br />
    <span data-bind="text:name"></span><br />
    <span data-bind="text:randomStringDesc()"></span>

</div>

<script type="text/javascript">
function ActivityListModel() {
      var self = this;
      var total = ko.observable();
      self.Activities = ko.observableArray([]);
      self.selectedData = ko.observable();

      total = 0;

      self.addData = function () {
          var addtoArray = 5;

          var finalVal = total + addtoArray;

          for (var i = total+1; i <= finalVal; i++) {
              self.Activities.push(
              {
                  name: randomString(),
                  id: i
              }
              )
          }

          total = finalVal;
      }

      self.showDesc = function (ActivitiesDesc) {
          $("#divActivites").hide();
          $("#divActDec").show();
          self.selectedData(ActivitiesDesc);
      }
  }

  function ActivitiesDesc(data) {
      var activitydesc = this;
      activitydesc.name = data.name;
      activitydesc.actid = data.id;
  }

  function randomString() {
      var value = "";
      var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      for (var i = 0; i < 10; i++) {
          value += letters.charAt(Math.floor(Math.random() * letters.length));
      }
      return value;
  }

  function randomStringDesc() {
      var value = "";
      var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      for (var i = 0; i < 150; i++) {
          value += letters.charAt(Math.floor(Math.random() * letters.length));
      }
      return value;
  }

  ko.applyBindings(new ActivityListModel());
</script>

Can someone tell me how to create ActivitiesDesc object as an observable array?

Thanks, Jollyguy

1
  • I've updated the answer based on your comments Commented Jul 21, 2014 at 10:10

1 Answer 1

1

Here's a working version of what I think you're after:

Working JS Fiddle

Firstly I nested the details section into the foreach block and created an observable to control it's visibility showDesc and the click binding was modified to call toggleDesc, which switches the visibility on or off:

<!-- ko foreach: Activities -->
<div data-bind="click:$root.toggleDesc, attr:{'name':name,'id':id}">
    <div>Name: <span data-bind="text:name"></span>

    </div>
    <div>Id: <span data-bind="text:id"></span>

    </div>
</div>
<!-- added this block with a visible binding -->
<div id="divActDec" data-bind="visible: showDesc" 
                    style="border: 1px solid #000;">
     <h1>Details:</h1>
     ID: <span data-bind="text:id"></span><br />
     Name: <span data-bind="text:name"></span><br />
     Desc: <span data-bind="text:randomStringDesc()"></span>

</div>
<!-- /ko -->

In the JS, you will see a new observable per Activity that looks like this:

showDesc: ko.observable(false)

This is set to false by default. Then there is the method to toggle the description when you click an item:

self.toggleDesc = function (item) {
    item.showDesc(!item.showDesc());
}

Full JS

function ActivityListModel() {
    var self = this;
    var total = ko.observable();
    self.Activities = ko.observableArray([]);
    self.selectedData = ko.observable();

    total = 0;

    self.addData = function () {
        var addtoArray = 5;

        var finalVal = total + addtoArray;

        for (var i = total + 1; i <= finalVal; i++) {
            self.Activities.push({
                name: randomString(),
                id: i,
                showDesc: ko.observable(false)
            })
        }

        total = finalVal;
    }

    self.toggleDesc = function (item) {
        item.showDesc(!item.showDesc());
    }
}

function ActivitiesDesc(data) {
    var activitydesc = this;
    activitydesc.name = data.name;
    activitydesc.actid = data.id;
}

function randomString() {
    var value = "";
    var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for (var i = 0; i < 10; i++) {
        value += letters.charAt(Math.floor(Math.random() * letters.length));
    }
    return value;
}

function randomStringDesc() {
    var value = "";
    var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for (var i = 0; i < 150; i++) {
        value += letters.charAt(Math.floor(Math.random() * letters.length));
    }
    return value;
}

ko.applyBindings(new ActivityListModel());

Update:

I've updated the sample to nest an observableArray in to the top level array. I have renamed the top level array to be Orders, which now contains an array of activities:

Updated JS Fiddle:

The for loop now looks like this:

    for (var i = total + 1; i <= finalVal; i++) {
        self.Orders.push({
            name: randomString(),
            id: i,
            showDesc: ko.observable(false),
            activities: ko.observableArray([{
                "name": "Description 1",
                "actid": 123
            }, {
                "name": "Description 2",
                "actid": 456
            }])
        })
Sign up to request clarification or add additional context in comments.

3 Comments

thanks for the reply. in your code, when clicking on a item, showDesc is showing only 1 item, but i want to show multiple items for that item. That is where i am stumped. I will be binding the datas from database, since i am learning about knockout, i was creating a simple example.
I'll have another look later
sorry for the delay, was on a vacation. I have put a button inside the activites and I tried to add some more activites for the same order when i click on that button and i was not able to do so. Then i created an activities object and then combined both and got a working example. I still have some issues in it. For example, when i click on Order1, it's showing the activites of Order1 and then when i click on Order4, only activities for Order4 should be shown, instead both Orders activities is shown. I have created an Fiddle. what am i doing wrong?

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.