mishap
mishap

Reputation: 8515

Create an array and show each item number of times determined by selected option in KnockoutJs

There is a drop-down:

 <div class="divInfoMargin">
        There are
        <select data-bind="options: numberOfChildren" class="mscSelect"></select>
 </div>

I need to need to display the below selected number of times above:

<div data-bind="foreach: children">
        <div>
            Name: <input data-bind="value: name" type="text" />
            Date Of Birth <input type="text" data-bind="value: dob" class="datepicker" />
            Residence :
            <select data-bind="value: residence" name="residence" id="residence">
                <option value="0">1</option>
                <option value="1">2</option>
                <option value="2">3</option>

            </select>
        </div>
</div>

Knockout viewmodel and some rough ideas:

function Child(name, dob) {
        var self = this;
        self.name = name;
        self.dob = dob;
}

function AppViewModel() {
    var self = this;

    self.numberOfChildren = ko.observableArray(['1', '2', '3', '4', '5', '6']);

    //this array needs to be added to:
    self.children = ko.observableArray([]);

    //self.addChild = function() {
    //    self.children.push(new Child(""));
    //};

      //This is not working code:
      self.allChildren = ko.computed(function () {
      var total = 0;
      for (var i = 0; i < self.numberOfChildren().value; i++) {
          self.children.push(new Child(""));
      }    
    });
}

ko.applyBindings(new AppViewModel());

I'm totally new to KO and confused. Here is JSFiddle

Upvotes: 0

Views: 44

Answers (2)

TysonWolker
TysonWolker

Reputation: 436

I have slightly modified your code, you needed to set a selected value in your select and then use it in your computed, you had the right idea though.

HTML

<select data-bind="options: numberOfChildren, value: selectedNumberOfChildren" class="mscSelect"></select>

JavaScript

    self.selectedNumberOfChildren = ko.observable();
    self.allChildren = ko.computed(function () {
        var total = 0;
        self.children.removeAll();
        for (var i = 0; i < self.selectedNumberOfChildren(); i++) {
            self.children.push(new Child(""));
        }    
    });

http://jsfiddle.net/2prhq5v2/5/

Upvotes: 1

Retsam
Retsam

Reputation: 33399

There's two main problems with your code:

1) Your select needs a value binding to hold the selected value; you can't do self.numberOfChildren().value, you'll need a viewmodel observable to hold that value. (So your data-bind should be something like <select data-bind="options: numberOfChildren, value: currentNumberOfChildren">

2) Instead of trying to use a computed to populate an observable array, you should either just have the computed return the array that you want, or have an observable array with a subscription that populates it.

Computed that returns the array:

self.children = ko.computed(function () {
    var children = [];
    for (var i = 0; i < self.currentNumberOfChildren(); i++) {
        children.push(new Child(""));
    }   
    return children;
});

Observable Array with subscription:

self.children = ko.observableArray([]);
//Update self.children wehenver currentNumberOfChildren changes
self. currentNumberOfChildren.subscribe(function () {
    var children = [];
    for (var i = 0; i < self.currentNumberOfChildren(); i++) {
        children.push(new Child(""));
    }   
    self.children(children);
});

The first is simpler, but it's not an observable array, and thus doesn't have the helper methods like self.children.push (in fact, it's read only), but personally I'd go the first route.

(Working JSFiddle)

Upvotes: 1

Related Questions