简体   繁体   中英

How to know if an insertion was successfull in a MongoDB Collection with Meteor.JS (inside the Template)

The situation

Let's break this question down to a simple todo list of which the entries are listed in a \\li:

//main.html
<ul>
{{ #each listEntries }}
  <li class="item">
   {{ title }}
  </li>
{{ /each }}
</ul>

Serverside:

//main.js
TodoCollection = new Mongo.Collection('todo_collection');

Now I am calling manually from the console in the client:

TodoCollection.insert({title: 'My first entry'});

Up to this point everything's fine .

Now meteor.JS works asynchronously which means that the changes that are made in the client also have effect on the DOM right away without knowing if the database insertion was successfull or not. If not, the DOM Element will be removed again (so first meteor inserts the new <li> , then it removes it again if insertion failed).

How can you get the information from meteor that something comes actually from the database?

What I need:

//main.html
<ul>
{{ #each listEntries }}
  <li class="item">
   {{ title }}

   {{ #if isInDatabase }}
     - i am actually stored!
   {{ /if }}
  </li>
{{ /each }}
</ul>

You can use the callback of the insert method of the collection. The callback is called with the error ( null if there is none) and the object Id that was stored in the database

Below you can see the code to test this:

html :

<head>
  <title>simple</title>
</head>

<body>
  <h1>Welcome to Meteor!</h1>
  {{>test}}
</body>

<template name="test">
  <ul>
      {{#each item in list}}
      <li>{{item.name}}</li>
      {{/each}}
  </ul>
  {{#if insertResult}}
  <div class="insert_result">{{insertResult}}</div>
  {{/if}}
  {{#if insertError}}
  <div class="insert_error">{{insertError}}</div>
  {{/if}}
  <form>
      <input type="text" name="name" />
      <input type="submit" value="Add" />
  </form>
</template>

Javascript :

import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';

collection = new Mongo.Collection('collection');

if (Meteor.isClient) {
    Template.test.onCreated(function () {
        this.insertResult = new ReactiveVar();
        this.insertError = new ReactiveVar();
    });

    Template.test.helpers({
        list() {
            return collection.find();
        },
        insertResult() {
            return Template.instance().insertResult.get();
        },
    });

    Template.test.events({
        'submit form'(event, instance) {
            event.preventDefault();
            collection.insert({
                name: event.target.name.value
            },function(err,result) {
                if (err) {
                    instance.insertError.set(err);
                    instance.insertResult.set(null);
                } else {
                    instance.insertResult.set(result);
                    instance.insertError.set(null);
                }

            });
        },
    });
}

As you can see in the previous answer, it is quite cumbersome in Meteor to know what causes a reactive update.

I would suggest a different approach: Don't insert on the client. Make a Meteor.call() to a server method which does the insert, and then let the client update reactively. Then you are always sure that what you see on the screen is actually in the database.

I think I found the most trivial solution myself: Adding a hook on server-side that will add the date of creation with obj.onCreated = new Date(); helps identifying that it came from the server because this will not exist on the client.

  {{#each item}}
    {{ #if item.onCreated }}
      <li class="success-db">{{name}}</li>
    {{ else }}
      <li class="pending-db">{{name}}</li>
    {{ /if }}
  {{/each}}

(Please do not hesitate to improve this answer if you find it contradictory to how Meteor.JS works)

If you want to show the data which title exist then you can write the code like this.

<ul>
{{ #each listEntries }}
  <li class="item">
   {{ title }}

   {{ #if title }}
     - i am actually stored!
   {{ /if }}
  </li>
{{ /each }}
</ul>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM