Using Grails 2.0.4 and FancyBox 2.
I am trying to render html in a modal or dialog popup in the grails framework. Currently I am attempting to do this with FancyBox 2. However I cannot seem to render the fancybox. Here is what I currently have.
Controller:
class TestController {
def index() { }
def createResult() {
render 'got here dude'
}
}
Exert from gsp:
<body>
//attempts to use fancy box but fails
<a class="fb" href="${createLink(action: 'createResult', controller: 'test') }" >Click Here</a>
//not fancy box, renders page only
<a class="not" href="${createLink(action: 'createResult', controller: 'test') }" >Click Here2</a>
<script type="text/javascript">
$(document).ready(function() {
$(".fb").fancybox();
});
</script>
</body>
By clicking on the top link I end up getting the following error:
Uncaught Error: Syntax error, unrecognized expression: /ModalTest/test/createResult
Does anyone have any suggestions on how to get this to work with grails or have another dialog/modal solution that will work by utilizing the controller?
Thank you in advance.
Add class fancybox.ajax, this should work, since you are trying to load ajax content:
<a class="fb fancybox.ajax" href="${createLink(action: 'createResult', controller: 'test') }" >Click Here</a>
Related
In my ruby on rails application, I'm generating a view via an ajax call.
I'm using following piece of code.
$("#a_div_id").html("<%= escape_javascript(render 'index')%>");
And the view I'm trying to render is _index.html.erb:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</div>
<script>
alert('first');
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
alert('second');
$scope.firstName = "John";
$scope.lastName = "Doe";
});
alert('third');
</script>
When I render the view, I'm getting only first and third messages. However, when I add this piece of code into dashboard.html.erb rather than rendering it via the ajax code, it perfectly works.
In the first case, I'm getting the following error.
angular.min.js:6 Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.4.8/$injector/modulerr?p0=myApp&p1=Error%3A%2…ogleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.4.8%2Fangular.min.js%3A20%3A274)
at angular.min.js:6
at angular.min.js:38
at n (angular.min.js:7)
at g (angular.min.js:37)
at eb (angular.min.js:41)
at c (angular.min.js:19)
at yc (angular.min.js:20)
at Zd (angular.min.js:19)
at HTMLDocument.<anonymous> (angular.min.js:294)
at fire (jquery.self-bd7ddd3….js?body=1:3233)
I'm be at my wits' end, I couln't decide what I'm missing,
Any suggestions,
Thanks.
Can you try without escape_javascript.
Also put a debugger like this, this will put a break point when chrome executes the js.
debugger;
$("#a_div_id").html("<%= render 'index' %>");
That would help you see what exactly jquery is trying to add as HTML.
If this doesn't work,
Probably you should take the js in script tag and put it in some method and call that method after you have added index to dom.
$("#a_div_id").html("<%= render 'index' %>");
myMethodToRenderAngular();
I've created a new asp.net MVC app in VS.NET 2013. In _Layout.cshtml, I have a reference to the angularjs library (Google developer site). I also define a controller called "con1" and create a variable.
_Layout.cshtml:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
<script type="text/javascript">
function con1($scope) {
$scope.somestring = "some string";
}
</script>
Index.cshtml:
<div>
{{1+1}}
</div>
The above works fine and renders the result of "2".
When I change the div to the following and start trying to access the somestring variable in the controller, I get the actual AnguarJS code rather than the result.
<div ng-controller="con1">
{{1+1}}
</div>
Output: "{{1+1}}"
Any idea why adding the controller reference breaks it? This seems to be VS.NET specific. I have a jsfiddle here that works fine: http://jsfiddle.net/jpswdzxu/. That is basically the output from the VS.NET project.
You need to define the Angular Application, or it won't work:
<script type="text/javascript">
var myApp = angular.module('myApp',[])
.controller('myAppCtrl', function($scope) {
$scope.somestring = 'teststring';
});
</script>
Then, the HTML should be:
<body ng-app="myApp">
<div ng-controller="myAppCtrl">
{{somestring}}
</div>
</body>
Or, using your jsfiddle, it would be:
<div ng-app="myApp" ng-controller="myAppController">
{{1+1}}
<br>
{{somestring}}
</div>
and:
angular.module('myApp',[])
.controller('myAppController', function ($scope) {
$scope.somestring = "some string";
});
Good Luck!
Happy new year to all,
I am working on a project where I have to show the details of each record in the "list" in a dialog (modal window) window while the user click the link on each record in the list. I am trying to accomplish this using the GrailUI plugin. Here is my code:
<gui:dialog width="300px"
controller="tag"
action="showTags"
params=" [id:userInstance.userId]"
update="dialogData"
draggable="true"
triggers="[show:[type:'link', text:'Show Tags', on:'click']]"
modal="true">
<div id='dialogData'>This will be updated by the controller action....</div>
For some reason the dialog tag is not firing the controller action. It opens the dialog window, but shows just this message "This will be updated by the controller action....". It's not showing the controller action rendered output(view). Could someone help me to understand what I am doing wrong?
Jquery and jquery-ui are the other plugins I am using in my project.
Appreciate your help.
Edit
def test(Integer max) {
....
....
userInstanceList = User.list(params)
render (view: "test", model: [userInstanceList: userInstanceList, userInstanceTotal: User.count()])
}
def showTags () {
def user = User.findByUserId(params.id)
def tagInstanceList = user.tags
render(view: "test", model: [tagInstanceList: tagInstanceList])
}
If you want something be submit to remote you need to set form="true". Then any form elements can be placed inside the dialog tag without defining a form. When form="true", the dialog creates its own form.
Here is a example I have tested:
test.gsp:
<html>
<head>
....
<r:require modules="grailsui-dialog"/>
</head>
<body class="yui-skin-sam">
<gui:dialog width="300px"
controller="test"
action="showTags"
params=" [id:userInstance.userId]"
form="true" <!-- the key to remote submit -->
update="dialogData"
draggable="true"
triggers="[show:[type:'link', text:'Show Tags', on:'click']]"
modal="true" >
<!-- You can put any input element here, which will be submitted in the form-->
<div id='dialogData'>This will be updated by the controller action....</div>
</gui:dialog>
</body>
</html>
TestController:
class TestController {
def test() {
.........
}
def showTags() {
def user = User.findByUserId(params.id)
def tagInstanceList = user.tags
render(template: "ajaxResponse", model: [tagInstanceList: tagInstanceList, user:user]) //render a template, not a view
}
For an Ajax request, you can not render a view, which will replace the original page. Instead, you should send back a template with the tags you want to show in the dialog:
_ajaxResponse.gsp
<h3>Tag List of user ${user.username}</h3>
<g:each in="${tagInstanceList}" var="tag">
<p>${tag}</p>
</g:each>
I'm using backbone jquery mobile and coffee script to develop a simple twitter application. My problem is the jquery mobile styles are failing to render. My View is
class HomeView extends Backbone.View
constructor: ->
super
initialize: ->
#Twitter= new TwitterCollection
template: _.template($('#home').html())
render: ->
#loadResults()
loadResults: ->
#Twitter.fetch({
success: (data) =>
$(#.el).html(#template({data: data.models, _:_}))
error: ->
alert('Error!')
})
This works fine in terms of pulling information from Twitter, however when
$(#.el).html(#template({data: data.models, _:_}))
is within the fetch function, jquerys styles do not render. Can anyone show me how to refresh the styles? Help would be much appreciated!
For reference, the html template is:
<script type="text/template" id="home">
<div data-role="header" data-position="fixed">
<h1>TWITTER DATA</h1>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true">
<% _.each(data, function (row) { %>
<li><%= row.get('text') %></li>
<% }); %>
</ul>
</ul>
</div>
Ok, I fixed it by adding ".listview('refresh').trigger('create');" to the end of
$(#.el).html(#template({data: data.models, _:_}))
When the fix is applied afterwards (after the view page has been rendered and displayed by $.mobile.changePage()) the user gets an unpleasant side-effect: the view flickers due to the change of style applied by jquery mobile.
My solution to the problem was to trigger custom event from the view once the dynamic rendering is complete and bind the $.mobile.changePage() to that event. This causes the output to be "buffered" until complete and then styled altogether.
Here's an example:
In the initialize function of my view I have code waiting for an event to be fired by the model/collection when fetched and a function to render the dynamic part of the html:
window.MyView = Backbone.View.extend({
// some other code here
initialize: function() {
this.listenTo(this.collection, "fetchCompleted:CollectionName", this.renderRows);
},
renderRows: function (eventName) {
$(this.el).find('div[class="content-primary"]').html(this.template_ul({data: this.collection}));
this.trigger( 'view:ready' );
},
//...
... then in the router I have the following code for the changePage():
myViewObject.on( 'view:ready', function() {
$.mobile.changePage($(next.el), {changeHash:false, transition: transition});
});
In my Grails controller I'm responding to an AJAX call and using render to return the text:
def ajaxRandomPersonName = {
def person = get a random person ...
render "Name: ${person.name}"
}
The problem is that render renders the whole template. So instead of just rendering "Name: John" it renders all the icons, navigation, etc defined in the template. How do I get render to just render without the template?
I'm pretty much following Chapter 1 of "Grails in Action" (page 28) using Grails 1.1.1.
Follow up:
Returning false per Rhysyngsun's suggestion has no impact. I also tried setting the template to null but it still renders the template:
def ajaxRandomPersonName = {
def person = get a random person ...
render (template:null, text:"Name: ${person.name}")
}
render has its heart bent on rendering it through the template no matter what I do.
Follow up 2: Parallel discussion on grails-user mailing list.
Follow up 3: Sample code:
I paired down my code the bare minimum and it still exhibits the undesired template rendering.
controllers/PersonController.groovy:
class PersonController {
def index = { }
def home = { [message:"Hello"] }
def ajaxTest = {
println "ajaxTest called"
render text: "ajax message"
}
}
views/person/home.gsp (view page for home method)
<html>
<head>
<title>Home View</title>
<g:javascript library="prototype" />
</head>
<body>
<p>
<g:remoteLink action="ajaxTest" update="test1">ajax call</g:remoteLink>
</p>
<p>Message = ${message}</p>
<p id="test1">Blank</p>
</body>
</html>
views/layouts/person.gsp (layout template for person controller)
<html>
<head>
<title>Test App - <g:layoutTitle/></title>
<g:layoutHead/>
</head>
<body>
<h1>Test App</h1>
<g:layoutBody/>
</body>
</html>
I access person controller with the home view:
http://localhost:8080/test/person/home
the page renders as:
Test App
ajax call (hyperlink)
Message = Hello
Blank
"Test App" is from the template. When I click "ajax call" it makes an asynchronous call to PersonController's ajaxTest method (verified with println). All ajaxTest does is println and render static text. This resultant in the following:
Test App
ajax call
Message = Hello
Test App
ajax message
Note that the template is being rendered within "test1" <p> which results in the second "Test App".
I'm running Grails 1.1.1. Any ideas? The code seems straightforward. I downloaded the Grails source and looked at RenderDynamicMethod.java. It doesn't do any template rendering unless template is in the argument list, which it isn't. So my only guess is something up steam is rendering the template again.
Resolved: Adding contentType results in the template not being rendered:
render text: "Name: ${person.name}", contentType: "text/plain"
Make your client side javascript code handle a JSON respond and render your response with:
render [text:"Name: ${person.name}"] as
JSON
You might be getting burnt by the 'layout-by-convention' feature in Grails. If your layout name matches the controller name prefix, for example, Grails will apply the layout to every view managed by that controller. Unfortunately, it even applies to text and templates. There are currently a few JIRAs logged regarding this (see http://jira.grails.org/browse/GRAILS-7624 for example).
I got burnt by this today. I resolved it by simply renaming my layout gsp such that it doesn't match any controller name. My layout was initially named 'storefront.gsp' and I have a controller named StorefrontController. I renamed the layout to 'public.gsp'.
We've found that explicitly returning false from the action fixes this.
I believe doing render foo as JSON returns false implicitly.