Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reactive Template with compex object

Tags:

meteor

I want to render a reactive template based on this document:

Sprint: 
    WorkStories:
        Tasks

I know this can be done by making a Meteor collection for each "level," but that means the result is actually being stored as a seperate document in the database. I want to know if its possible to have one collection/document for Sprint, that has standard collection of WorkStories with a standard collection of Tasks each, rendered to a reactive template.

I've seen [Meteor.deps.Context][1], but I can't figure out how to wire it up (or even if it's the right tool), and none of the examples do anything like this.

I've also seen [this question][2], but he seems to be asking about connecting related-but-separate documents, not rendering a single document.

like image 670
Kyeotic Avatar asked Apr 24 '26 23:04

Kyeotic


1 Answers

Because database queries on collections are already reactive variables on the client, the below will render one Sprint document with nested WorkStories that has nested Tasks in a template:

HTML:

<head>
    <title>Sprints Example</title>
</head>

<body>
    {{> sprints }}
</body>

<template name="sprints">
  {{#each items}}
    <div>Name: {{name}}</div>
        {{#each this.WorkStories}}
            <div>{{name}}</div>
            {{#each this.Tasks}}
                <div>{{name}}</div>
            {{/each}}
        {{/each}}
  {{/each}}
</template>

Javascript:

Sprints = new Meteor.Collection("sprints");

if (Meteor.isClient) {
    Template.sprints.items = function () {
      return Sprints.find({});
  };
}

if (Meteor.isServer) {
    Meteor.startup(function () {
        if (Sprints.find().count() === 0) {
            Sprints.insert({ name: 'sprint1', WorkStories: [{ name: 'workStory1', Tasks: [{ name: 'task1' }, { name: 'task2' }, { name: 'task3' }] }, { name: 'workStory2', Tasks: [{ name: 'task1' }, { name: 'task2' }, { name: 'task3' }] }] });
        }
  });
}

UPDATE WITH ANSWER

Per @Paul-Young's comment below, the problem with my usage of $set was the lack of quotes in the update. Once the nested object renders in the Template, as of Meteor 0.5.3 you can update sub arrays simply:

Sprints.update(Sprints.findOne()._id, { $set: { "WorkStories.0.name": "updated_name1" } });

BACKGROUND INFO

This does load the initial object, but updating seems problematic. I was able to get the Template to rerender by calling the below in the console:

Sprints.update(Sprints.findOne()._id, { name: 'sprint777', WorkStories: [{ name: 'workStory1232', Tasks: [{ name: 'task221' }, { name: 'task2' }, { name: 'task3' }] }, { name: 'workStory2', Tasks: [{ name: 'task1' }, { name: 'task2' }, { name: 'task3' }] }] })

Which follows these rules, per the Meteor Docs:

But if a modifier doesn't contain any $-operators, then it is instead interpreted as a literal document, and completely replaces whatever was previously in the database. (Literal document modifiers are not currently supported by validated updates.

Of course, what you want is to use the $set style operators on nested documents and get the templates to re-render when their nested properties change without having to replace the entire document in the table. The 0.5.3 version of Meteor included the ability to search for sub-arrays:

Allow querying specific array elements (foo.1.bar).

I've tried to do the . sub array search and haven't been able to update the WorkStories subdocument of the original entity yet, so I posted a question in the google talk.

Hope this helps

like image 200
TimDog Avatar answered Apr 27 '26 08:04

TimDog



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!