knockout.js click in one viewmodel and based on that render other viewmodel

时间:2021-11-20 20:34:02
    <div data-bind="with: SimpleListModel">  
<div data-bind="foreach: parents">   
        <span data-bind="text: parentname"></span> 
    </div>
</div>

<div data-bind="with: SimpleListModel2">  
    <div data-bind="foreach: childrens">   
        <span data-bind="text: childname"></span>
    </div>
</div>

this is my viewmodel

这是我的viewmodel

var parentsdata= [
{ parentid:1, parentname: "Danny" },{parentid:2, parentname: "Peter" },{parentid:3, parentname: "shawn" }];

var childdata= [
{ parentid:1, childrens: [
    { childname: "child1"},
    { childname: "child2"}]
},
{ parentid:2, childrens: [
    { childname: "child1"},
    { childname: "child2"}]
}];

var SimpleListModel = function(parents) {
  var self= this;
 self.parents= ko.observableArray(parents);
};

var SimpleListModel2 = function(childrens) {
 var self= this;
 self.childrens= ko.observableArray(childrens);
};

var masterVM = (function () {
         var self = this;         
         self.SimpleListModel= new SimpleListModel(parentsdata);
          self.SimpleListModel1= new SimpleListModel1(parentsdata);

})();

ko.applyBindings(masterVM);

I want to make parentname clickable so that when i click my parentname it's childs are populated in no 2 viewmodel. how can i do that?

我想使父名可点击,以便当我点击我的父名时,它的子项将填充在2视图模型中。我怎样才能做到这一点?

2 个解决方案

#1


1  

i like the answer posted by @M. Ihsan above but there are few corrections.

我喜欢@M发布的答案。 Ihsan上面,但几乎没有更正。

instead of using a function to filter children every time you click on a parent, you can use ko.computed to do the job automatically. that way you can also able to change the parent dynamically and your two Parent and Child models stays untouched.

而不是每次单击父项时使用函数来过滤子项,您可以使用ko.computed自动执行作业。这样你就可以动态地改变父亲,你的两个父子模型保持不变。

var parentsdata = [{ parentid: 1, parentname: "Danny" }, { parentid: 2, parentname: "Peter" }, { parentid: 3, parentname: "shawn" }];

var childdata = [{ parentid: 1, childrens: [{ childname: "DannyChild1" }, { childname: "DannyChild2" } ] }, { parentid: 2, childrens: [{ childname: "PeterChild1" }, { childname: "PeterChild2" } ] } ];

var SimpleListModel = function(parents) {
  var self = this;
  self.parents = ko.observableArray(parents);
};

var SimpleListModel2 = function(childrens) {
  var self = this;
  self.childrens = ko.observableArray(childrens);
};

var masterVM = (function() {
  var self = this;
  self.SimpleListModel = new SimpleListModel(parentsdata);
  self.SimpleListModel2 = new SimpleListModel2(childdata);
  self.selectedParent = ko.observable(); // holds selected parent
  self.ParentChildrens = ko.computed(function() {
    return ko.utils.arrayFilter(self.SimpleListModel2.childrens(), function(child) {
      return child.parentid == self.selectedParent();
    })[0];
  });
  self.parentClick = function(data) {
    self.selectedParent(data.parentid);
  }
})();
ko.applyBindings(masterVM);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="with: SimpleListModel">
  <div data-bind="foreach: parents">
    <span data-bind="text: parentname, click: parentClick"></span>
  </div>
</div>

<div data-bind="with: ParentChildrens">
  <div data-bind="foreach: childrens">
    <span data-bind="text: childname"></span>
  </div>
</div>

#2


1  

First of all, you don't have SampleListViewModel1 there. You need to change it to SampleListViewModel2 then pass childdata during initialization to that object instead of parentdata.

首先,你没有SampleListViewModel1。您需要将其更改为SampleListViewModel2,然后在初始化期间将childdata传递给该对象而不是parentdata。

Then you can create a function in SampleListViewModel1 which will pass the selected parent to parent object (masterVM). Then in masterVM, try to get children from the selected parent and store it in an observable object. In the view you just need to show this observable object.

然后,您可以在SampleListViewModel1中创建一个函数,该函数将所选父项传递给父对象(masterVM)。然后在masterVM中,尝试从所选父项中获取子项并将其存储在可观察对象中。在视图中,您只需要显示此可观察对象。

var parentsdata = [
  { parentid:1, parentname: "Danny" },
  {parentid:2, parentname: "Peter" },
  {parentid:3, parentname: "shawn" }
];

var childdata = [
  { parentid:1, childrens: [
    { childname: "child1 of parent1"},
    { childname: "child2 of parent1"}]
  },
  { parentid:2, childrens: [
    { childname: "child1 of parent2"},
    { childname: "child2 of parent2"}]
  }
];

var SimpleListModel = function(parents, parentObject) {
  var self = this;

  // this is used to get the reference to parent object (masterVM)
  self.parentObject = parentObject;

  self.parents = ko.observableArray(parents);

  // call this function on click and trigger the parent function which will do the filtration
  self.selectParent = function(parent) {
    self.parentObject.selectParent(parent);
   }
};

var SimpleListModel2 = function(childrens) {
  var self = this;
  self.childrens = ko.observableArray(childrens);
};

