I have a set of objects called 'categories' which have posts in them that belong to that category. A user is able to 'follow' a category by clicking a button that takes the data within that category object, most importantly the posts puts them in a field within Meteor.users. As it stands, the user only gets the posts that were available at the when the user clicked the button.
How do i make it so that when they 'follow' a category, any new posts that come in later, after the click event has already been done, will automatically be pushed to their user data. In other words, how do make this process reactive?
client/categories.js
Template.CategoriesMain.events({
'click .toggle-category': function(e){
var ob = $(e.target).parent().find("div").text();
var id = $.makeArray( ob );
console.log(id);
e.preventDefault();
Meteor.call('addingCategory', id, function(error, user){ console.log(id)});
}
});
server/categories.js
Meteor.publish("userData", function () {
if (this.userId) {
return Meteor.users.find({_id: this.userId},
{fields: {'name': 1}});
} else {
this.ready();
}
});
could i do something with autorun? to the tune of this?
Template.CategoriesMain.events({
'click .toggle-category': function(e){
autorun(function() {
var ob = $(e.target).parent().find("div").text();
var id = $.makeArray( ob );
console.log(id);
e.preventDefault();
Meteor.call('addingCategory', id, function(error, user){ console.log(id)});
}
});
});
can't get it currently but try
Meteor.publish("userData", function () {
if (this.userId) {
return Meteor.users.find({_id: this.userId},
{fields: {'name': 1}});
} else {
return null;
}
this.ready();
});
Related
I'm using "Braintree - Dropin" here. Instance is created when page load and I have a dropdown to select "pay amount" after. I want to update value of instance (already created) when dropdown is changed.
var form = document.querySelector('#payment-form');
var client_token = "{{ Braintree\ClientToken::generate()}}";
var amount = document.getElementById("amount");
var amount_val = amount.options[amount.selectedIndex].value;
braintree.dropin.create({
authorization: client_token,
selector: '#bt-dropin',
applePay: {
displayName: 'My Store',
paymentRequest: {
total: {
label: 'My Store',
amount: amount_val
}
}
}
}, function (createErr, instance) {
if (createErr) {
console.log('Create Error', createErr);
return;
}
amount.addEventListener("change", function() {
console.log(amount.value);
// Where i'm trying to change amount
instance.updateConfiguration('applePay', 'paymentRequest', {
total: {
label: 'My Store',
amount: amount.value
}
});
});
form.addEventListener('submit', function (event) {
event.preventDefault();
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Request Payment Method Error', err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
According to "Dropin" documentation this should work. but it doesn't.
https://braintree.github.io/braintree-web-drop-in/docs/current/Dropin.html#updateConfiguration
I couldn't find a possible way to change instance after it is created. But I solved the problem by splitting process in to two parts. I made two steps to do the payment. In first page user will select amount from dropdown then click next button which submit selected amount into payment page. then on payment page this instance is created with amount already post from previous page. Hope this will help someone with a similar issue.
I tried to include a button (created from user event) on Sales order. Upon clicking it, Invoice will be generated. As soon as the button is hit, ther comes an error and invoice doesnt get generated. Can anyone help me with this?
//Client script
function pageInit() {
}
function csForButton(ctx) {
var rec = curr.get();
var customer = rec.getValue({ "fieldId": "customer" });
log.error({
title: 'customer',
details: customer
});
var scriptURL = url.resolveScript({
"scriptId": "customscript_button_task_sl",
"deploymentId": "customdeploy_button_task_sl"
});
console.log('scriptURL', scriptURL);
window.onbeforeunload = null;
window.open(scriptURL + '&id=' + rec.id);
}
return {
pageInit: pageInit,
csForButton: csForButton
};
//User Event Script
function beforeLoad(ctx) {
//if (context.type == context.UserEventType.VIEW) {
addbutton(ctx);
// }
}
function addbutton(ctx) {
try {
var rec = ctx.newRecord;//record object, now we can get its properties through it(e.g. fields)
var statusOfTrans = rec.getValue({ fieldId: 'status' });
log.error('statusOfTrans', statusOfTrans);
ctx.form.clientScriptFileId = "16474"
if (ctx.type == "view" && statusOfTrans == 'Pending Fulfillment') {
ctx.form.addButton({
id: 'custpage_make_invoice',
label: 'create invoice!',
functionName: 'csForButton'
});
}
}
catch (error) {
log.error('addbutton', error);
}
}
return {
beforeLoad: beforeLoad,
}
//Suitelet Script
function onRequest(ctx) {
try {
var req = ctx.request;
var res = ctx.response;
if (req.method == 'GET') {
var objRecord = rec.transform({
fromType: rec.Type.SALES_ORDER,
fromId: req.parameters.id,
toType: rec.Type.INVOICE,
isDynamic: true,
});
objRecord.save({
ignoreMandatoryFields: true
});
res.write({output: 'Invoice created'});
}
} catch (error) {
log.error('onRequest', error);
}
}
return {
'onRequest': onRequest
}
error (in suitelet):
{"type":"error.SuiteScriptError","name":"USER_ERROR","message":"You must enter at least one line item for this transaction.","stack":["anonymous(N/serverRecordService)","onRequest(/SuiteScripts/button SL.js:39)"],"cause":{"type":"internal error","code":"USER_ERROR","details":"You must enter at least one line item for this transaction.","userEvent":null,"stackTrace":["anonymous(N/serverRecordService)","onRequest(/SuiteScripts/button SL.js:39)"],"notifyOff":false},"id":"","notifyOff":false,"userFacing":false}
As Error says to include atleast 1 line but i wanted it to be generated automatically. I am new in suitescript and taking all the help from the documentation. Can anyone jst guide me what is wrong i m doing?
Thank u
You need the SO status to be Pending Billing. If the status of the SO is Pending Fulfillment, then no line items are ready to be invoiced.
If I try to add reviews or like a recipe I get an error Error invoking Method 'addReview': Internal server error [500] debug.js:41,even though it adds reviews and likes into databases and works fine but still gives me above error.
Source code Github
add_review.js
Template.add_review.events({
'submit .add-review':function(event){
event.preventDefault();
var rating = event.target.rating.value;
var review = event.target.review.value;
var recipeId = Router.current().data()._id;
Meteor.call('addReview',rating,review,recipeId);
}
});
Template.recipes.events({
"click [data-action='addLikes']": function (event) {
event.preventDefault();
var recipe = Recipes.findOne({_id: this._id});
Meteor.call('upvote',recipe)
}
});
client/methods.js
Meteor.methods({
addReview:function(rating,review,recipeId){
if(review!=""){
Reviews.insert({
rating:rating,
review:review,
recipeId:recipeId
});
Router.go('reviews',{_id:recipeId});
FlashMessages.sendSuccess('Review Added',{ autoHide: true, hideDelay: 2000 });
}
else{
FlashMessages.sendError('Review field is empty',{ autoHide: true, hideDelay: 3000 });
}
return false;
},
upvote:function(currentRecipe){
var user = Meteor.user();
if(!user){
FlashMessages.sendError("You need to login to like this recipe", {hideDelay: 1000});
}
if (currentRecipe) {
if (_.contains(currentRecipe.voters, Meteor.userId())) {
FlashMessages.sendError("You already liked this recipe", {hideDelay: 1000});
return false;
}
Recipes.update(currentRecipe._id, {$addToSet: {voters: Meteor.userId()}, $inc: {likes: 1}});
}
}
})
server/permissions.js
RecipesImages.allow({
insert: function(userId, doc) {
return true;
},
update: function(userId, doc, fieldNames, modifier) {
return true;
},
remove: function(userId, doc) {
return false;
},
download: function(userId,doc) {
return true;
},
fetch: null
});
Recipes.allow({
insert: function(userId, doc) {
return true;
},
update: function(userId, doc, fieldNames, modifier) {
return true;
}
});
Reviews.allow({
insert: function(userId, doc) {
return true;
},
update: function(userId, doc, fieldNames, modifier) {
return true;
}
});
It seems that you are trying to use methods where they are not needed and only make things harder. Isn't this all just client code? If so, you can just use functions:
add_review.js
Template.add_review.events({
'submit .add-review':function(event){
event.preventDefault();
var rating = event.target.rating.value;
var review = event.target.review.value;
var recipeId = Router.current().data()._id;
addReview(rating,review,recipeId);
}
});
Template.recipes.events({
"click [data-action='addLikes']": function (event) {
event.preventDefault();
var recipe = Recipes.findOne({_id: this._id});
upvote(recipe)
}
});
client/methods.js
addReview = function(rating,review,recipeId){
if(review!=""){
Reviews.insert({
rating:rating,
review:review,
recipeId:recipeId
});
Router.go('reviews',{_id:recipeId});
FlashMessages.sendSuccess('Review Added',{ autoHide: true, hideDelay: 2000 });
}
else{
FlashMessages.sendError('Review field is empty',{ autoHide: true, hideDelay: 3000 });
}
return false;
};
upvote = function(currentRecipe){
var user = Meteor.user();
if(!user){
FlashMessages.sendError("You need to login to like this recipe", {hideDelay: 1000});
}
if (currentRecipe) {
if (_.contains(currentRecipe.voters, Meteor.userId())) {
FlashMessages.sendError("You already liked this recipe", {hideDelay: 1000});
return false;
}
Recipes.update(currentRecipe._id, {$addToSet: {voters: Meteor.userId()}, $inc: {likes: 1}});
}
};
#Waqar First off, in your methods.js file, which as someone else has already told you should go in the /lib folder, you should have single quotes around your function name. I've re-written your code for Meteor.methods and for the Template.add-review.events below
client/templates/reviews/add_review.js (sorry, I put each template in a separate folder along with the js file for it)
Template.add_review.events({
'submit .add-review': function(event){
var rating = event.target.rating.value;
var review = event.target.review.value;
var recipeId = this._id;
var params = {
rating: rating,
review: review,
_id: recipeId
}
Meteor.call('addReview', params);
FlashMessages.sendSuccess('Review Added'); // and any other options you want to include
Router.go('reviews',{_id:recipeId});
return false;
}
});
/lib/methods.js
Meteor.methods({
'addReview': function(params){
Reviews.insert(params);
}
});
Give that a try and see if it works. Also, put your methods.js file in the /lib folder as Stephen suggested.
I have a backbone view that loads a model and some templates. When I submit the form in the edit template, backbone successfully sends a PUT request, just as it’s supposed to. On success, I navigate the user back to the view template.
However, if I navigate to the edit route again and submit the form, backbone sends two PUT requests. It then GETs the view template. If I navigate to the edit route a third time, backbone sends three PUT requests. The number of PUT requests keep incrementing every time I submit the form. Why might that be?
Here is my view:
// Filename views/users/edit.js
/*global define:false */
define([
'jquery',
'underscore',
'backbone',
'models/user/UserModel',
'text!templates/users/edit.html',
], function($, _, Backbone, UserModel, UserTemplate) {
var UserEdit = Backbone.View.extend({
el: '#page',
render: function (options) {
var that = this;
if (options.id) {
// modify existing user
var user = new UserModel({id: options.id});
user.fetch({
success: function (user) {
var template = _.template(UserTemplate, {user: user});
that.$el.animate({opacity: 0}, 180, function() {
that.$el.html(template).animate({opacity: 1}, 180);
});
}
});
} else {
// create new user
var template = _.template(UserTemplate, {user: null});
that.$el.animate({opacity: 0}, 180, function() {
that.$el.html(template).animate({opacity: 1}, 180);
});
}
},
events: {
'submit #create-user-form': 'createUser'
},
createUser: function (e) {
var postData = $(e.currentTarget).serializeObject();
var user = new UserModel();
user.save(postData, {
success: function (user, response) {
Backbone.history.navigate('#/users/view/' + response, {trigger: true, replace: true});
}
});
return false;
}
});
return UserEdit;
});
In my case, I could fix it by calling undelegateEvents() on the view in the success callback.
createUser: function (e) {
var postData = $(e.currentTarget).serializeObject(),
user = new UserModel(),
that = this;
user.save(postData, {
success: function (user, response) {
that.undelegateEvents();
Backbone.history.navigate('#/users/view/' + response, {trigger: true});
}
});
return false;
}
Thanks, #dbf.
I am trying to implement the .allow part of meteor in an application I'm building. Before introducing it a list was displaying comments a user entered, now the comments just flash up for a second and then disappear. The comments are still being added to the collection though.
Could anyone tell me what I'm doing wrong, I am very new to this.
Main js file:
if (Meteor.isClient) {
Meteor.startup(function () {
Meteor.subscribe("ques");
});
Template.compose.events({
'submit form': function (event) {
var $body = $('#que-body');
var $score = 1;
event.preventDefault();
Questions.insert({
body: $body.val(),
score: $score,
created_at: Date()
});
$body.val('');
}
});
Template.question.selected = function () {
return Session.equals("selected_question", this._id) ? "selected" : '';
};
Template.question.events({
'click': function () {
Session.set("selected_question", this._id);
}
});
Template.question.que = function(){
return Questions.findOne(Session.get("selected"));
};
// Deals with up-vote, down-vote, remove buttons
Template.list.events({
'click .icon-thumbs-up': function(event) {
Questions.update(Session.get("selected_question"), {$inc: {score: 1}});
},
'click .icon-thumbs-down': function(event) {
Questions.update(Session.get("selected_question"), {$inc: {score: -1}});
},
'click .icon-remove': function(event) {
Questions.remove(Session.get("selected_question"));
}
});
Template.list.questions = Questions.find({}, {sort: {score: -1, created_at: -1}});
}
if (Meteor.isServer) {
Meteor.startup(function () {
Meteor.publish("ques", function(){
return Questions.find({}, {
fields:{ }
})
});
});
}
The model.js file:
Questions = new Meteor.Collection("questions");
Questions.allow({
insert: function(userId, que){
return userId && que.owner === userId;
},
update: function(id, ques, fields, modifier){
return true;
},
remove: function(id, que){
return id && que.owner === id;
}
});
Do you mean the questions (you said comments?): Your Meteor.allow rule is basically something that says the question.owner is the current logged in user's _id. You need to insert an owner when you insert your question. This is the only way (que.owner === userId will return true):
Questions.insert({
owner: Meteor.userId(),
body: $body.val(),
score: $score,
created_at: Date()
});
Make sure you ensure that only logged in users have the chance to insert questions. Either by hiding the button or having a check just before everything is inserted too:
if(!Meteor.userId()) {
alert("You need to be logged in to post a question");
return;
}