Issue Angular-Meteor Meteor.publishComposite - meteor

When running helper brings values are stored in the variable verCandidatos.postulados.
Once I get me the information I need to get a document that is linked (using the function ng-init="candidato = la postulado.candidato()) wich runs on the helper from file: collection.js.
Sometimes the html shows the properties: {{candidato.nombre}}, {{candidato.apellidos}} and {{candidato.sexo}} correctly, and sometimes appear empty, why?
Is very strange, like a bug or something. How is possible that behavior?
The information is being obtained, because the ng-repeat works and shows elements.
Below is the publishComposite(), collection.js, html and js client
html client
my-app/imports/ui/components/vacantes/verCandidatos/ verCandidatos.html
<div ng-repeat="postulado in verCandidatos.postulados">
<div ng-init="candidato = postulado.candidato();">
{{candidato.nombre}}
{{candidato.apellidos}}
{{candidato.sexo}}
</div>
</div>
js in client
my-app/imports/ui/components/vacantes/verCandidatos/ verCandidatos.js
imports ...
class VerCandidatos {
constructor($scope, $reactive, $stateParams) {
'ngInject';
$reactive(this).attach($scope);
this.vacanteId = $stateParams.vacanteId;
this.subscribe('vacantes.candidatosOseleccionados', ()=> [{vacanteId: this.vacanteId}, {estado: 1}]);
this.helpers({
postulados (){
return Postulaciones.find();
}
});
}
}
collection.js
my-app/imports/api/postulaciones/ collection.js
imports...
export const Postulaciones = new Mongo.Collection('postulaciones');
Postulaciones.deny({...});
Postulaciones.helpers({
candidato(){
return Candidatos.findOne({_id: this.candidatoId});
}
});
publish.js:
my-app/imports/api/vacantes/server/ publish.js
imports...
if (Meteor.isServer) {
Meteor.publishComposite('vacantes.candidatosOseleccionados', function (vacanteId, estado) {
const selector = {$and: [estado, vacanteId]};
return {
find: function () {
return Postulaciones.find(selector);
},
children: [
{
find: function (postulacion) {
return Candidatos.find({_id: postulacion.candidatoId}, {
fields: {
nombre: 1,
apellidos: 1,
sexo: 1,
}
});
}
}
]
};
});
}
Any ideas?
- Thanks,

The ISSUE was in html
The solution was deteted ng-init and call directly the helpers inside collection.js, the other files (js in client, collection.js, publish.js) aren't modify.
The html file is as follows:
<div ng-repeat="postulado in verCandidatos.postulados">
{{postulado.candidato().nombre}}
{{postulado.candidato().apellidos}}
{{postulado.candidato().sexo}}
</div>
Thanks for read.
And I hope you will be useful.

Related

Meteor How to call global helper in template file?

I have created global helper in app/client/lib/global_helper.js
Template.registerHelper("getImages", id => {
if(id){
let user = Meteor.users.findOne({_id: id});
try {
if (user.profile.picture) {
return user.profile.picture;
} else {
return "http://api.adorable.io/avatars/150/"+id+".png";
}
}catch(e) {
return "http://api.adorable.io/avatars/150/"+id+".png";
}
}
});
and trying to call it in my html template
app/client/template/shared/sidebar/my_sidebar.html
<img src="{{getImages this._id}}" alt="User" class="profilepic">
But it's not working. Not getting what is issue.
It's working when i called it in other files
app/client/template/pages/dashboard/dashboard.html
If your console is working properly then you should try ES6 way as like id instead of _id: id see the below
let user = Meteor.users.findOne({ id });

Meteor - Tracker.nonreactive() is not removing reactivity from helper

I'm trying to make a Meteor helper non-reactive with this code:
let titleNonReactive;
Template.articleSubmission.onCreated(function () {
this.autorun(function() {
titleNonReactive = Template.currentData().title;
});
});
Template.articleSubmission.helpers({
titleNonreactive: function() {
return titleNonReactive;
}
});
However the resulting output is still reactive. If I save a new value in the background, it's automatically updated on the frontend where I'm displaying the result of this helper with {{ titleNonreactive }}.
How can I fix this?
This is likely caused by your Blaze data context (will need to see your Template code to confirm), but here's a possible solution that doesn't involve using Tracker.nonreactive. Since you want the value of titleNonreactive to not be reactive, you can just use a standard local / non-reactive variable to store a copy of the original reactive title. For example:
import { Template } from 'meteor/templating';
import { articles } from '/imports/api/articles/collection';
import './main.html';
let originalTitle;
Template.body.onCreated(function onCreated() {
this.autorun(() => {
const article = articles.findOne();
if (article && !originalTitle) {
originalTitle = article.title;
}
});
});
Template.body.helpers({
article() {
return articles.findOne();
},
titleNonreactive() {
return originalTitle;
}
});
Then in your Template:
<ul>
{{#with article}}
<li>Reactive Title: {{title}}</li>
<li>Non-Reactive Title: {{titleNonreactive}}</li>
{{/with}}
</ul>

Meteor.renderList alway end up in [elseFunc]

I'm new to Meteor.
Trying to render items from collection but Meteor.renderList(observable, docFunc, [elseFunc]) alway go to elseFunc.
this.ComponentViewOrdersFlow = Backbone.View.extend({
template: null,
initialize: function() {
var frag;
Template.ordersFlow.events = {
"click a": function(e) {
return App.router.aReplace(e);
}
};
this.template = Meteor.render(function() {
return Template.ordersFlow();
});
console.log(Colors);
frag = Meteor.renderList(
Colors.find(),
function(color) {
console.log(color);
},
function() {
console.log('else consdition');
}
);
},
render: function() {
this.$el.html(this.template);
return this;
}
});
Initially I thought that Collection is empty, but console.log(Colors) shows that there are items in collection. Moreover if I use Meteor.render(... -> Template.colors({colors: Colors.find()}) ) it renders template end show Collection items there.
Meteor version 0.6.6.3 (Windows 7, 64bit)
Mongo - connected to MongoLab
Thank you for any help.
Jev.
Can't really explain this well in the comments, so here is a very, very simple example of using the Meteor template engine. This is a 100% functional app, showcasing basic reactivity. Note that I never call render() or renderList() anywhere.
All this app does is show a button, that when clicked, adds a number to a list. The number is reactively added to the list, even though I never do anything to make that reactivity explicit. Meteor's templates are automatically reactive! Try it out - this is all of the code.
numbers.html:
<body>
{{> numberList}}
</body>
<template name="numberList">
<ul>
{{#each numbers}}
<li>{{number}}</li>
{{/each}}
</ul>
<button>Click Me</button>
</template>
numbers.js:
var Numbers = new Meteor.Collection("numbers");
if (Meteor.isClient) {
Template.numberList.numbers = function() {
return Numbers.find();
};
var idx = 0;
Template.numberList.events({
"click button": function() {
Numbers.insert({
number: idx
});
idx++;
}
});
}

Meteor - How to insert dynamically generated content into a collection?

I'm new to Meteor and barely understand any of it but let's say I have a collection called mycollection, declared way up top so it's available in both the client and server section:
mycollection = new Meteor.Collection('MyDumbCollection');
And then I have something like this:
if (Meteor.isClient) {
Deps.autorun(function() {
Meteor.subscribe('mycollectionSubscription');
});
Template.myshittytemplate.rendered = function() {
$("#heynow").prepend(shitfuck).dosomething();
godammit = thisfuckingthing;
//paraphrasing
mycollection.insert({thing1: thisfuckingthing});
};
}
if (Meteor.isServer) {
Meteor.publish('mycollectionSubscription', function () {
return mycollection.find();
});
};
And then in my template:
<template name="myshittytemplate">
<div id ="heynow">
{{#each mycollection}}
{{{thing1}}}
{{/each}}
</div>
</template>
What I'm trying to do is have the 'thisfuckingthing' html that's created in the #heynow div saved to the collection and published to everybody. If there's a way to make Meteor simply observe changes to the dom and save them, that's even better.
I do have autopublish uninstalled, if that makes a difference. Halp.
In client Template
Template.myshittytemplate.mycollection = function() {
return mycollection.find({}).fetch();
};
Template.myshittytemplate.rendered = function() {
$(function(){
$("#heynow").prepend(shitfuck).dosomething();
godammit = thisfuckingthing;
//paraphrasing
mycollection.insert({thing1: thisfuckingthing},function(err,_id){
if(err){
console.log(err);
return;
});
console.log(_id);
});
};
}
I needed this in the Client part:
Template.myshittytemplate.mycollection = function() {
return mycollection.find();
};
Hopes this helps somebody!

Possible bug when observing a cursor, when deleting from collection

I've run into an interesting possible bug, but in this case it may be caused by the lack of a function for me to use to delete a document when observing a collection. Or I am misusing observe... which could very well be the case!
Here is sample code that will reproduce the issue I'm having.
I'm using the devel branch as of this writing, so I'm not sure if this works in 0.3.5
observebug.html
<head>
<title>observebug</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
<h1>Example showing possible bug in Meteor wrt observe</h1>
<div>
<p>Try to delete a note. You will notice that it doesn't appear to get deleted. However, on the server, the delete did occur. Refresh the page to see that the delete did in fact occur.</p>
<h2>Notes:</h2>
<ul>
{{#each notes}}
{{> note_row}}
{{/each}}
</ul>
</div>
</template>
<template name="note_row">
<li>{{title}} <button name="delete">delete</button></li>
</template>
observebug.js
// CLIENT
if (Meteor.is_client) {
Notes = new Meteor.Collection("notes_collection");
Meteor.autosubscribe(function () {
Meteor.subscribe("notes_subscription");
});
Template.main.notes = function () {
return Notes.find();
};
Template.note_row.events = {
"click button[name='delete']": function (evt) {
Meteor.call("deleteNote", this._id, function (error, result) {
if (!error) {
console.log("Note deletion successful.");
} else {
console.log("Error when deleting note.");
}
});
}
};
}
// SERVER
if (Meteor.is_server) {
Notes = new Meteor.Collection("notes_collection");
Meteor.methods({
"deleteNote": function (note_id) {
try {
Notes.remove(note_id);
return true;
} catch (e) {
return false;
}
}
});
Meteor.publish("notes_subscription", function () {
var notes = Notes.find({}, {sort: {title: 1}});
var self = this;
// What we're doing here is basically making an exact duplicate
// of the notes collection. A possible use-case for this would be
// to actually make changes to the copied collection on the fly,
// such as adding new fields without affecting the original
// collection.
var upsertHandler = function (note, idx) {
note.some_new_field = 100;
self.set("notes_collection", note._id, note);
self.flush();
};
var handle = notes.observe({
added: upsertHandler,
changed: upsertHandler,
removed: function (note, idx) {
// As far as I can tell, unset won't remove the document,
// only attributes of the document. I don't think there's
// a method to handle actually removing a whole document?
self.unset("notes_collection", note._id);
self.flush();
}
});
self.onStop(function () {
handle.stop();
self.flush();
});
});
// Add example notes
Meteor.startup(function () {
if (Notes.find().count() === 0) {
Notes.insert({title: "Note #1"});
Notes.insert({title: "Note #2"});
Notes.insert({title: "Note #3"});
Notes.insert({title: "Note #4"});
Notes.insert({title: "Note #5"});
Notes.insert({title: "Note #6"});
}
});
}
What you'll be seeing
When you start this application up, you'll see 6 example "notes", each with a delete button. I suggest having your console open so you can see the console.logs. Click the delete button on any note. The note does get deleted, however this doesn't get reflected back up to the client.
I suspect the issue lies in how I'm leveraging observe to create a copy of the collection (which I can then manipulate without affecting the original collection). I feel like I need a function that deletes a whole document, not just some attributes (unset).
EDIT: See the example in action over at http://observebug.meteor.com/
So I've got it figured out. I did indeed need to use observe, and there is no Meteor bug on that end. Just a lack of understanding of what was involved in what I was trying to accomplish. Luckily I found a great starting point within the Meteor code itself and wrote an adjusted version of the _publishCursor function, which I've called publishModifiedCursor.
Here are the adjusted project templates and code:
observe.html
<head>
<title>observe</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
<h1>Example in trying to publish a modified copy of a collection</h1>
<div>
<h2>Notes:</h2>
<ul>
{{#each notes}}
{{> note_row}}
{{/each}}
</ul>
<p><button name="add">add note</button></p>
</div>
</template>
<template name="note_row">
<li>
<strong>Original title:</strong> <em>{{title}}</em><br />
<strong>Modified title:</strong> <em>{{__modified_title}}</em><br />
<button name="delete">delete</button>
</li>
</template>
observe.js
// CLIENT
if (Meteor.is_client) {
ModifiedNotes = new Meteor.Collection("modified_notes_collection");
Meteor.autosubscribe(function () {
Meteor.subscribe("modified_notes_subscription");
});
Template.main.notes = function () {
return ModifiedNotes.find();
};
Template.main.events = {
"click button[name='add']": function (evt) {
Meteor.call("addNote", function (error, result) {
if (!error) {
console.log("Note addition successful.");
} else {
console.log("Error when adding note.");
}
});
}
};
Template.note_row.events = {
"click button[name='delete']": function (evt) {
Meteor.call("deleteNote", this._id, function (error, result) {
if (!error) {
console.log("Note deletion successful.");
} else {
console.log("Error when deleting note.");
}
});
}
};
}
// SERVER
if (Meteor.is_server) {
Notes = new Meteor.Collection("notes_collection");
Meteor.methods({
"addNote": function () {
try {
Notes.insert({title: "Note #" + (Notes.find().count() + 1)});
return true;
} catch (e) {
return false;
}
},
"deleteNote": function (note_id) {
try {
Notes.remove(note_id);
return true;
} catch (e) {
return false;
}
}
});
Meteor.publish("modified_notes_subscription", function () {
// Pull up the original notes_collection
var notes = Notes.find({}, {sort: {title: 1}});
// Publish a near identical collection, with modifications
this.publishModifiedCursor(notes, "modified_notes_collection", function (note) {
note.__modified_title = getTitleModifiedByServer(note.title);
return note;
});
});
var getTitleModifiedByServer = function (title) {
return title + "!!!";
};
// Add example notes
Meteor.startup(function () {
if (Notes.find().count() === 0) {
Notes.insert({title: "Note #1"});
Notes.insert({title: "Note #2"});
Notes.insert({title: "Note #3"});
Notes.insert({title: "Note #4"});
Notes.insert({title: "Note #5"});
Notes.insert({title: "Note #6"});
}
});
_.extend(Meteor._LivedataSubscription.prototype, {
publishModifiedCursor: function (cursor, name, map_callback) {
var self = this;
var collection = name || cursor.collection_name;
var observe_handle = cursor.observe({
added: function (obj) {
obj = map_callback.call(self, obj);
self.set(collection, obj._id, obj);
self.flush();
},
changed: function (obj, old_idx, old_obj) {
var set = {};
obj = map_callback.call(self, obj);
_.each(obj, function (v, k) {
if (!_.isEqual(v, old_obj[k])) {
set[k] = v;
}
});
self.set(collection, obj._id, set);
var dead_keys = _.difference(_.keys(old_obj), _.keys(obj));
self.unset(collection, obj._id, dead_keys);
self.flush();
},
removed: function (old_obj, old_idx) {
old_obj = map_callback.call(self, old_obj);
self.unset(collection, old_obj._id, _.keys(old_obj));
self.flush();
}
});
self.complete();
self.flush();
self.onStop(_.bind(observe_handle.stop, observe_handle));
}
});
}
See it live over at http://observebug.meteor.com/. The final effect is underwhelming, since it's just a test involving adding/removing notes... but hey now it works!
Hope this helps someone else out in the future.
this.unset requires three parameters, the first and second one are correct; it however requires a third parameter to tell which attributes to unset. This is a bug in your code and not in Meteor.
However, note that when your callback is called tha the document is already deleted from the collection and that you are just working on a copy of the object. Exactly, Notes.find({}).count() reveals the remaining count at any point during your callback.
// I don't think there's
// a method to handle actually removing a whole document?
If you want two collections, create two collections. By only keeping one and trying to do all sorts of magic, you are calling functions that are not even meant to be doing what you want them to do. If you just create
Notes_copy = new Meteor.Collection("notes_collection_copy");
and use that to keep track of temporary notes, you won't run into any of the trouble you had now.

Resources