在子对象中显示筛选列表的挖空 js.访问要过滤的父对象列表

Knockout js displaying a filtered list in a child object. Accessing the parent object list to filter

本文关键字:列表 对象 访问 js 过滤 显示 筛选      更新时间:2023-09-26

>我目前有一个学生列表和一个学校对象中的类列表。我希望每个类对象都能够根据类 id 属性显示筛选的学生列表。

我尝试通过自定义绑定访问父对象,但没有任何成功。

也许我看错了问题?我花了几天时间解决这个问题,无论我以哪种方式解决它,我总是需要访问父对象上的值。

有什么方法可以访问我需要的东西吗?我开始认为无法访问全局样式变量。

function School()
{
  var self = this;
  self.ClassVMs = ko.observableArray([]).indexed('Number');
  self.ChildVMs = ko.observableArray([]).indexed('Number');
}
function ClassVM(classId, text)
{
  var self = this;
  self.Number = ko.observable();
  self.Text =  ko.observable(text);
  self.ClassId = ko.observable(classId);
}
function ChildVM(classId, text)
{
  var self = this;
  self.Number = ko.observable();
  self.ClassId = ko.observable(classId);
  self.Text = ko.observable(text);
}

我对我的设置有一个小提琴。感谢任何和所有指导。谢谢

不需要全局变量来解决这个问题。淘汰赛已经$root$parent稍微超出你在foreach内的范围。此外,如果确实需要,您始终可以确保视图模型获得另一种类型的视图模型作为其依赖项。事实上,如果一个视图模型有一个子视图模型的列表,它已经有这样的依赖关系。

您需要考虑的是您的UI/UX会是什么样子。您是否设计视图模型以支持用户"查看"学生并让他/她注册课程的视图?还是应用程序用户正在查看课程并逐个添加学生?

这是一个变体,显示了两者的一点点:

function School(classes) {
  var self = this;
  self.classes = ko.observableArray(classes);
  self.students = ko.observableArray([]);
  self.enroll = function(child, someClass) {
    if (self.students().indexOf(child) < 0) {
      self.students.push(child);
    }
    if (someClass.students().indexOf(child) < 0) {
      someClass.students.push(child);
    }
  };
  self.enrollNewChild = function(someClass) {
    if (!!someClass.childToBeEnrolled()) {
      self.enroll(someClass.childToBeEnrolled(), someClass);
      someClass.childToBeEnrolled(null);
    }
  };
  self.enrollInClass = function(child) {
    if (!!child.classToBeEnrolledIn()) {
      self.enroll(child, child.classToBeEnrolledIn());
      child.classToBeEnrolledIn(null);
    }
  };
}
function Class(id, txt) {
  var self = this;
  self.id = ko.observable(id);
  self.txt = ko.observable(txt);
  self.students = ko.observableArray([]);
  self.studentsCsv = ko.computed(function() {
    return self.students().map(function(s) { return s.txt(); }).join(", ");
  });
  self.childToBeEnrolled = ko.observable(null);
}
function Child(id, txt) {
  var self = this;
  self.id = ko.observable(id);
  self.txt = ko.observable(txt);
  self.classToBeEnrolledIn = ko.observable(null);
}
var english = new Class(1, "English 1");
var math1 = new Class(2, "Mathematics 1");
var math2 = new Class(2, "Mathematics 2");
var john = new Child(1, "John Doe");
var mary = new Child(1, "Mary Roe");
var rick = new Child(1, "Rick Roll");
var marc = new Child(1, "Marcus Aurelius");
var school = new School([english, math1, math2]);
ko.applyBindings(school);
// Method 1:
school.enroll(john, english);
school.enroll(john, math2);
school.enroll(marc, english);
school.enroll(mary, math2);
school.enroll(mary, english);
school.enroll(rick, english);
school.enroll(rick, math1);
td { background-color: #eee; padding: 2px 10px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<h3>Classes:</h3>
<table>
  <tbody data-bind="foreach: classes">
    <tr>
      <td><span data-bind="text: txt"></span></td>
      <td><span data-bind="text: studentsCsv"></span></td>      
      <td>
        Add student
        <select data-bind="options: $root.students, value: childToBeEnrolled, optionsText: 'txt', optionsCaption: 'Choose...'"></select>
        <button data-bind="click: $root.enrollNewChild">enroll now</button>
      </td>
    </tr>
  </tbody>
</table>
<h3>School Students</h3>
<table>
  <tbody data-bind="foreach: students">
    <tr>
      <td><span data-bind="text: txt"></span></td>
      <td>
        Enroll in:
        <select data-bind="options: $root.classes, optionsText: 'txt', value: classToBeEnrolledIn, optionsCaption: 'Choose...'"></select>
        <button data-bind="click: $root.enrollInClass">enroll now</button>
      </td>
    </tr>
  </tbody>
</table>

不会直接回答您的问题("根据类 id 属性显示过滤的学生列表"),因为我认为这是一个 XY 问题,您最好尝试找到像上面这样的解决方案,其中您有适当的引用,而不必使用id和某种查找机制。

是的,我可以看到它如何被认为是一个 XY 问题。你们俩都以不同的方式看待它,这是一个很大的帮助。

我最初想要的方式看起来不可行。我的折衷方案是将计算添加到根视图模型并以这种方式显示列表。

function School()
{
    var self = this;
    self.ClassVMs = ko.observableArray([]).indexed('Number');
    self.ChildVMs = ko.observableArray([]).indexed('Number');
    self.DisplayClassId = ko.observable(1);
    self.Display = function(x)
    {
        console.log(x);
        self.DisplayClassId(x);
    }
 }
    var viewModel = new School();
    viewModel.filteredItems = ko.computed(function () {
    var filter = viewModel.DisplayClassId();
    if (!filter) { 
        return viewModel.ChildVMs();
    } else {
        var filtered = ko.utils.arrayFilter(viewModel.ChildVMs(), function (item) {
            return (item.ClassId() === filter);
        });
        return filtered;
    }
  })

小提琴供参考