Grails RemoteFunction creates bad javascript - javascript

I am taking over a project from an engineer that left my company, and am having to quickly come up to speed on Grails, so if this is a noob question, well, I'm a noob.
In one of one of my GSP files, I've got a remoteFunction call in the middle of a javaScript function:
function fnCreateEntitiesPerForceChart() {
var interval = $("#entitiesPerForceTimeIntervalSelect").val();
var url = '${createLink(controller: 'federation', action: 'createEntitiesPerForceChart')}?interval='+escape(interval);
$("#entitiesPerForceChart").attr("src", url);
${remoteFunction(controller: 'federation',
action: 'getEntitiesPerForceTable',
params: '\'interval=\'+interval',
onSuccess: 'fnUpdateEntitiesPerForceTable(data,textStatus)')};
}
That remoteFunction call is being sent to the client as:
try{DojoGrailsSpinner.show();}catch(e){} dojo.xhr('Get',{content:{'interval='+interval}, preventCache:true, url:'/FederationReporter/federation/getEntitiesPerForceTable', load:function(response){ fnUpdateEntitiesPerForceTable(data,textStatus); }, handle:function(response,ioargs){try{DojoGrailsSpinner.hide();}catch(e){} }, error:function(error,ioargs){try{DojoGrailsSpinner.hide();}catch(e){} } });;
Which is causing a error:
SyntaxError: missing : after property id
...){} dojo.xhr('Get',{content:{'interval='+interval}, preventCache:true, url:'/Fed...
federation (line 400, col 60) (which is the bolded '+' before the second 'interval'
What am I missing?

Dojo content should be a key-value pair.
{content:{'interval': interval}

Related

Vue.js - Trouble displaying results from API call in component

Experimenting with Vue.js, trying to display results from a Wikipedia API call in a component using the v-for directive, but something is not working on the back end and I don't know what it is.
Link to the jsFiddle
HTML
<div id="app">
<input type="text" v-model="searchTerm" v-on:keyup="getResults">
<searchResult
v-for="item in results"
v-bind:result="item"
v-bind:key="item.key"
></searchResult>
</div>
Javascript
new Vue({
el: '#app',
data: {
api: "https://en.wikipedia.org/w/api.php?",
searchTerm: 'Ron',
searchDataString: "action=opensearch&format=json&origin=*&uselang=user&errorformat=html&search="+this.searchTerm+"&namespace=0%7C4&limit=20&profile=fuzzy",
searchCall: this.api+""+this.searchDataString,
results: []
},
methods: {
getResults() {
this.searchCall = this.api+"action=opensearch&format=json&origin=*&uselang=user&errorformat=html&search="+this.searchTerm+"&namespace=0%7C4&limit=20&profile=fuzzy";
//console.log( this.searchCall );
axios.post( this.searchCall )
.then(response => { this.processResults(response.data) });
},
processResults(data) {
//console.log( data );
for(var i = 0; i < data[1].length; i++) {
var resultItem = { key:i, link:data[3][i], name:data[1], description:data[2][i] };
this.results.push(resultItem);
console.log(resultItem);
}
}
}
});
Vue.component( "searchResult", {
props:['result'],
template: "<a target='_blank' href='{{ result.link }}'><div class='search-result'><h3>{{ result.name }}</h3><p>{{ result.description }}</p><div></a>"
});
The two issues on my mind are
the error message that shows in the console when typing input, and
that the array of results is creating empty objects instead of passing the data
When I look at the array in the console, all it shows are getters and setters. I'm new to this, so maybe that's what it's supposed to be doing.
I'm so close to getting this working, but I'm at my wits end, help is much appreciated.
The problem with your code is that html tags aren't case sensitive so naming a component searchResult causes issues. If you need to use searchResult, you'll have to use <search-result> in your template. I find it better just to avoid the problem altogether and give components lower-case names. Here are docs about the issue: https://v2.vuejs.org/v2/guide/components.html#Component-Naming-Conventions
You mentioned "the error message that shows in the console when typing input". I didn't get any errors copying and pasting your code (other than forgetting to include axios). What error are you getting?

AttributeError: 'unicode' object has no attribute 'get' - In Django Forms

I'm trying to use Django Forms with Ajax Calls.
Previously I just used a html form that I could get all the information through request.POST['item']. But I've been thinking about validators, and I would benefit if I switched normal html forms into Django forms.
In my HTML code (the page where the user clicks, and a AJAX calls another view with javascript):
if not request.user.is_authenticated():
#Tells the user to login if not authenticated
return redirect('/webapp/login.html')
else:
#Get Logger
logger = logging.getLogger('views.logger.chartConfigure')
logger_uuid = uuid.uuid4()
logger_time = datetime.datetime.now()
#Log the User
logger.info("Request in editChart, User:" + str(request.user.username) + ", UUID:" + str(logger_uuid) + ", Time:" + str(logger_time))
#Forms to use
chartName = changeChartNameForm(auto_id=False)
#Put Forms into a context
context = {'chartNameForm': chartName}
#Return the context
return render(request, 'webapp/editChart.html', context)
The Forms that are used is a changeChartNameForm:
#Form for editing chart names
class changeChartNameForm(forms.Form):
#Only one variable which is called chartName, with label set to ""
#Since I don't want any labels. I have my own in HTML.
chartName = forms.CharField(max_length=100, label="")
#form-control is an extra class that is required by bootstrap 3, and the html id
#of the form is called chartName
chartName.widget.attrs['class'] = 'form-control'
chartName.widget.attrs['id'] = 'chartName'
HTML Code:
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="newChartName" >New Chart Name</button>
</span>
{{ chartNameForm }}
</div>
The Javascript code:
$.ajax(
{
type:"POST",
url:"ajax_postColumnAction/",
datatype: 'json',
data:
{
'csrfmiddlewaretoken':csrftoken,
'currentTabSelected':currentTabSelected,
'currentColumnSelected':currentColumnSelected,
'action':'changeName',
'changeNameForm':$('#chartName').serialize()
},
success: function(response)
{
...Some logic happens here
}
}
basically the javascript code will call this view, called ajax_postColumnAction:
#Get the name form, and get the newName
changeNameForm = changeChartNameForm(request.POST['changeNameForm'])
newName = ""
if(changeNameForm.is_valid()):
newName = changeNameForm.cleaned_data['chartName']
The return is always:
'unicode' object does not have the attribute 'get' at the following line: if(changeNameForm.is_valid())
I have tried the following:
using data=request.POST
using data=request.POST['changeNameForm']
Full Traceback:
Traceback (most recent call last):
File "C:\Users\Desktop\Dropbox (Personal)\Django\Dashboard_Web\WebApp\views.py", line 738, in ajax_postColumnAction if(changeNameForm.is_valid()):
File "C:\Python27\lib\site-packages\django\forms\forms.py", line 129, in is_valid return self.is_bound and not bool(self.errors)
File "C:\Python27\lib\site-packages\django\forms\forms.py", line 121, in errors self.full_clean()
File "C:\Python27\lib\site-packages\django\forms\forms.py", line 273, in full_clean self._clean_fields()
File "C:\Python27\lib\site-packages\django\forms\forms.py", line 282, in _clean_fields value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
File "C:\Python27\lib\site-packages\django\forms\widgets.py", line 207, in value_from_datadict return data.get(name, None) AttributeError: 'unicode' object has no attribute 'get'
Edit:
When I Do:
print request.POST['changeNameForm']
I get chartName = "some text I typed in the browser"
This part of the error says that data is an unicode string:
return data.get(name, None) AttributeError: 'unicode' object has no attribute 'get'
data needs to be an object. Instead, it is a string, and strings don't have a get() method, and don't have name attributes as the error trace back says.
Try going off of the Django Docs to properly call the AJAX:
https://docs.djangoproject.com/en/1.6/topics/class-based-views/generic-editing/#ajax-example
It seems that a workaround is to construct the form in the view.
I've looked at tenths and hundreds of StackOverFlow posts and Google websites, and non seem to have my problem.
The method is to recreate the form when you get the POST data, since a form uses a dictionary as a constructor.
changeNameForm = changeChartNameForm({request.POST['changeNameForm'].split("=")[0]}):request.POST['changeNameForm'].split("=")[1]})
I know that request.POST['changeNameForm'] returns a string "chartName=someName". I split the string with "=", and I would get someName, and chartName. Hence I would put someName into a dictionary, with the key called chartName.
{'chartName':'someName'}
Hence the form is recreated with the post data and finally passes is_valid.

Meteor template isn't rendering properly

I'm building a notifications page, where the user can see which posts have comments, and I want to display the date of each post, but it's not working.
Here is the code:
<template name="notification">
<li>Someone commented your post, {{postDate}} </li>
</template>
Template.notification.helpers({
notificationPostPath: function() {
return Router.routes.PostPage.path({_id: this.postId});
},
post: function () {
return Post.findOne({_id: this.postId});
},
postDate: function() {
return moment(post.submitted).format('dddd, MMMM Do');
}
});
The console prints this: Exception from Deps recompute: ReferenceError: post is not defined.
Thanks in advance
I assume the error is being flagged on the following line:
return moment(post.submitted).format('dddd, MMMM Do');
Note that you can't refer to helpers from within other helpers like that (and anyway, post is a function) - you need too add another line at the start of the postDate helper like this:
var post = Post.findOne({_id: this.postId});

Twitter like "x new tweets" with .arte or .ajax?

I've found this great example to implement a twitter like "x new tweets" http://blog.hycus.com/2011/03/14/realtime-updates-like-twitter-using-phpmysqljquery/
In this example the .arte jQuery plug-in is used. However I think it can be done just as the same with .ajax and I've coded as:
$.ajax({
url:'async.php? main='+$('.boxOfMainPage:first').attr('id'),
success:function(results)
{
if(results!='')
{
if(results.indexOf('boxOfMainPage')>=0)
$('#tweetEveryone').prepend(results);
else
$('#newTweet').html("<center><a href=''>I found "+results+" new tweets</a></center>").show();
}
}
});
This checks the results and loads the result to tweetEveryone. Async.php simply makes a mysql_query and brings the new results. I've actually done exactly the same with the example however when I click the 'new tweet's like it sometimes causes a postback. In the example I haven't experience it. Can it be because of the difference between .arte and .ajax ?
It's nothing about the differences between arte and ajax (in fact and in a short way, arte is ajax that is called with an interval, trying to do something like "long polling")
So, u have a link without href value, this must "reload" ur page, ie, it will perform a GET request to the actual URL in window.location. A postback performs a POST request, this is really happening?
--- edited ---
If you wanna to do the same effect from twitter, it's simple.. In async.php, instead u write an link element that shows how many tweets has after the old state, make this page write a JSON object with all tweets, then, ur ajax function must get this JSON and convert it into a JS object. With this object, u'll be able to count how many updates u have to show and exactly which are they.
So, ur function could be like this (assuming that "#boxOfMainPage" is ur tweets container):
$.ajax({
url : 'async.php?main='+$('.boxOfMainPage:first').attr('id'),
success : function (tweets) {
window.NEW_TWEETS = tweets;
if ( NEW_TWEETS && NEW_TWEETS.length ) {
$('#newTweet').html("<center><a href='#' onclick='showNewTweets()'>I found "+NEW_TWEETS.length+" new tweets</a></center>").show();
}
}
});
The showNewTweets functions will be:
function showNewTweets() {
if ( window.NEW_TWEETS && NEW_TWEETS.length ) {
$('#newTweet').hide().html("");
for ( tweet in NEW_TWEETS ) {
$("#boxOfMainPage").prepend(buildTweetHTML(tweet));
}
}
}
And buildTweetHTML:
function buildTweetHTML(tweet) {
var $tweetElm = $("<div class='tweet'>");
$tweetElm.append("<h2>"+tweet.user+" said:</h2>");
$tweetElm.append("<p>"+tweet.content+"</p>");
$tweetElm.append("<p class='time'>"+tweet.time+"</p>");
return $tweetElm;
}
Finally, async.php should write JSON object like this:
[
{ user : 'Rafael', content : 'The content from tweet', time : 'X time ago' },
{ user : 'George', content : 'The content from tweet', time : 'Y time ago' }
{ user : 'Jack', content : 'The content from tweet', time : 'H time ago' }
]

JQuery-Ui Autocomplete not displaying results

I am trying to display autocomplete results for a list of managers. I have the following code:
Application.js
function log(message) {
$( "<div/>" ).text( message ).prependTo("#log");
}
$("#managers").autocomplete({
source : function(request, response) {
$.ajax({
url : "/managerlist",
dataType : "json",
data : {
style : "full",
maxRows : 12,
term : request.term
},
success : function(data) {
var results = [];
$.each(data, function(i, item) {
var itemToAdd = {
value : item,
label : item
};
results.push(itemToAdd);
});
return response(results);
}
});
}
});
Project controller
def manager_list
list=Project.all.map{|i|i.manager_user_id}
arr= [].concat(list.sort{|a,b| a[0]<=>b[0]}).to_json
render :json =>arr
end
Routes.rb
match '/managerlist' => 'projects#manager_user_id'
_form.html.erb
<p>
<%= f.label :manager_user_id %><br />
<input id="managers" />
</p>
The following code is fine, I don't recieve no errors in firebug. However when I try to enter a managers name for example James Johnson the name won't appear. I have also tried putting the whole function in the _form.html.erb and wrapped it in tags this didn't work. Is there any idea why this is happening
So I've managed to fix my error, which was because of the ordering of Jquery core and Jquery ui.
I've got the managers to be listed. In the image below.
From the image it can be seen that when I type 'Arm' it brings the entire list of managers, when it should display 'Deshawn Armstrong'. I understand that this is most probably to do with my project controller below
Project controller
def manager_list
list=Project.all.map{|i|i.manager_user_id}
arr= [].concat(list.sort{|a,b| a[0]<=>b[0]}).to_json
render :json =>arr
end
Check the response in the Firebug console and make sure the string is in proper json format for the autocomplete.
It appears that you are just returning an array. The dataType setting in .ajax doesn't convert to json; it's just expecting that format back. If you are not sending json back from your url : "/managerlist", this may be the problem.
Actually, provided your ajax function is working correctly, you could just:
return response(JSON.stringify({ results: results }));
jsfiddle example of JSON.stringify: http://jsfiddle.net/xKaqL/
Based on your new information, you need to add a minLength option to your autocomplete.
$("#managers").autocomplete({
minLength: 2, // 2 or whatever you want
// rest of your code

Categories

Resources