Prefill Mustache.JS Template with Values from Mongo DB (Mongoose) - mongodb

I am currently having a list with some entries in my database. Now i want the users to be able to edit one of those entries.
When the "Edit" Button is clicked, it should load the original form and prefill all the fields with the values already stored in the database.
I used a mustache template for my form, looking like this:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>Issue Form</h1>
<p>{{ errors }}</p>
<form method="post">
<label>Title: <br><input type="text" name="title">{{ value }}</label><br>
<label>Description: <br><textarea type="text" name="description">{{ value }}
</textarea></label><br>
<label>Priority: <br>
<select name="priority">
<option>high</option>
<option>medium</option>
<option>low</option>
</select>
</label><br>
<input type="submit" value="Save Entry">
</form>
</body>
</html>
This is my mongoose schema:
var issueSchema = new mongoose.Schema({
title: String,
description: String,
priority: String
});
I of course did a lot of researche on how to fill my fields. I read about the mongoose "populate()" function, but when i tried to use it, there was always some errors telling me that the function itself is undefined.
Another option was using a JSON file to store the data values, but i cannot do this in this example since the values should always be stored in my MongoDB data folder.
Another version i found was creating an object via the toObject() function. But anytime i tried that out:
router.get('/edit/:id', (req, res) => {
var objectForEditing = issueModel.findOne(req.params.id).toObject;
console.log(objectForEditing);
res.render('issueFormEdit');
});
The console.log part shows me the object as undefined.
Using JQuery like i did in any other javascript file before didn't work either, even when including the modules.
I simply need a method to connect my javascript code with my hjs file. But i simply am not able to do so, my knowledge is not enough for this. I really tried out a lot and have invested hours so far. But i simply can't get to the bottom on how to connect these two files.
This is my first time ever working with this combination of Mustache.JS and MongoDB/Mongoose/Express. Please be gentle :(
If any more code is needed, please just let me know.

Your code has the following list of issues:
1) Model.prototype.findOne() method is asynchronous, so you either need to use async/await or use promises before calling toObject() on it.
2) You are querying mongoose in the wrong way. You need to use findOneById(id) or findOne({ _id: id }).
3) toObject is a function, so it has to be called.
4) objectForEditing needs to be passed to res.render function as the second argument which represents locals, which basically is:
an object whose properties define local variables for the view
Try this code (async/await):
router.get('/edit/:id', async (req, res) => {
let objectForEditing = await issueModel.findOneById(req.params.id);
objectForEditing = objectForEditing.toObject();
res.render('issueFormEdit', objectForEditing);
});
Using Promises:
router.get('/edit/:id', (req, res) => {
issueModel.findOneById(req.params.id)
.then(issue => {
const objectForEditing = issue.toObject();
res.render('issueFormEdit', objectForEditing);
});
});

Related

MongoDB stitch "getting started" failure

Nothing is more frustrating than failing on a simple task.
I am following along with : https://docs.mongodb.com/stitch/getting-started/first-stitch-app/ - and I get to setp 9 - which is supposed to clear the permissions rule, so anyone can view my posts; however, I still get the permissions error.
Uncaught (in promise) Error: no rule exists for namespace 'blog.comments'
at client.js:343
at <anonymous>
Here's the entire code - but I suspect the error is on the stitch setting side.
YES - i have replaced "your-app-id" with my app id...
I DID clear the filter, and I did change the READ permission to {}...
<html>
<head>
<script src="https://s3.amazonaws.com/stitch-sdks/js/library/v2/stable/stitch.min.js"></script>
<script>
const client = new stitch.StitchClient('<your-app-id>');
const db = client.service('mongodb', 'mongodb-atlas').db('blog');
function displayComments() {
db.collection('comments').find({}).execute().then(docs => {
var html = docs.map(c => '<div>' + c.comment + '</div>').join('');
document.getElementById('comments').innerHTML = html;
});
}
function displayCommentsOnLoad() {
client.login().then(displayComments)
}
function addComment() {
var c = document.getElementById('new_comment');
db.collection('comments').insertOne({owner_id : client.authedId(), comment: c.value})
.then(displayComments);
c.value = '';
}
</script>
</head>
<body onload="displayCommentsOnLoad()">
<h3>Aspirational blog post</h3>
<div id="content">
I like to write about technology, because I want to get on the front page of hacker news (in a good way).
</div>
<hr>
<div id="comments"></div>
<hr>
Add comment:
<input id="new_comment"><input type="submit" onClick="addComment()">
</body>
</html>
Cant go any further, if the first real steps fail.
ANY help is appreciated.
Go to mongodb-atlas in the Stitch console and cross check if you have a collection named blog.comments. It's not the permission error, it's most likely due to the absence of the collection algogether.
I tried setting up stitch once and got into the same problem. Just make sure if the <databasename>.<collectionname> is matching with what you are using in your script which here should be blog.comments. Or just try deleting the collection from there and create a new one.

Jade + mongodb + express.js, delete form not working

My delete code is not working and I think not even firing as I don't see my console.log, I have an add button that works with a form and they look alike, this is why I don't get it.
app.js:
var db = monk('localhost:27017/mongodb');
Jade:
extends admin_menu
block content
h1.
Cocktail list
ul
each cocktail, i in cocktaillist
li
p= cocktail.name
form#form_delete_project(name="/admin/delete_cocktail", method="post", action="/admin/delete_cocktail")
input#input_name(type="hidden", placeholder="", name="_id", value="#{cocktail._id}")
button#submit_project(type="submit") delete
index.js:
router.post('/admin/delete_cocktail', function(req, res) {
console.log(id)
// Set our internal DB variable
var db = req.db;
// Get our form values. These rely on the "name" attributes
var id = req.body._id;
// Set our collection
var collection = db.get('cocktailcollection');
// Submit to the DB
collection.remove({
"_id":id
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("There was a problem removing the information to the database.");
}
else {
// And forward to success page
res.redirect("/admin/cocktail_list");
}
});
});
Jade is built on indentation. Since you are not indenting the items in your form it is not in you form. In html your code would look like this:
<form>
</form>
<input name="_id">
<button>
Since your input with _id is outside the form it is not being posted. That is why your console log is showing nothing. There is no req.body._id.And, of course, your submit-button is also outside the form. So it does nothing.
So, the first thing you should do is indent the code.

