Database entry not created in autoform meteor - meteor

I have implemented the following code from insert autoform
Schemas = {};
Template.registerHelper("Schemas", Schemas);
Schemas.Person = new SimpleSchema({
firstName: {
type: String,
index: 1,
unique: true
},
lastName: {
type: String,
optional: true
},
age: {
type: Number,
optional: true
}
});
var Collections = {};
Template.registerHelper("Collections", Collections);
People = Collections.People = new Mongo.Collection("People");
People.attachSchema(Schemas.Person);
Meteor.publish(null, function () {
return People.find();
});
People.allow({
insert: function () {
return true;
},
remove: function () {
return true;
}
});
{{#autoForm id="afInsertDemo" type="insert" collection=Collections.People}}
<div class="form-group {{#if afFieldIsInvalid name='firstName'}}has-error{{/if}}">
<label class="control-label">{{afFieldLabelText name='firstName'}}</label>
{{> afFieldInput name='firstName'}}
{{#if afFieldIsInvalid name='firstName'}}
<span class="help-block">{{{afFieldMessage name='firstName'}}}</span>
{{/if}}
</div>
<div class="form-group {{#if afFieldIsInvalid name='lastName'}}has-error{{/if}}">
<label class="control-label">{{afFieldLabelText name='lastName'}}</label>
{{> afFieldInput name='lastName'}}
{{#if afFieldIsInvalid name='lastName'}}
<span class="help-block">{{{afFieldMessage name='lastName'}}}</span>
{{/if}}
</div>
<div class="form-group {{#if afFieldIsInvalid name='age'}}has-error{{/if}}">
<label class="control-label">{{afFieldLabelText name='age'}}</label>
{{> afFieldInput name='age'}}
{{#if afFieldIsInvalid name='age'}}
<span class="help-block">{{{afFieldMessage name='age'}}}</span>
{{/if}}
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Add Person</button>
<button type="reset" class="btn btn-default">Reset Form</button>
</div>
{{/autoForm}}
Database entries are not being created, where am I going wrong.

Added this to 2_collections.js in common folder and it works fine.
People.allow({
insert: function () {
return true;
},
remove: function () {
return true;
}

Related

State variables becoming undefined when calling vuex action

Error Message:Error: Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field articleName)
I am trying to add the variables from my form to my Firebase Cloud Firestore database. I use vuex for global state management. When I pass the variables from my CreateSale component to sale->state they get defined. But when I call the action createSale when submitting the form, the state variables are undefined. Everything should be setup properly. I registered Vuex aswell as configured firebase.
sale.js (vuex module)
createSale(state, getters) {
console.log(state.articleName) //undefined
db.collection('clothes').add({
articleName: state.articleName,
description: state.description,
brand: state.brand,
price: state.price,
imagesRefs: getters.fileRefs
}).then(docRef => {
for (var i = 0; i < state.files.length; i++) {
}
this.$router.push('/')
}).catch(error => alert(error.message))
}
CreateSale.vue
template:
<div class="container" id="createSale">
<form #submit.prevent="createSale" class="col s12">
<div class="row">
<div class="input-field col s12">
<input type="text" v-model="articleName" v-on:change="setArticleName(articleName)" required>
<label>Article Name</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input type="text" v-model="description" v-on:change="setDescription(description)" required>
<label>Description</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input type="text" v-model="brand" v-on:change="setBrand(brand)" required>
<label>Brand</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input style="padding-top: 16px;" type="number" v-model="price" v-on:change="setPrice(price)" required>
<label>Price</label>
</div>
</div>
<UploadFile />
<button type="submit" class="btn btn-success">Submit</button>
<router-link to="/" class="btn grey">Cancel</router-link>
</form>
script:
export default {
name: 'createSale',
components: {
UploadFile
},
data() {
return {
articleName: '',
description: '',
brand: '',
price: ''
}
},
methods: {
...mapMutations('sale', [
'setArticleName',
'setDescription',
'setBrand',
'setPrice'
]),
...mapActions('sale', {
createSale: 'createSale',
console: 'console'
})
}
Your action need to be
createSale({state, getters}) {
console.log(state.articleName) //undefined
db.collection('clothes').add({
articleName: state.articleName,
description: state.description,
brand: state.brand,
price: state.price,
imagesRefs: getters.fileRefs
}).then(docRef => {
for (var i = 0; i < state.files.length; i++) {
}
this.$router.push('/')
}).catch(error => alert(error.message))
}
The first parameter which is passed to action is context object, you need to get state and getters from this context object.
Example from vuex website:

Passing amount from user to braintree server

This Meteor code uses patrickml:braintree, since I do not have access to the braintree submit event in order to send a price to the server for processing.
How can I pass an $$ amount from a html element on the page where the client is clicking to the server?
//client
Template.account.onRendered(function () { //6a
Meteor.call('getClientToken', function (error, clientToken) {
if (!error) {
braintree.setup(clientToken, "dropin", {
container: "payment-form",
onPaymentMethodReceived: function (response) {
var nonce = response.nonce;
Meteor.call('btCreateCustomer', function(error) {
if (error) {
throw new Meteor.Error('customer-creation-failed');
} else {
Meteor.call('createTransaction', nonce, function (error) {
if (error) {
throw new Meteor.Error('transaction-creation-failed');
}
});
}
});
}
});
}
});
});
<template name="account">
<div id="account">
<p>Select invoice period:</p>
<select class={{this.class}} data-id={{_id}} name={{name}}>
{{#each values}}
<option class={{class}} selected={{selected}} name={{name}} value={{value}}>{{{label}}}</option>
{{/each}}
</select>
<br><br>
<form role="form">
<div class="row">
<div class="col-md-6 col-xs-12">
<div id="payment-form"></div>
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
</div>
</template>

meteor: searching data in collection

I have created search code, but the values cannot display. Can anyone help me?
This my code:
<template name="search">
<form >
<input type="text" id="categories" />
<button>Search</button>
</form>
<hr/>
<h3></h3>
<ol>
{{#each profil}}
<li>{{brand}}</li>
{{/each}}
</ol>
Template.search.events({
"submit ": function (e) {
e.preventDefault();
Session.set("categories", $("#categories").val());
}
});
Template.search.helpers({
profil: function() {
return Profil.find({
categories: Session.get('categories'),
});
}
});
I'm not sure how to code in publish (server).
Try this :
Put this in search.html
<template name="search">
<form id="searchForm">
<input type="text" id="categories" />
<button>Search</button>
</form>
<hr/>
<ol>
{{#each profil}}
<li>{{brand}}</li>
{{/each}}
</ol>
</template>
This in search.js :
Template.search.events({
"submit #searchForm": function (e) {
e.preventDefault();
Session.set("categories", e.target.text.value);
}
});
Template.search.helpers({
profil: function() {
return Profil.find({
categories: Session.get('categories'),
});
}
});
And make sure that "autopublish" package is added. This would do the trick!

Meteor aldeed:autoform custom arrayField template not working

I've looked for tutorials about AutoForm's custom field templates but I'm not sure where I'm going wrong with mine. If anyone has any suggestions it would be greatly appreciated.
My Schema: One field is an Array of Objects.
guests: {
type: Array,
minCount: 1,
maxCount: 10,
label: "Guests in Party"
},
"guests.$": {
type: Object,
label: "Guest Object"
},
"guests.$.firstName": {
type: String,
label: "First Name"
},
"guests.$.lastName": {
type: String,
label: "Last Name"
}
Template Code:
<template name='afArrayField_guestsObjectField'>
{{#afEachArrayItem name="guests" minCount="this.atts.minCount" maxCount="this.atts.maxCount"}}
<div class="form-group">
<label class="control-label col-sm-2">Guest</label>
{{> afObjectField name="this.name" label="false" template='customObjectField'}}
<div class="col-sm-2">
{{#if afArrayFieldHasLessThanMaximum name="guests"}}
<button type="button" class="btn btn-primary autoform-add-item" data-autoform-field="{{guests}}" data-autoform-minCount="{{this.atts.minCount}}" data-autoform-maxCount="{{this.atts.maxCount}}"><span class="glyphicon glyphicon-plus"></span></button>
{{/if}}
{{#if afArrayFieldHasMoreThanMinimum name="guests"}}
<button type="button" class="btn btn-primary autoform-remove-item pull-left"><span class="glyphicon glyphicon-minus"></span></button>
{{/if}}
</div>
</div>
{{/afEachArrayItem}}
</template>
<template name="afObjectField_customObjectField">
<div class="col-sm-4">
{{> afFieldInput name="this.firstName" class="form-control" placeholder="First Name"}}
{{#if afFieldIsInvalid name='this.firstName'}}
<span class="help-block">{{{afFieldMessage name='this.firstName'}}}</span>
{{/if}}
</div>
<div class="col-sm-4">
{{> afFieldInput name="this.lastName" class="form-control" placeholder="Last Name"}}
{{#if afFieldIsInvalid name='this.lastName'}}
<span class="help-block">{{{afFieldMessage name='this.lastName'}}}</span>
{{/if}}
</div>
</template>
The problem I am having is that the plus buttons shows up after the firstName and lastName field how I want it to, but when I press it another guest object (in the form) does not generate. Any thoughts?

Meteor JS: list is populating with Collection results

Here is my template:
<template name="list">
<div class="col-md-12">
{{#if jobsLoaded}}
<ul class="list-group" id="jobs">
{{#each jobs}}
<li>
<span class="pull-right">{{address}}</span>
<span id="jobTitle">{{{ jobUrl url title }}}</span>
<span id="company">{{company}}</span>
<span id="date"><em>{{dateacquired}}</em></span>
</li>
{{/each}}
</ul>
{{else}}
{{> spinner}}
{{/if}}
</div>
{{#if jobsLoaded}}
<div class="row">
<div class="col-md-12">
<div class="row">
<div class="col-md-2">
{{#if jobs}}
<select id="perPage" class="selectpicker select-block" _val="{{selected_opt}}">
<option value="10">10 Per Page</option>
<option value="25">25 Per Page</option>
<option value="50">50 Per Page</option>
<option value="100">100 Per Page</option>
</select>
{{/if}}
</div>
<div class="col-md-10">
{{{pagination}}}
</div>
</div>
</div>
{{/if}}
</div>
</template>
Client Side JS:
Deps.autorun(function(){
Meteor.subscribe('cities');
Meteor.subscribe('jobs', Session.get('currentIndustryOnet'), function(){
Session.set('jobsLoaded', true);
});
});
Template.list.jobsLoaded = function () {
return Session.equals('jobsLoaded', true);
};
Template.list.rendered = function(){
var select = $('#perPage');
var option = select.attr('_val');
$('option[value="' + option + '"]').attr("selected", "selected");
select.selectpicker({
style: 'btn-info col-md-4',
menuStyle: 'dropdown-inverse'
});
}
Template.list.jobs = function() {
Deps.autorun(function(){
var jobs = Jobs.find();
if(Session.get('currentIndustryOnet')) {
jobs = Jobs.find({onet: Session.get('currentIndustryOnet')});
}
Session.get('jobCount', jobs.count());
return Pagination.collection(jobs.fetch());
});
}
Server Side JS:
Meteor.publish('jobs', function(onet_code){
var cursor, options = {sort: {dateacquired: -1}};
console.log(onet_code);
if(onet_code){
cursor = Jobs.find({onet: onet_code}, options);
} else {
cursor = Jobs.find({}, options);
}
return cursor;
});
Meteor.publish('cities', function(){
return Cities.find({}, {sort: {pop: -1}, limit: 100});
});
For some reason when you load the page, the pagination appears, but the {{#each jobs}} isn't populated with the collection results.
Update:
Template.list.jobs = function() {
var options = {}, jobs;
if(Session.get('currentMapArea')) {
var c = Cities.findOne({_id: Session.get('currentMapArea')});
options.address = c.city.capitalize() + ", " + c.state;
}
if(Session.get('currentIndustryOnet')) {
options.onet = Session.get('currentIndustryOnet');
}
if($.isEmptyObject(options)) {
jobs = Jobs.find();
} else {
jobs = Jobs.find(options);
}
Session.set('jobCount', jobs.count());
return Pagination.collection(jobs.fetch());
}
Update 3:
Pagination:
Template.list.pagination = function() {
return Pagination.links('/jobs', Session.get('jobCount') || 1, {currentPage: Session.get('page') || 1, perPage: Session.get('perPage') || 10});
}
<template name="list">
<div class="col-md-12">
{{#if jobsReady}}
<ul class="list-group" id="jobs">
{{#each jobs}}
<li>
<span class="pull-right">{{address}}</span>
<span id="jobTitle">{{{ jobUrl url title }}}</span>
<span id="company">{{company}}</span>
<span id="date"><em>{{dateacquired}}</em></span>
</li>
{{/each}}
</ul>
{{else}}
{{> spinner}}
{{/if}}
</div>
{{#if jobsReady}}
<div class="row">
<div class="col-md-12">
<div class="row">
<div class="col-md-2">
<select id="perPage" class="selectpicker select-block" _val="{{selected_opt}}">
<option value="10">10 Per Page</option>
<option value="25">25 Per Page</option>
<option value="50">50 Per Page</option>
<option value="100">100 Per Page</option>
</select>
</div>
<div class="col-md-10">
{{{pagination}}}
</div>
</div>
</div>
{{/if}}
</div>
</template>
I believe the problem is with this code -- it doesn't return anything:
Template.list.jobs = function() {
Deps.autorun(function(){
var jobs = Jobs.find();
if(Session.get('currentIndustryOnet')) {
jobs = Jobs.find({onet: Session.get('currentIndustryOnet')});
}
Session.get('jobCount', jobs.count());
return Pagination.collection(jobs.fetch());
});
}
Think about what the return does. It return from the function in the Deps.autorun. The outer function returns nothing.
I think you can simply lose the Deps.autorun and do this, which should still be reactive:
Template.list.jobs = function() {
var jobs = Jobs.find();
if(Session.get('currentIndustryOnet')) {
jobs = Jobs.find({onet: Session.get('currentIndustryOnet')});
}
Session.get('jobCount', jobs.count()); // should this be a 'Session.set'?
return Pagination.collection(jobs.fetch());
}
Also note the question in the comment.

Resources