function masterVM() {
  var self = this;         
 
  // pass its own object during initialization
  self.SimpleListModel = new SimpleListModel(parentsdata, self);

  self.SimpleListModel2 = new SimpleListModel2(childdata);

  // store children of the selected parent
  self.childForSelectedParent = ko.observable(null);

  // get the children of the selected parent
  self.selectParent = function(parent) {
    var children = ko.utils.arrayFirst(self.SimpleListModel2.childrens(), function(children) {
        return children.parentid === parent.parentid;
    });
    if(children)
      self.childForSelectedParent(new SimpleListModel2(children.childrens));
    else
      self.childForSelectedParent(null);
  };
}

ko.applyBindings(new masterVM());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div>Click on any of the name</div>

<div data-bind="with: SimpleListModel">  
  <div data-bind="foreach: parents">   
    <span data-bind="text: parentname, click: $parent.selectParent"></span> 
  </div>
</div>

<div data-bind="with: childForSelectedParent">  
  <div data-bind="foreach: childrens">   
    <span data-bind="text: childname"></span>
  </div>
</div>

#1


1  

i like the answer posted by @M. Ihsan above but there are few corrections.

我喜欢@M发布的答案。 Ihsan上面,但几乎没有更正。

instead of using a function to filter children every time you click on a parent, you can use ko.computed to do the job automatically. that way you can also able to change the parent dynamically and your two Parent and Child models stays untouched.

而不是每次单击父项时使用函数来过滤子项,您可以使用ko.computed自动执行作业。这样你就可以动态地改变父亲,你的两个父子模型保持不变。

var parentsdata = [{ parentid: 1, parentname: "Danny" }, { parentid: 2, parentname: "Peter" }, { parentid: 3, parentname: "shawn" }];

var childdata = [{ parentid: 1, childrens: [{ childname: "DannyChild1" }, { childname: "DannyChild2" } ] }, { parentid: 2, childrens: [{ childname: "PeterChild1" }, { childname: "PeterChild2" } ] } ];

var SimpleListModel = function(parents) {
  var self = this;
  self.parents = ko.observableArray(parents);
};

var SimpleListModel2 = function(childrens) {
  var self = this;
  self.childrens = ko.observableArray(childrens);
};

var masterVM = (function() {
  var self = this;
  self.SimpleListModel = new SimpleListModel(parentsdata);
  self.SimpleListModel2 = new SimpleListModel2(childdata);
  self.selectedParent = ko.observable(); // holds selected parent
  self.ParentChildrens = ko.computed(function() {
    return ko.utils.arrayFilter(self.SimpleListModel2.childrens(), function(child) {
      return child.parentid == self.selectedParent();
    })[0];
  });
  self.parentClick = function(data) {
    self.selectedParent(data.parentid);
  }
})();
ko.applyBindings(masterVM);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="with: SimpleListModel">
  <div data-bind="foreach: parents">
    <span data-bind="text: parentname, click: parentClick"></span>
  </div>
</div>

<div data-bind="with: ParentChildrens">
  <div data-bind="foreach: childrens">
    <span data-bind="text: childname"></span>
  </div>
</div>

#2


1  

First of all, you don't have SampleListViewModel1 there. You need to change it to SampleListViewModel2 then pass childdata during initialization to that object instead of parentdata.

首先,你没有SampleListViewModel1。您需要将其更改为SampleListViewModel2,然后在初始化期间将childdata传递给该对象而不是parentdata。

Then you can create a function in SampleListViewModel1 which will pass the selected parent to parent object (masterVM). Then in masterVM, try to get children from the selected parent and store it in an observable object. In the view you just need to show this observable object.

然后,您可以在SampleListViewModel1中创建一个函数,该函数将所选父项传递给父对象(masterVM)。然后在masterVM中,尝试从所选父项中获取子项并将其存储在可观察对象中。在视图中,您只需要显示此可观察对象。

var parentsdata = [
  { parentid:1, parentname: "Danny" },
  {parentid:2, parentname: "Peter" },
  {parentid:3, parentname: "shawn" }
];

var childdata = [
  { parentid:1, childrens: [
    { childname: "child1 of parent1"},
    { childname: "child2 of parent1"}]
  },
  { parentid:2, childrens: [
    { childname: "child1 of parent2"},
    { childname: "child2 of parent2"}]
  }
];

var SimpleListModel = function(parents, parentObject) {
  var self = this;

  // this is used to get the reference to parent object (masterVM)
  self.parentObject = parentObject;

  self.parents = ko.observableArray(parents);

  // call this function on click and trigger the parent function which will do the filtration
  self.selectParent = function(parent) {
    self.parentObject.selectParent(parent);
   }
};

var SimpleListModel2 = function(childrens) {
  var self = this;
  self.childrens = ko.observableArray(childrens);
};

function masterVM() {
  var self = this;         
 
  // pass its own object during initialization
  self.SimpleListModel = new SimpleListModel(parentsdata, self);

  self.SimpleListModel2 = new SimpleListModel2(childdata);

  // store children of the selected parent
  self.childForSelectedParent = ko.observable(null);

  // get the children of the selected parent
  self.selectParent = function(parent) {
    var children = ko.utils.arrayFirst(self.SimpleListModel2.childrens(), function(children) {
        return children.parentid === parent.parentid;
    });
    if(children)
      self.childForSelectedParent(new SimpleListModel2(children.childrens));
    else
      self.childForSelectedParent(null);
  };
}

ko.applyBindings(new masterVM());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div>Click on any of the name</div>

<div data-bind="with: SimpleListModel">  
  <div data-bind="foreach: parents">   
    <span data-bind="text: parentname, click: $parent.selectParent"></span> 
  </div>
</div>

<div data-bind="with: childForSelectedParent">  
  <div data-bind="foreach: childrens">   
    <span data-bind="text: childname"></span>
  </div>
</div>