Not sure why the jsonp callback is not getting returned to the client.
accountcontrol.js
exports.find = function(req, res) {
var b=req.query.q;
db.collection('catData').find({ wrapperType : "titles", titleTitles : new RegExp(b)}).limit(5).toArray(function (err, results) {
if(results) {
res.type('application/json');
res.jsonp(results);
} else {
console.log("No Results")
}
})
}
app.js
app.get('/operations/autocompletehome', ensureLoggedIn('/login'), function(request, response) {
response.render('autocompletehome', { title: 'Autocomplete' });
});
app.get('/operations/autocomplete', accountcontrol.find)
autocompletehome.jade
doctype html
html(lang="en")
head
meta(charset="utf-8")
title jQuery UI Autocomplete - Remote JSONP datasource
link(rel="stylesheet", href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css")
script(src="//code.jquery.com/jquery-1.10.2.js")
script(src="//code.jquery.com/ui/1.11.2/jquery-ui.js")
script(src="/javascripts/autocomplete.js")
link(rel="stylesheet", href="/stylesheets/newstyle.css")
style
.ui-autocomplete-loading {background: white url("images/ui-anim_basic_16x16.gif") right center no-repeat;}
#city { width: 25em; }
.ui-widget
label(for="city") Your city:
input#city(type="text")
| Powered by
a(href="http://dog.org") dog.org
.ui-widget(style="margin-top:2em; font-family:Arial")
| Result:
#log.ui-widget-content(style="height: 200px; width: 300px; overflow: auto;")
autocomplete.js
$(function() {
function log( message ) {
$( "<div>" ).text( message ).prependTo( "#log" );
$( "#log" ).scrollTop( 0 );
}
$( "#city" ).autocomplete({
source: function( request, response ) {
$.ajax({
url: "/operations/autocomplete",
dataType: "jsonp",
data: {
q: request.term
},
success: function( data ) {
response( data );
console.log('success', data);
},
complete: function() {
console.log('done');
}
});
},
minLength: 3,
select: function( event, ui ) {
log( ui.item ?
"Selected: " + ui.item.label :
"Nothing selected, input was " + this.value);
},
open: function() {
$( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
},
close: function() {
$( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
}
});
});
Console.Log in the Browser
success [
Object
_id: "546c6b509c97a9880d2b29db"
titleTitles: "06image.com"
titlesEmail: "d#c.com"
titlesName: "Fox"
titlesOwner: "Dog"
wrapperType: "titles"
__proto__: Object
It appears that everything is firing except for the return to the browser.
Here is the Answer:
Changed to json from jsonp in both the autocomplete.js and app.js
In autocomplete.js Replace:
success: function( data ) {
response( data );
console.log('success', data);
},
With:
success: function( data ) {
response($.map(data, function(item) {
return {
label: item.titleTitles
};
}));
},
Enables JQuery to parse the Mongo array.
Hope this helps others who are woking with Jade, Mongo and Express trying to learn how to implement Ajax.
Related
I am getting error 404 that the API cannot be found. The Boolean in API is "auto_delete". I want to change it to true when this is referenced.
I wrote a button to reference a function that would reference this API but OnClick it will not be able to find this API apparently.
I posted first the front end file with constructor/binding, button, and function. I then put API at bottom.
Any input would help.
//FRONT END
This is the front end with button and function button references to
//CONSTRUCTOR AND BINDING FUNCTION
export default class VideoContent extends Component {
constructor(props) {
super(props);
let video = this.props.video;
let user = this.props.user;
this.state = {
fetchDuration: false,
viewed: false,
subscribed:
user &&
user.hasOwnProperty("follows") &&
user.follows.includes(video.author)
};
this.view = this.view.bind(this);
this.report = this.report.bind(this);
this.reportJ= this.reportJ.bind(this);
}
<Button
disabled={user ? !user.userId : true}
onClick={this.reportJ}
style={{ float: "right", backgroundColor: "purple" }}
>
ReportJ
</Button>
//FUNCTION
reportJ() {
const { video, user } = this.props;
confirmAlert({
title: "Confirm Objectionable Content",
message: "You Sure Fool?",
buttons: [
{
label: "Yes",
onClick: () => {
axios
.post(
inDev
? devAPI.concat("reportJ")
: baseAPI.concat("reportJ"),
{
id: video._id,
update: {
auto_delete: true
}
}
)
.then(res => {
this.setState({ changed: true });
})
.catch(error => {
console.log(error);
});
}
},
{
label: "No",
onClick: () => alert("Nevermind")
}
]
});
}
//SERVER JS File with API below
router.post("/reportJ", (req, res) => {
const { id, update } = req.body;
models.Videos.findById(id, function (err, video) {
video.auto_delete = true;
video.save((err, data) => {
if (err)
return res.json({
success: false,
error: err
});
return res.json({
success: true,
data: data
});
});
});
});
I have two directories where vue, node exist. And I have the vue build file in the node folder.
I am currently processing requests from nodes in the vue. However, the event occurs but the data does not cross.
I have the following code, I sent form data via create, but the return data is empty. Also, in mongodb, title and content are require: true, so I get an error like the title.
Please help me.
node/routes/api
...
const Post = require('../db/post');
router.post('/new', (req, res) => {
const post = new Post({
title: req.body.title,
content: req.body.content
});
post.save((err) => {
if (err) {
console.error(err);
res.json({ result: 0 });
return;
}
res.json({ result: 1 });
});
});
...
vue/src/component/new
<template>
<div id="form-group">
name : <input v-model="post.title">
content : <input v-model="post.content">
<button v-on:click="new" >New</button>
</div>
</template>
<script>
export default {
data: function () {
return {
post: {}
}
},
methods: {
new: function (evt) {
this.$http.post('/api/post/new', {
post: this.post
})
.then((response) => {
if (response.data.result === 0) {
alert('Error')
}
if (response.data.result === 1) {
alert('Success')
this.$router.push('/')
}
})
.catch(function (error) {
alert('error')
})
}
}
}
</script>
I would like to update my view after an ajax call, rendering compiled ejs from the server.
These two previous questions seem to achieve this but I cannot update my view
Can't Render EJS Template on Client
How to generate content on ejs with jquery after ajax call to express server
So from what I understand I should compile my ejs file (partial) on the server.
fixtures.ejs
<% fixtures.forEach((fixture) => { %>
<h2><%= fixture.home_team %> vs <%= fixture.away_team %></h2>
<% }) %>
index.js
app.post('/league_fixtures', async function (req, res) {
try {
var league_name = req.body.league_name;
const fixtures = await leagueFixtures(league_name);
//compile view
fs.readFile('./views/fixtures.ejs', "utf-8", function(err, template) {
fixture_template = ejs.compile(template, { client: true });
var html = fixture_template({fixtures: fixtures});
console.log(html);
// This logs out my HTML with fixtures so I am almost there
// <h2>Club Africain vs Al-Faisaly Amman</h2>
// <h2>Al Nejmeh vs ASAC Concorde</h2>
});
res.json({fixtures: fixtures });
} catch (err) {
res.status(500).send({ error: 'Something failed!' })
}
});
Ajax
$("a.league-name").on("click", function (e) {
e.preventDefault();
var league_name = $(this).text().trim();
$.ajax({
url: '/league_fixtures',
type: 'POST',
dataType: "json",
data: { league_name: league_name },
success: function(fixtures){
// How do i get HTML from server into here ?
$('#panel_' + league_name).html(fixtures);
},
error: function(jqXHR, textStatus, err){
alert('text status '+textStatus+', err '+err)
}
})
});
});
I don't get any errors when I fire the ajax request but I also do not get any data or HTML updated in my div.
What am I doing wrong?
So I finally got a working solution:
index.js
app.post('/league_fixtures', async function (req, res) {
try {
const league_name = req.body.league_name;
const fixtures = await leagueFixtures(league_name);
const file = await readFile('./views/fixtures.ejs');
var fixture_template = ejs.compile(file, { client: true });
const html = fixture_template({fixtures: fixtures});
res.send({ html: html });
} catch (err) {
res.status(500).send({ error: 'Something failed!' })
}
});
ajax call
$.ajax({
url: '/league_fixtures',
type: 'POST',
dataType: "json",
cache: true,
data: { league_name: league_name },
success: function(fixtures){
var html = fixtures['html'];
$('#panel_' + league_name).html(html);
},
error: function(jqXHR, textStatus, err){
alert('text status '+textStatus+', err '+err)
}
})
Hey guys I have this simple handler that reads a mysql table and returns the json obj to the route like so.
handler
var PostStore = {};
PostStore.getAllPosts = function(){
conn.query('SELECT * FROM posts',function(err, result){
if(err){
console.log(err);
}
console.log(JSON.parse(JSON.stringify(result)));
return JSON.parse(JSON.stringify(result));
});
}
module.exports = PostStore;
router
{
path: '/',
method: 'GET',
handler: function (request, reply) {
console.log(PostStore.getAllPosts);
reply.view('index', {
title: 'My home page',
posts: PostStore.getAllPosts
});
}
}
index.html
<h1>{{title}}</h1>
{{#each posts}}
<h1>{{this.title}}</h1>
{{/each}}
Here is what the console output looks like
[Function]
[ { id: 1,
title: 'Hello World',
body: 'My First Post on this cool Hapi Blog!',
date: null } ]
As you can see the sql result is parsed in to a JSON obj but not read from handlebars. Also note that the {{title}} is displaying "My home page" as expected.
Any help would be much appreciated! Thank you.
PostStore.getAllPosts is async, you need to render the view inside it's callback function.
PostStore.getAllPosts(function (err, posts) {
// render the view
});
The only way to render async method in view is to call this methods in a pre handler and assign the return value so you can render the returned data inside the view. See here in hapi's documents for further explanation http://hapijs.com/api#route-prerequisites.
In PostStore routines this code
PostStore.getAllPosts = function(callback){
conn.query('SELECT * FROM posts',function(err, result){
if(err){
return callback(err);
}
return callback(result);
});
}
Then in handlers code
const getPosts = function (request, reply) {
... // do something async to set posts
PostStore.getAllPosts(function(err, results) {
if (err) {
return reply('Error occurred')
}
reply(results);
};
};
server.route({
method: 'GET',
path: '/',
config: {
pre: [
{ method: getPosts, assign: 'posts' }
],
handler: function (request, reply) {
reply.view('index', {
title: 'My home page',
posts: request.pre.posts,
});
}
}
});
We are using following JQuery code (within JSF) to invoke Autocomplete. Everything seems to work fine when user keys in data but when user copies and pastes Autocomplete will be invoked on second attempt. I am testing following code in IE 8. Any inputs are appreciated
<pre>
<code>
<script type="text/javascript">
$(function () {
$(document).on('keyup.autocomplete','##{resp.workItemResponse.wiResponseId}', function() {
$('##{resp.workItemResponse.wiResponseId}').autocomplete({
minLength: 3,
source: function( request, response){
$.ajax({
type: 'GET',
url: "/iaportal/autoCompleteServlet",
cache: false,
delay: 200,
data: {
'respId':'#{resp.workItemResponse.wiResponseId}',
'type': '#{autoCompleteType}',
'term':request.term
},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data){
response($.map(data.acctNum, function (item) {
return {
label: item.label,
value: item.label
}
}));
},
error: function(message){
alert("error "+message);
}
});
},
select: function( event, ui ) {
var selectedObj = ui.item;
var text = selectedObj.value;
$('.autoComplete#{resp.workItemResponse.wiResponseId}').attr('value', text);
$('.autoComplete#{resp.workItemResponse.wiResponseId}').trigger('change');
}
});
$('##{resp.workItemResponse.wiResponseId}').keyup(function(){
var text = this.value;
if(text == '' || text.length == 0){
$('.autoComplete#{resp.workItemResponse.wiResponseId}').attr('value', "");
$('.autoComplete#{resp.workItemResponse.wiResponseId}').trigger('change');
}
});
}); // on Ends
var textElem;
$(document).on('paste','##{resp.workItemResponse.wiResponseId}',function() {
textElem = this;
setTimeout(invokeOnPaste , 100);
});
function invokeOnPaste(){
var text = $(textElem).val();
if(text.length == 14){
$('.autoComplete#{resp.workItemResponse.wiResponseId}').attr('value', text);
$('.autoComplete#{resp.workItemResponse.wiResponseId}').trigger('change');
} else if(text.length != 0){
$('##{resp.workItemResponse.wiResponseId}').trigger('search','autocomplete');
}
}
});
</script>
</code>
</pre>