5

I can't reset observable array with new value am using some lazy loading Technic. I can clear but can't reset, but it not allowing me to add new dynamic value.

fiddle http://jsfiddle.net/kspxa8as/

js

var i = 1;
            optionsProvider = function(self) {
                var self = self || {};
                self.options = {};
                self.get = function(name, initialValue) {
                    if (!self.options[name]) {
                        console.log("Called - " + name);
                        self.options[name] = ko.observableArray([initialValue]);
                        var requestHeader = '';
                        setTimeout(function() {
                            var aa = [{name: "plant 1" + i, selected: true}, {name: "palnt 2" + i, selected: false}];
                            self.options[name](aa);
                            i++;
                        }, 2000);
                    }
                    return self.options[name];
                };
                return self;
            };
            ViewModel = function() {
                var self = this;
                var k = 1;
                var ob = new optionsProvider(self);
                self.PlantSelected = ob.get("name" + k, '');
                self.fillNewSelect = function() {
                    self.PlantSelected.removeAll();
                    self.PlantSelected().push(ob.get("name" + k, ''));
                    k++;
                };
            };
            ko.applyBindings(new ViewModel());

HTML

<select class="n_imported_country"                     
            data-bind="options: PlantSelected,
                               optionsText :'name'   
            "
            >
    </select>
    <div data-bind="click: function(){
         $root.fillNewSelect();
    }">click to fill new select value</div>

I am a newbie to knockout, great welcome your answers.

Display Name
  • 4,502
  • 2
  • 47
  • 63

2 Answers2

1

I recommend the use of a promise library to handle the asynchronous Ajax load of new items. I've used jQuery's implementation in the sample below. Notice how optionsProvider no longer requires any dependency on the viewmodel.

var optionsProvider = function (name, initialValue) {
    return function () {
        return $.get("/target/url", {parameter: "value"})
        .fail(function () {
            console.log("request to get new items failed", arguments);
        });
    };
};

var ViewModel = function () {
    var self = this,
        k = 1,
        ob = optionsProvider("name" + k, '');

    self.PlantSelected = ko.observableArray([]);
    self.fillNewSelect = function () {
        ob().then(function (newData) {
            var p = self.PlantSelected;
            p.removeAll();
            p.push.apply(p, newData);
        });
    };

    // init
    self.fillNewSelect();
};
ko.applyBindings(new ViewModel());

The second change to mention is the way to push new objects into an array. .push() supports an argument list:

arr.push('a', 'b', 'c')

If you have an array of items you want to push (for example a JSON result), you would use .apply(), otherwise you would push the array itself as the first item:

arr.push.apply(arr, ['a', 'b', 'c']);

Observable arrays in knockout support the same usage.

Compare: http://jsfiddle.net/kspxa8as/6/

Tomalak
  • 332,285
  • 67
  • 532
  • 628
0

Try something like this the trick here is passing the instance of the observableArray to the function and get our job done

Viewmodel:

 var  ViewModel = function() {
        var self = this;
        var k = 1;
        var ob = new optionsProvider(self);
        self.PlantSelected = ko.observableArray(); //Declare it as observableArray
        ob.get("name" + k, '',self.PlantSelected) // call the function passing observableArray instance 
        self.fillNewSelect = function() 
        {
          self.PlantSelected.removeAll();
          ob.get("name", ''+ k,self.PlantSelected)
           k++;
        };
  };
 ko.applyBindings(new ViewModel());

function :

  var i = 1;
  optionsProvider = function(self) {
      var self = self || {};
        self.options = {};
          self.get = function(name, initialValue,instance) { //pass observableArray instance here
          if (!self.options[name] || self.options[name]()) {
            var requestHeader = '';

            setTimeout(function() {
            var aa = [{name: "plant 1" + i, selected: true}, 
                      {name: "palnt 2" + i, selected: false}];
                   instance(aa); // assign data to instance 
             },2000);
          i++;
       }
    return true;      
   };
  return self;
};

working sample here

super cool
  • 6,003
  • 2
  • 30
  • 63