AngularJs binding model attribute to checkbox - javascript

I am trying to assign some tags on post creation.
I have a Post model that looks like this:
var mongoose = require('mongoose');
var PostsSchema = {
title: String,
content: String,
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Users'
},
comments: [{
text: String,
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Users'
},
}],
tags: [String]
};
I am trying to bind the some checkboxes to the 'tags' array attribute in the Post.
This how my post router looks like:
///* Create post */
postRouter.route('/').post(function (req, res) {
mongoose.createConnection('localhost', 'CMS');
console.log(req.body);
var post = {
title: req.body.title,
content: req.body.content,
tags: req.body.tags
};
if (typeof req.body.title === "undefined" || typeof req.body.content === "undefined")
{
res.json({message:"Error"});
}else
{
var newPost = new Posts(post);
newPost.save(function (err, post) {
if (err) res.json({message:"Error"});
res.json(post);
});
}
});
My controller looks like:
$scope.createPost = function(post){
postService.createPost(post);
postService.getPosts()
.then(modelPosts);
}
And my view look like:
div(ng-controller='postController')
h2 Create Post
form
div.form-group
label(for='title') Title
input(type='text', class='form-control', id='title', name='title', placeholder='Title', ng-model='newpost.title', autofocus)
div.form-group
label(for='password') Content
input(type='text', class='form-control', id='content', name='content', placeholder='content', ng-model='newpost.content')
div(ng-controller='tagController')
h2 Tags
div( ng-model='Tags', ng-init='getTags()')
ul( ng-repeat='tag in Tags')
li
label
input(ng-model='newpost.tag',value='{{tag.name}}', type='checkbox', name='tag[]')
span {{tag.name}}
button( ng-click='createPost(newpost)', class='btn btn-small btn-primary') Create Post
I am not sure what is the problem with the binding my view to the model. Tags are rendered and checkboxes are created , but when i check one checkbox , all of them get checked.

input(ng-model='newpost.tag', ng-value-true='tag.name', ng-value-false='null' type='checkbox', name='tag[]')
Docs Input[checkbox]

Related

MethodOverride PUT not working