Method override for expressJS not working for PUT hidden method HTML FORM

Using express and mongoose/mongo to create a todo app. Domain model: Authors have reminders.
In my app.js:
var bodyParser = require('body-parser')
var methodOverride = require('method-override')
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}))
app.use(methodOverride('_method'))
my form using handlebars in views/authors/edit.hbs:
<h2>Edit {{name}}</h2>
<form action="/authors/{{_id}}" method="post">
<input type="hidden" name="_method" value="put">
<label>Name:</label>
<input type="text" name="name">
<input type="submit">
</form>
My routing for the edit view and put request to update author:
app.get("/authors/:id/edit", function(req, res){
AuthorModel.findById(req.params.id, function(err, docs){
res.render("authors/edit", docs)
})
})
app.put("/authors/:id", function(req, res){
console.log("updating")
AuthorModel.findById(req.params.id, function(err, docs){
docs.name = req.body.name
docs.save(function(err){
if(!err){
res.redirect("authors/" + req.params.id)
}
})
})
})
When I inspect the elements in the dev tools I see everything I need to see, but when I go to submit, gives me error CANNOT POST. Create functionality works fine, so my first thought is the method override isn't working. If I change put to POST, everything works great.
If it helps, link to the repo that contains this app
Judging by the documentation, there are two common ways to override the method:
using a header;
using a query string parameter;
You're using the "old" method of specifying a form variable, which you can still use, but this requires custom logic on the server side.
It seems to me that the easiest way for you to fix this is to use the query string parameter:
<form action="/authors/{{_id}}?_method=put" method="post">

Submit a Form to Custom URL in Laravel 4

I have a simple form which allows the User to enter from_date and to_date.Lets say a user enters 2014-09-01 and 2014-09-10 respectively.
How can I get this form submit to a URL ../from_date/2014-09-01/to_date/2014-09-10
You cannot do that but if you need to do something like this, you need to submit to standard class Controller and then resubmit it using redirection:
public function resubmit() {
Redirect::to('/from_date/'.Input::get('from_date').'/to_date/'.Input::get('to_date'))->withInput();
}
But to be honest I don't know why you try to do that. Usually you post data to static url and display content using dynamic urls with pretty urls.
To change the URL once the page has already loaded, you will need to use javascript, as you won't be able to do this using Laravel/PHP because you need access to the dates, which are only selected after the page has loaded.
If your form is similar to:
<form id="dateForm" onsubmit="return submitDateForm()">
<input type="text" id="from_date" name="from_date">
<input type="text" id="to_date" name="to_date">
</form>
Assuming you are using POST for the form submission, and have already imported jQuery, then insert into your view (or a separate .js file which you import) the following jQuery:
function submitDateForm() {
var from_date = $( '#from_date' ).val();
var to_date = $( '#to_date' ).val();
//Send the request
var request = $.post("../from_date/" + from_date + "/to_date/" + to_date);
//prevent the form from submitting itself normally
return false;
}

Why do i not get through to my Meteor.method on the server?

I'm trying to add a url to the logged in users collection. My final goal at least is to be able to add a field e.g {profilePicture: 'http://randompic.com/123.png'}
What i've tried so far is:
<template name="profile">
<h1>My Profile</h1>
<form class="form-inline"action="">
<label for="url"></label>
<input class="input input-large" type="url" name="url" placeholder="URL for you image..." id="url">
<button class="btn btn-success submit">Update profile picture</button>
</form>
</template>
When the user will press the Update profile picture -button i send it to this helper function:
Template.profile.events({
'click .submit': function (evt, tmpl) {
var userid = Meteor.userId();
var url = tmpl.find('#url').value;
var options = {_id: userid, profilePicture: url};
Meteor.call('addToProfile', options);
}
});
I have tried to alert out option._id and options.profilePicture and i have that data availble.
Now when i pass it along to my server.js file i get no output of my alert:
Meteor.methods({
'addToProfile': function(options) {
//Not even this alert will show..
alert(options._id); Edit: console.log() works on the server thought.
}
})
So that is my first issue.
The second problem (to come) is that i don't know how to update/add to the users collection with this profilePicture data. Would really appreciate if someone could contribute with a small example of that part.
Based on the comments everything seems to be functioning as expected. It appears that you are just trying to update some user data on the client. Since you have the insecure package removed you need to validate the updates on the server (that the client requests), this is how you would do that:
// only applies to client requests
Meteor.users.allow({
// validation for user inserts
insert: function ( userId, doc ) {
// perform any checks on data that you want to perform, like checking to see if the current user is an admin.
// this check just requests that a user be logged in
return userId;
}
,
// is your validation for user updates
update: function ( userId, doc, fields, modifier ) {
// again, perform any validation you want. A typical check is to make sure they didn't add any extra fields.
// this makes sure a user is logged in and that they are only attempting to update themself
return userId === doc._id;
}
});
There are some more thorough examples in the docs. Now you can just call update like you normally would and rely on the server to perform any validation!