在非规范化数据结构列表中呈现每个孩子的信息 [英] Rendering information of each child in a list of a denormalized data structure

查看:23
本文介绍了在非规范化数据结构列表中呈现每个孩子的信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设有一些students的数据,这些数据属于不同学校的班级(groups):

<代码>{学生们": {亚历克斯":{"firstName": "热吉娜",等级":2,"lastName": "idk",...},鲍比":{ ... },克里斯" : { ... },...},学校":{春田":{"name" : "斯普林菲尔德小学","location" : "123 Main St",...},"quahog" : { ... },"锡安" : { ... },...},团体": {一" : {成员":{alexa":真的,鲍比":真的,克里斯":真的},学校" : {春田":真的},名称":数学课"},二" : {成员":{巴特":真的,丽莎":真的,梅格":真的,...},学校" : {quahog":真的},名称":艺术班"},三" : { ... },四":{ ... },...}}

据我所知,这是以平面方式构建数据的正确方法.如果这不正确,请告诉我.我在每个项目上都保留了相关列表,因此每个班级都需要一个名册(members),如果我也遇到学生在多个班级(group) 或学校,那些需要他们参加的课程和学校的列表.

现在在 HTML 中,我们需要有一个视图来显示所有学校班级(groups)和每个班级的学生以及同一视图中的学生带有嵌套的 ng-repeat:

//获取所有组,并一一展示<div ng-repeat="分组">//这有效 - 我如何获得它关联的学校?//??{{group.name}} - {{group 的学校名称}}//开始一个表<表格><头><tr><th>学生姓名</th><th>Grade</th>... </thead>//获取每组的学生,并一一展示//??<tr ng-repeat="student in groups.members"><td>{{student.name}}</td><td>{{student.grade}}</td>...</tr></tbody>

在控制器中:

angular.module('sofDataViewerApp').controller('dataTableController', function ($scope, $firebaseObject, $firebaseArray) {//这将获取我们所有的组.它还允许 `group.memebers` 渲染适当数量的 ``,因为它知道它有 N 个学生.var groupsRef = new Firebase("https://sof-data.firebaseio.com/studyGroups");$scope.groups = $firebaseArray(groupsRef);//这将给所有学生.如何让模板的group.members"成为每个合适的学生?var studentRef = new Firebase("https://sof-data.firebaseio.com/students");$scope.allStudents = $firebaseArray(studentsRef);});

问题:
如何让 HTML 模板正确迭代 groups' members 并且我可以访问每个 student 的所有数据(例如作为他们的 firstNamegrade)?(我假设它可能在控制器和 HTML 中包含更好的代码)

PLNKR:http://plnkr.co/edit/uAn1Ky9v5NHHDFPs2c6S?p=preview(如果您知道如何在 plnkr 中注入 Firebase 和 angularFire,那么它应该可以工作,但是尽管包含了它们的 CDN,我仍然无法弄清楚...)

我能理解的最接近的解释是在这个页面 由 Firebase 提供,他们建议使用 LINK_ID,但这并没有按照他们的意思进行描述,尤其是因为他们谈到不按 id 搜索.就我而言,link 将与 group 同义,而 comment 将是 student.

 var commentsRef = new Firebase("https://awesome.firebaseio-demo.com/comments");var linkRef = new Firebase("https://awesome.firebaseio-demo.com/links");var linkCommentsRef = linkRef.child(LINK_ID).child("comments");linkCommentsRef.on(child_ added",函数(快照){评论Ref.child(snap.key()).once("value", function() {//在链接页面上呈现评论.});});

解决方案

您似乎正在尝试加入多个表".使用 AngularFire 做到这一点的最佳方法是扩展 $firebaseArray (文档链接).有了这个,您可以在添加(或修改)每个子项时从其他位置加载其他数据.

另见加藤的这个答案显示扩展数组(尽管用于不同的用例).

最后,您可以考虑将每个屏幕所需的数据复制到该屏幕的列表中.虽然 Firebase 检索连接数据的速度非常快(它保持开放的连接并可以管道化多个请求),但如果您需要执行更少的请求来获取数据,它总是会更快.

一个例子是,如果你想显示一个组中的成员列表:

组":{一" : {成员":{"alexa" : "热吉娜",鲍比":罗伯特",克里斯":基督徒"...

因此,我们实际上在这里存储了每个成员的名字,而不是仅仅存储 true.这允许我们通过一次读取操作获取所有数据以显示组成员:

ref.child('group/one/members').on('value'...

然后当用户点击其中一个群组成员时,我们会转到该群组成员的页面并从 /students/$studentid 加载数据,并且可能拥有他们所在的群组那里也有一部分(以及这些组的名称)..

Let say there is some data of students that are in classes (groups) of different schools:

{
  "students": {
    "alexa" : {
      "firstName" : "ReJina",
      "grade" : 2,
      "lastName" : "idk",
      ...
    },
    "bobby" : { ... },
    "chris" : { ... },
    ...
  },
  "schools": {
    "springfield" : {
      "name" : "Springfield Elementary",
      "location" : "123 Main St",
      ...
    },
    "quahog" : { ... },
    "zion" : { ... },
    ...
  },
  "group": {
    "one" : {
      "members" : {
        "alexa" : true,
        "bobby" : true,
        "chris" : true
      },
      "school" : {
        "springfield" : true
      },
      "name" : "Math Class"
    },
    "two" : {
      "members" : {
        "bart" : true,
        "lisa" : true,
        "meg" : true,
        ...
      },
      "school" : {
        "quahog" : true
      },
      "name" : "Art Class"
    },
    "three" : { ... },
    "four" : { ... },
    ...
  }
}

To my knowledge this is the proper way of structuring data in a flat way. Please let me know if this is incorrect. I keep the associated lists on each item, so each class needs a roster (members) and if I also had the situation where a student was in more than one class (group) or school, those would need lists of classes and schools they attend.

Now in the HTML we need to have a view that shows all of the schools classes (groups) and the students in each class and the students in the same view with a nested ng-repeat:

<div id="data-table-div" class="col-md-6">
  // Get all the groups, and show them one by one
  <div ng-repeat="group in groups">
    // This works  -  How do I get the school it is associated to?
    //                ??
    {{group.name}} - {{group's school's name}}

    //Start a table
    <table>
      <thead> <tr> <th>Student Name</th> <th>Grade</th> ... </thead>
      <tbody>
        // Get the students in each group, and show them one by one
        //                        ??
        <tr ng-repeat="student in groups.members">
          <td>{{student.name}}</td> <td>{{student.grade}}</td> ...
        </tr>
      </tbody>
    </table>
  </div>
</div>

And in the controller :

angular.module('sofDataViewerApp')
  .controller('dataTableController', function ($scope, $firebaseObject, $firebaseArray) {
    // This gets all of our groups.  It also allows `group.memebers` to render the appropriate number of `<tr>`s as it knows it has N students.
    var groupsRef = new Firebase("https://sof-data.firebaseio.com/studyGroups");
    $scope.groups = $firebaseArray(groupsRef);

    // This will give all the students. How do I get just the template's `group.members` to be each appropriate student?
    var studentsRef = new Firebase("https://sof-data.firebaseio.com/students");
    $scope.allStudents = $firebaseArray(studentsRef);
  });

Question:
How do I get the HTML template to properly iterate over the groups' members and I have access to all of the data of each student (such as their firstName and grade)? (I am assuming it may involve better code in the controller and possibly in the HTML)

PLNKR: http://plnkr.co/edit/uAn1Ky9v5NHHDFPs2c6S?p=preview (If you know how to inject Firebase and angularFire in the plnkr, then it should work, but I still can't figure that out despite including the CDN of them...)

The closest explanation I can understand is on this page by Firebase, they suggest using a LINK_ID, but it is not described as what they mean, esp since they talk about not searching by id. In my case, a link would be synonymous with group and a comment would be a student.

    var commentsRef = new Firebase("https://awesome.firebaseio-demo.com/comments");
    var linkRef = new Firebase("https://awesome.firebaseio-demo.com/links");
    var linkCommentsRef = linkRef.child(LINK_ID).child("comments");
    linkCommentsRef.on("child_added", function(snap) {
      commentsRef.child(snap.key()).once("value", function() {
        // Render the comment on the link page.
      });
    });

解决方案

It looks like you're trying to join multiple "tables". The best way to do that with AngularFire is by extending $firebaseArray (link to docs). With this you can load the additional data from the other locations as each child get added (or is modified).

Also see this answer from Kato that show extending an array (although for a different use-case).

Finally you can consider duplicating the data that is necessary for each screen into the list for that screen. While Firebase is pretty fast to retrieve joined data (it keeps an open connection and can pipeline multiple requests), it will always be faster if you have to do fewer requests to get the data.

An example of this would be if you want to display a list of the members in a group:

"group": {
    "one" : {
      "members" : {
        "alexa" : "ReJina",
        "bobby" : "Robert",
        "chris" : "Christian"
        ...

So instead of just storing true, we actually store the first name of each member here. This allows us to get all the data to show the group members with a single read operation:

ref.child('group/one/members').on('value'...

Then when the user clicks on one of the group members, we'd go to that group member's page and load the data from /students/$studentid and possible have the groups that they're part of (and the names of those groups) under there too..

这篇关于在非规范化数据结构列表中呈现每个孩子的信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