I am using Node.js, Express and MethodOverride to try and have a form update only 1 part of a model (my user model).
User model:
var userSchema = new mongoose.Schema({
email: { type: String, unique: true, lowercase: true },
password: String,
profile: {
name: { type: String, default: 'Company Name' },
location: { type: String, default: 'Location' },
website: { type: String, default: 'Your Website' },
picture: { type: String, default: '' }
},
assetNumPre: { type: String, default: 'test' }, // this is the one I want to change
});
module.exports = mongoose.model('User', userSchema);
HTML form:
<form role="form-inline"action="/dashboard/settings/assetNumber?_method=PUT" method="POST">
<div class="col-md-3">
<div class="form-group">
<label for="prefix" class="control-label">Prefix for Asset Number</label>
<br>
<small>Any alphanumeric characters to a limit of 6</small>
<input type="text" class="form-control" id="prefix" name="prefix" placeholder="Prefix max 6 characters" maxlength="6" value="{{ prefix }}">
</div><!-- Prefix for Asset Number-->
<br>
<div class="box-footer">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
Then route:
app.put('/dashboard/settings/assetNumber',
setRender('dashboard/settings/assetNumbers'),
setRedirect({auth: '/login'}),
isAuthenticated,
dashboard.getDefault,
(req, res) => {
var prefix = req.body.prefix;
console.log(req.params);
User.findByIdAndUpdate({_id: req.params.user_id}, prefix, function(err, UpdatedUser) {
if (err) {
res.send(err);
}
console.log(UpdatedUser);
});
res.locals.prefix = req.user.assetNumPre;
});
One thing my route is missing is req.user.assetNumPre which is where I need to save it but I have no clue how to do this PUT request. Docs are not helping much either.
I got the route from a Stack Overflow example a few days ago and can't find the link to it. My app.js had method override working because I have done DELETE requests already. The model has the correct field and has a default test value that shows up in my show page.
You're calling this:
User.findByIdAndUpdate({_id: req.params.user_id}, prefix...
But prefix is only the value:
var prefix = req.body.prefix;
findByIdAndUpdate takes an Object, not a value, to update a specific field.
So try:
User.findByIdAndUpdate({_id: req.params.user_id}, { assetNumPre: prefix }...
Here is the fixed route:
app.put('/dashboard/settings/assetNumber',
setRedirect({auth: '/login', success: '/dashboard/settings/assetNumber', failure: '/dashboard/settings/assetNumber'}),
isAuthenticated,
(req, res) => {
User.findById(req.user.id, function(err, user) {
if (err) return (err);
user.assetNumPre = req.body.prefix || 'pre';
user.save(function(err) {
if (err) return (err);
req.flash('success', { msg: 'Asset Number Prefix updated.' });
res.redirect(req.redirect.success);
});
});
res.locals.prefix = req.user.assetNumPre;
});
So a few things changed that were not part of the issue. I figured out I need to just set the data inside the callback function. Then do a user.save.

Resolving "next is not defined"

I keep encountering "ReferenceError: next is not defined" whenever i try to access /catalog/bookinstance/:id/delete. I Spent almost 2 hours trying to troubleshoot but to no avail :(
Any suggestions on which part went wrong?
catalog.js
/* GET request to delete BookInstance. */
router.get('/bookinstance/:id/delete', book_instance_controller.bookinstance_delete_get);
// POST request to delete BookInstance
router.post('/bookinstance/:id/delete', book_instance_controller.bookinstance_delete_post);
bookinstanceController.js
var BookInstance = require('../models/bookinstance');
var Book = require('../models/book');
var async = require('async');
// Display BookInstance delete form on GET
exports.bookinstance_delete_get = function(req, res, next) {
BookInstance.findById(req.params.id)
.populate('book')
.exec(function(err, bookinstance){
if(err){
return next(err);
}
res.render('bookinstance_delete', {title: 'Delete BookInstance', bookinstance: bookinstance})
});
};
// Handle BookInstance delete on POST
exports.bookinstance_delete_post = function(req, res, next) {
//req.checkBody('bookid', 'Book ID must exist').notEmpty();
BookInstance.findByIdAndRemove(req.body.id, function deleteBookInstance(err){
if(err){
return next(err);
}
res.redirect('/catalog/bookinstances');
});
};
bookinstance_delete.pug
h1= title
p #[strong Do you really want to delete this BookInstance?]
div(style="margin-left:20px")
p #[strong ID]: #{bookinstance._id}
p #[strong Title:]
a(href=bookinstance.book.url) #{bookinstance.book.title}
p #[strong Imprint:] #{bookinstance.imprint}
p #[strong Status:]
if bookinstance.status=='Available'
span.text-success #{bookinstance.status}
else if bookinstance.status=='Maintenance'
span.text-danger #{bookinstance.status}
else
span.text-warning #{bookinstance.status}
if bookinstance.status!='Available'
p #[strong Due back:] #{bookinstance.due_back_formatted}
form(method='POST' action='')
div.form-group
input#id.form-control(type='hidden',name='id', required='true', value=bookinstance._id )
button.btn.btn-primary(type='submit') Delete
bookinstance.js
var mongoose = require('mongoose');
var moment = require('moment');
var Schema = mongoose.Schema;
var BookInstanceSchema = Schema({
book: {type: Schema.ObjectId, ref: 'Book', required: true},
imprint: {type: String, required: true},
status: {type: String, required: true, enum: ['Available', 'Maintenance', 'Loaned', 'Reserved'], default: 'Maintenance'},
due_back: {type: Date, default: Date.now},
});
BookInstanceSchema
.virtual('url')
.get(function(){
return '/catalog/bookinstance/' + this._id;
});
BookInstanceSchema
.virtual('due_back_formatted')
.get(function(){
return moment(this.due_back).format('MMMM Do, YYYY');
});
module.exports = mongoose.model('BookInstance', BookInstanceSchema);

Meteor using namedContext to addInvalidKeys to an AutoForm form returning an error

I have the following SimpleSchema where I am trying to add custom validation to validate against entering duplicate customer name, yet whenever I try to save a new customer I get error:
Exception in delivering result of invoking
'adminCheckNewCustomerName': TypeError: Cannot read property
'namedContext' of null
can someone please tell me what I am doing wrong / missing here to validate the customer name against duplicate records? Thanks
schema.js:
AdminSection.schemas.customer = new SimpleSchema({
CustomerName: {
type: String,
label: "Customer Name",
unique: true,
custom: function() {
if (Meteor.isClient && this.isSet) {
Meteor.call("adminCheckNewCustomerName", this.value, function(error, result) {
if (result) {
Customer.simpleSchema().namedContext("newCustomerForm").addInvalidKeys([{
name: "CustomerName",
type: "notUnique"
}]);
}
});
}
}
}
});
UI.registerHelper('AdminSchemas', function() {
return AdminSection.schemas;
});
form.html:
{{#autoForm id="newCustomerForm" schema=AdminSchemas.customer validation="submit" type="method" meteormethod="adminNewCustomer"}}
{{>afQuickField name="CustomerName"}}
<button type="submit" class="btn btn-primary">Save Customer</button>
{{/autoForm}}
collections.js:
this.Customer = new Mongo.Collection("customers");
Check collection2 code for fetching the schema attached to a collection:
_.each([Mongo.Collection, LocalCollection], function (obj) {
obj.prototype.simpleSchema = function () {
var self = this;
return self._c2 ? self._c2._simpleSchema : null;
};
});
This cryptic homonym _c2 (one of two hard things in programming...) comes from attachSchema:
self._c2 = self._c2 || {};
//After having merged the schema with the previous one if necessary
self._c2._simpleSchema = ss;
Which means that you have forgotten to attachSchema or fiddled with the property of your collection.
To solve:
Customer.attachSchema(AdminSchemas.customer);
//Also unless this collection stores only one customer its variable name should be plural

Error copying req.body properties into Mongoose Model

First of all I have to say that I'm new in Angular and node technologies. So sorry for my ignorance.
I get this error when I try to save an Entity from edition view: 'Cast to ObjectId failed for value "[object Object]" at path "category"'.
Well, I've got these code:
HTML:
<form class="form-horizontal" data-ng-submit="update()" novalidate>
<fieldset>
<div class="form-group">
<label for="listaCat">Categoría:</label>
<select id="listaCat" class="form-control" data-ng-Fmodel="notification.category" data-ng-options="c.name for c in listaCategorias track by c._id">
</select>
</div>
<div class="form-group">
<label class="control-label" for="name">Descripción</label>
<div class="controls">
<input type="text" data-ng-model="notification.name" id="name" class="form-control" placeholder="Descripción" required>
</div>
</div>
<div class="form-group">
<input type="submit" value="Guardar" class="btn btn-default">
</div>
<div data-ng-show="error" class="text-danger">
<strong data-ng-bind="error"></strong>
</div>
</fieldset>
</form>`
Angular controller:
$scope.update = function() {
var notification = $scope.notification;
notification.$update(function() {
$location.path('notifications/' + notification._id);
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
Server side controller:
var mongoose = require('mongoose'),
errorHandler = require('./errors.server.controller'),
Notification = mongoose.model('Notification'),
_ = require('lodash');
exports.update = function(req, res) {
var notification = req.notification;
notification = _.extend(notification , req.body);
notification.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(notification);
}
});
};
Mongoose Model:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var NotificationSchema = new Schema({
name: {
type: String,
default: '',
required: 'Rellena la notificación',
trim: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
},
category: {
type: Schema.ObjectId,
ref: 'Category'
}
});
mongoose.model('Notification', NotificationSchema);
var CategorySchema = new Schema({
name: {
type: String,
default: '',
required: 'Rellena la categoría',
trim: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Category', CategorySchema);
So, if I debug inside Server controller at update method with WebStorm, I can see that req.body comes with each attribute well formed, but after convert req.body into Notification Mongoose Model with:
notification = _.extend(notification , req.body);
the category attribute is not a Model but an ObjectId. It seems as lodash.extend is not working properly for complex attributes. I've tried many other ways of cloning the object but without success.
Finally I solved it, with this line inside the angular controller:
notification.category = $scope.notification.category._id;
notification.$update(function() {
Anyway, I think that this is not the right way. I guess there must be a way of copying the req.body properties into a mongoose model without doing it manually for the complex properties.
Thanks a lot in advance!
Since you are working on AngularJS and ExpressJS, i would suggest you to use $resource service which is exactly meant for interacting with the rest API.
**$resource** contains these default set of actions:
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
There is nice documentation available in the link that i shared above.
In your case:
i assume, http://localhost:300/notifications/:id, this might be your rest url where you want to perform update action.
You can create your custom services like:
var module = angular.module('myapp.services',['ngResource']);
module.factory('MyAppUpdateService',function($resource){
return $resource('notifications/:id',
{
id: '#id'
},
{
'update': { method:'PUT' }
}
);
});
Now inside your angular app controller you can inject this service as dependency and hence it will be available to perform update in that REST url.
angular.module('myapp',['ngResource','myapp.services']);
angular.module('myapp').controller('MeetupsController',['$scope','$resource','$state','$location','MeetupUpdateService','socket',
function($scope,$resource,$state,$location, MyAppUpdateService){
$scope.updateMeetup = function(){
$scope.updateService = new MyAppUpdateService();
$scope.updateService.name = $scope.notification.name;
.
.
.
$scope.updateService.$update({id:$scope.notification.category._id},function(result){
$location.path("/meetup/")
});
}
})]);
So this was just an example, if you want more comprehensive implementation. Look here, i am creating a MEAN seed of my own, and i am doing the same.
Any doubt please do ask.

Post Form Data to Array of Existing MongoDB Document using Express and Mongoose

I'm attempting to create a Mongo document then update the document form a form to have additional properties, one of which has an array of objects.
I'm able to save everything except objects to the address array.
The following code snippets show my current attempt to save an object to the address array. I feel like I'm missing a push or shift which I've tried and can't seem to get syntax correct.
Mongoose Schema:
var UserSchema = new mongoose.Schema({
username: { type: String, lowercase: true }
, password: { type: String }
, email: { type: String, lowercase: true }
, phone: { type: String }
, newsletter: Boolean
, created: { type: Date, default: Date.now }
, address: [{
nickname: { type: String }
, streetAddress: { type: String }
, streetAddress2: { type: String }
, state: { type: String }
, zip: { type: String }
}]
});
Model Methods:
First I create an account. The form only asks for username, email, password then redirects to the jade file where users can fill out the rest of the form.
module.exports = exports = function(){
//create account
this.createAndSave = function (req, res ) {
new User({
username: req.body.username
, password: req.body.password
, email: req.body.email
, phone: req.body.phone
, address: [{
nickname: req.body.nickname
, streetAddress: req.body.streetAddress
, streetAddress2: req.body.streetAddress2
, state: req.body.state
, zip: req.body.zip
}]
}).save(function (err, user){
if (err) throw err;
req.session.isLoggedIn = true;
req.session.user = user.username;
res.redirect('/account/' + user.username)
})
}
//update account
this.updateRequest = function (req, res) {
User.update({username: req.user.username}, {
username: req.body.username
, email: req.body.email
, phone: req.body.phone
, newsletter: req.body.newsletter
, address: [{
nickname: req.body.nickname
, streetAddress: req.body.streetAddress
, streetAddress2: req.body.streetAddress2
, state: req.body.state
, zip: req.body.zip
}]
}, function (err) {
res.redirect("/account/" + req.body.username);
});
}
Jade Template: (I'm sure this could be cleaner)
h1 Edit User
#{user}
form(method="POST", action="/account/#{user.username}")
input(type="hidden", name="_method", value="PUT")
.form-group
label(for="username") Name
input#name.form-control(type="text", name="username", value= user.username )
.form-group
label(for="email") Email
input#email.form-control(type="email", name="email", value= user.email )
.form-group
label Phone
input#phone.form-control(type="text", name="phone", value= user.phone )
.form-group
label Newsletter Opt In/Out
input#newsletter(type="checkbox", name="newsletter", checked=(true===false ? "checked" : undefined))
if(user.address.length > 0)
for (var i = 0; i < user.shippingAddresses.length; i++) {}>)
.form-group
label Street Address
input#address.form-control(type="text", name="streetAddress", value= user.shippingAddresses[i].streetAddress )
.form-group
label Address Continued
input#address2.form-control(type="text", name="streetAddress2", value= user.shippingAddresses[i].streetAddress2 )
.form-group
label Zip Code
input#zip.form-control(type="text", name="zip", value= user.shippingAddresses[i].zip )
else
.form-group
label Location Nick Name
input#address.form-control(type="text", name="nickname", value= )
.form-group
label Street Address
input#address.form-control(type="text", name="streetAddress", value= )
.form-group
label Address Cont.
input#address2.form-control(type="text", name="streetAddress2", value= )
.form-group
label State
input#state.form-control(type="text", name="state", value= )
.form-group
label Zip Code
input#zip.form-control(type="text", name="zip", value= )
button(type="submit") Update Account
Additionally there is another address only form which is why the address is an array.
Any direction would be very helpful as I may go unhinged at any moment. If you any further code let me know.
Something else to note, I'm not able to get any of the updated data from the update function to save to mongo.
Thanks!
Here is the solution I came up with. I find the document to update and push an object to the property that stores the array.
Example method:
this.addAddress = function (req, res) {
var newAddress = {
nickname: req.body.nickname,
streetAddress: req.body.streetAddress,
streetAddress2: req.body.streetAddress2,
state: req.body.state,
zip: req.body.zip
}
User.update({username: req.session.user}, { $push : {
address: newAddress
}}, {upsert: true}, function ( err ) {
if(err){
console.log(err);
}else{
console.log("Successfully added");
}
})
}

Categories

Resources