I am working on an rails application to manage and present images to friends and family.
In that application you can have
Events -> Subevents -> EventImages
routes.rb
resources :events do
resources :subevents do
resources :event_images
end
end
The angularjs part/page is starting when a user selects an specific event.
On the event edit page i want to present the subevents and images like that:
Subevent1 -> Upload Images Button
Image1 Image2 Image3 ...
Subevent2 -> Upload Images Button
Image1 Image2 Image3 ...
...
New Subevent Button
So basically i want to present all available subevents and the images inside each subevent on one page (there could be several subevents and several 100 images). The user should be able to add new subevents and to upload or delete images to each subevent and moving images between subevents via drag/drop. But adding/deleting/uploading/mowing is not my problem right now i just mentioned it because it might influence the solution to my problem.
Im using a nested ng-repeat to display all the information on the page
<div class="subevent" ng-repeat="subevent in event.subevents">
<li class="img" ng-repeat="image in subevent.event_images">
</li>
</div>
Im new to the angular world and im having problems now on how to retrieve the data i need for the page mentioned above.
I came up with two ideas so far:
Retrieve all the informations via an api controller in an nested form:
show.json.jbuilder
json.id #event.id
json.subevents #event.subevents do |subevent|
json.id subevent.id
json.name subevent.name
json.event_images subevent.event_images do |event_image|
json.id event_image.id
json.thumb event_image.image({ resize: "150x150" }).url
end
end
Which will give me this:
{
"id": "54d75dd9686f6c2594020000",
"subevents": [
{
"id": "54d75de1686f6c2594030000",
"name": "Test",
"event_images": [
{
"id": "54df3904686f6c41cf0c0000",
"thumb": "/uploads/event_image/54df3904686f6c41cf0c0000/ebd83a10e03f9794f46cda02fdbc84d3.jpg"
},
{
"id": "54df56c5686f6c41cf850100",
"thumb": "/uploads/event_image/54df56c5686f6c41cf850100/ebd83a10e03f9794f46cda02fdbc84d3.jpg"
}
]
}
]
}
And im using restangular to retrieve this information
$scope.event = Restangular.one('api/events','<%= #event.id %>').get().$object;
But this solution doesnt feel right to me. When i start to manipulate the page (uploading new images/deleting images/moving images from one subevent to another) i see myself refreshing the complete page because i see no other way here on how to just delete one image for example without reloading the complete $scope.event to get the updated page.
The other solution which came to my mind but i did not get working so far was to use the nested features of restangular to retrieve all the needed information for my page without having to create a seperate api controller.
$scope.event = Restangular.one("events",'<%= #event.id %>').all("subevents").all("event_images");
I could not find a working solution which would let me iterate over the $scope.event with ng-repeat like i did above and im not sure if this would solve my overall problem.
So the questions i would like to have answered are:
Should i stick to the API controller appreaoch or is there a way to make my second idea working to get rid of the api controller ?
How do i manipulate the images/subevents without having to reload everything ? ( an example of deleting an image on the page would be great )
This answer your second question using your current API
Plunker
app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.event = {
"id": "54d75dd9686f6c2594020000",
"subevents": [
{
"id": "54d75de1686f6c2594030000",
"name": "Test",
"event_images": [
{
"id": "54df3904686f6c41cf0c0000",
"thumb": "/uploads/event_image/54df3904686f6c41cf0c0000/ebd83a10e03f9794f46cda02fdbc84d3.jpg"
},
{
"id": "54df56c5686f6c41cf850100",
"thumb": "/uploads/event_image/54df56c5686f6c41cf850100/ebd83a10e03f9794f46cda02fdbc84d3.jpg"
}
]
}
]
};
});
app.directive('myEvent', function(){
return {
scope: { myEvent: '=' },
template: "<div>{{myEvent.id}}<div my-subevent='subevent' ng-repeat='subevent in myEvent.subevents'></div></div>",
controller: function($scope){
this.removeSubevent = function(e){
$scope.myEvent.subevents.splice($scope.myEvent.subevents.indexOf(e), 1);
};
}
};
});
app.directive('mySubevent', function(){
return {
scope: {mySubevent: '='},
template: "<div>{{ mySubevent.name }} <a href='' ng-click='remove()'>remove subevent</a><div my-subevent-img='img' ng-repeat='img in mySubevent.event_images'></div></div>",
require: '^myEvent',
link: function(scope, ele, attrs, myEventCtrl){
scope.remove = function(){
myEventCtrl.removeSubevent(scope.subevent);
};
},
controller: function($scope){
this.removeImg = function(img){
$scope.mySubevent.event_images.splice($scope.mySubevent.event_images.indexOf(img), 1);
};
}
};
});
app.directive('mySubeventImg', function(){
return {
scope: { mySubeventImg: '=' },
template: "<div><img ng-src='mySubeventImg.thumb'><a href ng-click='remove()'>remove img</a></div>",
require: '^mySubevent',
link: function(scope, ele, attrs, mySubeventCtrl){
scope.remove = function(){
mySubeventCtrl.removeImg(scope.mySubeventImg);
};
}
};
});
index.html
<div my-event="event"></div>
Related
I am using jquery datatable in asp.net mvc and i want to show a submit button which will be saving the data to the database only if there is atleast one row in the datatable.
I am trying this code, however its not working
<tr id="trbtnSubmit">
<td colspan="9" align="center">
<input type="submit" name="btnSubmit" value="Save"
class="btn btn-edit btn-text" />
</td>
</tr>
<script>
var PopUp, dataTable;
$(document).ready(function () {
dataTable = $("#tblCustomerList").DataTable({
"ajax": {
"url": "/Customer/GetCustomers",
"type": "GET",
"data": "json"
},
"lengthChange": false,
"pageLength": 10,
"columns": [
{ "data": "Number" },
{ "data": "Name" },
{ "data": "fileName" },
{ "data": "mD5Hash" },
{ "data": "dataSizeInGB" },
{
"data": "Id",
"render": function () {
return "<a href='#'><i class='fa fa-eye'></a></i><a href='#' style='margin-left:5px'><i class='fa fa-pencil'></i></a><a href='#' style='margin-left:5px'><i class='fa fa-trash'></a></i>";
},
"orderable": false,
"width": "40px"
},
],
"language": {
"emptyTable": "No Customers , click on <b>New Customer</b> to add Customers"
}
});
var table = $('#tblCustomerList').DataTable();
if (!table.data().any()) {
$('#trbtnSubmit').hide();
} else {
$('#trbtnSubmit').show();
}
});
</script>
Since you didn't specify the version of datatables, I assume it's v1.10.
And there are 2 side notes I want to make before going into your problem:
Difference between .datatable() and .DataTable()
Enable server-side processing
Difference Between .datatable() and .DataTable()
I saw you declared another variable, var table, at the bottom of your sample code to get another instance of DataTables and check if there is any data? You actually don't need to.
.DataTable() returns a DataTables API instance, while .datatable() returns a jQuery object.
So if you intent to make usages on the DataTables APIs after you initialize the table, you can just use the varirable you declared from the beginning, var dataTable since you used .DataTable() way.
Enable Server-side Processing
Server-side processing is enabled by turning on the serverSide option, and configuring the ajax option. You're missing the first one, whose default is false.
So you might need to add serverSide option in your code:
dataTable = $("#tblCustomerList").DataTable({
serverSide: true,
ajax: {
...
},
...
});
Enough said. Now looking at your problem ...
DataTables Callbacks
There are many ways to achieve what you want to do, and I like to use callbacks so that you can configure your DataTables in one place.
There are lots of callbacks you can use, and the one I would use is drawCallback:
dataTable = $("#tblCustomerList").DataTable({
serverSide: true,
...,
language: {
emptyTable: "No Customers , click on <b>New Customer</b> to add Customers"
},
drawCallback: function(settings) {
$('#trbtnSubmit').toggle(settings.aoData.length > 0);
}
});
Hopefully my code is readable enough without any additional explanations :)
I am new to backbone and am using backbone in my rails application . This is what I am doing in my application
I am using Backbone Paginator for pagination support in my application as well using Gmaps for rendering locations on gmaps , for each time I am displaying 5 records from the server with pagination and displaying corresponding 5 location in map view , so now I need to show the remaining locations on map when I click on paginated links (prev page , next page) , I think I need to write some click events , but I am not sure where to write and how to write this events , Can any one please help me . please review the code below I have written evnets but those are not working
Thanks in advance
var Listings = Backbone.PageableCollection.extend({
model: Bdemo.Models.Listing,
mode: "server" ,
url: '/listings' ,
events: {
"click #paginationSelect" : "fetchSelectedData"
},
fetchSelectedData: function(){
console.log("CAMEEEEEEEEEEEEEEEEEEEEEEEEEEE")
},
// Initial pagination states
state: {
pageSize: 3,
/* sortKey: "updated",*/
order: 1
},
queryParams: {
totalPages: null,
totalRecords: null,
sortKey: "sort"
},
parseState: function (resp, queryParams, state, options) {
return {totalRecords: resp.total_pages};
},
parseRecords: function (resp, options) {
return resp.listings;
}
});
#ratnakar:
All you need is events function. Set an id for each of your paginated links. Then include the events function. I hope that you're developing SPA(single page application). With that note assume the following settings.
In the homeview.js("templates" folder) page include the paginated links enclosed by the footer tag.
<footer>
<button id="prevPage">previous</button>
<button id="nextPage">next</button>
</footer>
then the go to the corresponding homeview.js view file("views" folder)
backboneApp.Views.homeview = Backbone.View.extend({
//Default "events" function for handling delegate events.
events:{
//catching click events
"click #prevPage" : "goPrevious" //on click of DOM which has id as prevPage, calling a function goPrevious.
"click #nextPage" : "goNext" //same as above call goPrevious function.
},
//Defining the user created function goPrevious and goNext.
goPrevious: function(){
//Make your server call here.... for the previous 5 records.
},
goNext: function(){
// server call here for the next 5 records.
}
});
Thus the basic idea of using delegate events for paginated links is defined above.
From your question I understand that you are using backgrid-paginator in server mode.
Binding to the click event won't work, because you need to make sure that the models have been fetched from the server before you can access their data.
You can bind to your collections' request event and act on the xhr.done()
In your view:
initialize: function() {
this.listenTo(this.record_collection, "request", this.onCollectionRequested);
},
onCollectionRequested: function(collection, xhr, options) {
_this = this;
xhr.done(function(){
_this.showRecordLocationsOnMap(collection);
})
},
showRecordLocationsOnMap: function(records) {
/* Update your map here */
}
Hi finally solved this by calling my own function(callGmap) from Backbone.PageableCollection , here is my new code
var Listings = Backbone.PageableCollection.extend({
model: Bdemo.Models.Listing,
mode: "server" ,
url: '/listings' ,
events: {
"click #paginationSelect" : "fetchSelectedData"
},
fetchSelectedData: function(){
console.log("CAMEEEEEEEEEEEEEEEEEEEEEEEEEEE")
},
// Initial pagination states
state: {
pageSize: 3,
/* sortKey: "updated",*/
order: 1
},
queryParams: {
totalPages: null,
totalRecords: null,
sortKey: "sort"
},
parseState: function (resp, queryParams, state, options) {
return {totalRecords: resp.total_pages};
},
parseRecords: function (resp, options) {
callGmap(resp.hash);
return resp.listings;
}
});
I have a page with a button that will change the state of the resource on the server. Everything is wired up and working fine. But I had to resort to a server response that sent the browser "back" because I don't want to display a new template for the action url.
This seems like a typical thing to do: ask the server to do something, then get the current state of the resource and redisplay it in the current template without refetching the template.
The markup on the page is like this:
<a ng-href="/api/preference/{{video._id}}/add_to_watchlist" data-method="get">
<i rel="tooltip" data-original-title="Add to watchlist" class="icon-3x action-icon
icon-plus-sign" ng-class="{iconSelected : video.user_watchlist == 1}">
</i>
</a>
This highlights the icon depending on the value of $scope.video.watchlist. When clicked it fires a custom action on the server to add the video being viewed to the current user's watchlist. The url created is /api/preference/{{video._id}}/add_to_watchlist, this fires the server controller, which does the right thing but instead of going to a template for /api/preference/{{video._id}}/add_to_watchlist the server responds by telling the client to go "back" in Rails this is redirect_to :back.
Clearly this is wrong. It works but refetches the entire page markup and data.
The AngularJS controller that loads the original data is here:
GuideControllers.controller('VideoDetailCtrl', ['$scope', 'Video',
function($scope, Video) {
var pattern = new RegExp( ".*/([0-9,a-f]*)", "gi" );
//ugh, there must be a better way to get the id!
$scope.video = Video.get({ id: pattern.exec( document.URL )[1] });
}
]);
Here is the resource that gets the json
var VideoServices = angular.module('VideoServices', ['ngResource']);
VideoServices.factory('Video', ['$resource',
function($resource){
return $resource("/api/videos/:id", {id: "#id"}, {
update: {method: "PUT"},
query: {
isArray: true,
method: "GET",
headers: {
"Accept": "application/json",
"X-Requested-With": "XMLHttpRequest"
}
},
get: {
isArray: false,
method: "GET",
headers: {
"Accept": "application/json",
"X-Requested-With": "XMLHttpRequest"
}
}
});
}
]);
Somehow I need to
tell the server to add_to_watchlist without changing the browser URL
trigger a refetch of the video json without reloading the template.
It seems like you're relying on routing to handle a model update on the server, instead of doing it through angular's $resource service. Here's a quick and dirty:
Instead of routing, call a function when the user clicks:
<a ng-click="addToWatchlist(video._id)">
<i rel="tooltip" data-original-title="Add to watchlist" class="icon-3x action-icon
icon-plus-sign" ng-class="{iconSelected : video.user_watchlist == 1}">
</i>
</a>
Add the click handler function to your controller (I'm using $http here, but you would be better off adding a custom action to your Video resource). On the success callback you can reload the video. Or, better yet, you can return the video from the add_to_watchlist action.
Check out http://docs.angularjs.org/tutorial/step_07 which explains the $routeParams (to answer your comment about getting the video id).
GuideControllers.controller('VideoDetailCtrl', ['$scope', '$http', '$routeParams', 'Video',
function($scope, $http, $routeParams, Video) {
$scope.video = Video.get({ id: $routeParams.videoId });
$scope.addToWatchlist = function(videoId) {
$http.get('/api/preference/'+videoId+'/add_to_watchlist').success(function() {
$scope.video = Video.get({ id: $routeParams.videoId });
};
};
}
]);
I am using datatables and charts. I would prefer to return standard data through the model but cant for some odd reason, and the controls only seem to work with Json. Perhaps it's just my understanding. But at this point I am completely lost.
What I want to do is actually (in theory) quite simple.
Action result 1 returns a table which has paged data to a view as a Json result because that is what datatables require. This works fine.
Here are the controller actionresults for this:
public ActionResult AjaxVitalsHandler()
{
return PartialView();
}
[HttpPost]
[AccessRequired(AccessFeature.Vitals, AccessLevel.Read)]
public ActionResult AjaxVitalsHandler(JQueryDataTableParamModel param)
{
int start = param.iDisplayStart;
int perPage = Math.Min(param.iDisplayLength, 100);
int currentPage = (start / perPage) + 1;
int id = _accountSession.CurrentUserId;
//...Bunch of code here to do basic queries and get the data...All working fine.
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = model.TotalItemCount,
iTotalDisplayRecords = model.TotalItemCount,
aaData = result
});
}
Here is the corresponding partial view (This is a partial view loaded into a main view with RenderAction, nothing special):
<table class="table table-striped table-bordered table-hover"
id="vitalsTable"
data-request-url="#Url.Action("AjaxVitalsHandler")">
<thead>
<tr>
<th class="hidden-480">Date</th>
<th class="hidden-480">Weight (kg)</th>
<th class="hidden-480">Height (cm)</th>
<th class="hidden-480">BMI</th>
<th class="hidden-480">B/P</th>
</tr>
</thead>
</table>
Finally the corresponding DataTables code (which for some odd reason gives errors when placed in the partial view but not in the main view, (not my question but anyway):
<script>
$(document).ready(function ()
{
var urlRequest = $('#vitalsTable').data("request-url");
$('#vitalsTable').dataTable({
"bSort": false,
"bServerSide": true,
"sAjaxSource": urlRequest,
"sServerMethod": "POST",
"bProcessing": true,
"bFilter": false,
"aLengthMenu": [[10], [10]],
"aoColumns": [
{ "mDataProp": "VitalsDate" },
{ "mDataProp": "weight" },
{ "mDataProp": "height" },
{ "mDataProp": "bmi" },
{ "mDataProp": "bp" },
]
});
});
</script>
Action result 2 returns a chart which has the same data to another view as a Json result because that is what flot charts require. This works fine but only for the first page of data.
Here are the controller actionresults for this:
public ActionResult LoadVitalsChartData2()
{
return PartialView();
}
//[HttpPost]
[AccessRequired(AccessFeature.Vitals, AccessLevel.Read)]
public JsonResult LoadVitalsChartData()
{
int id = _accountSession.CurrentUserId;
//Bunch of code here to retrieve the data...Problem here.
//There seems to be no way to sync the Ajax call back to that it refreshes
//the data here too.
//Ideally what I want is that when the page button is pressed, it reloads this
//chart too and passes to it the relevant columns of data for plotting.
//Presently I can only get it to do the first page.
//The queries work, but how do I pass the relevant page data from the above
//action result so I am not just getting the first page of data every time.
return Json(new
{
weightData = weightResult,
xLabels = xAxisResult,
heightData = heightResult
//There is security issues around AllowGet inside a post method.
//I would like to fix this but it is also not my question.
}, JsonRequestBehavior.AllowGet);
}
Here is the corresponding partial view (This is a partial view loaded into a main view with RenderAction, nothing special):
<div id="VitalsChart" class="chart"
data-request-url="#Url.Action("LoadVitalsChartData")">
</div>
Finally the corresponding chart code this was copied and pasted from the site and only slightly modified so I put it into a separate file, if you would like to see the full code go here there is a lot of reading but I don't see anywhere to do paging:
Charts.initCharts();
Obviously I want my chart to display the data that is currently displayed in the table. i.e. if my table has 100 items paged in sets of 10, then when my table is displaying items 20 to 30, my chart should show the data for those items. It only shows the data for the first items 1 to 10. The chart itself doesn't need to handle paging, it just needs the 10 items to display and to know when the table updates. This is all available from the data sent to the table and its paging event.
So how do get this out of my table and pass it to my chart.
I have tried extracting the data to an array of some sort so it can be shared. flot charts doesn't like this. I also tried extracting the data to a common action method and passing it to another actionresult but I cant figure out how to do it.
I have tried converting all the data from anonymous types to standard class types by defining the class and casting it. But I still get errors.
This has been done before. A paged table and a chart that corresponds to the data displayed in it. Why is this so difficult to do in C# MVC4.
If there was a way I could use the above with standard data instead of Json, I would be laughing cause I know the solution. In fact, I have the solution. When querying the data, wrap it in a Paging wrapper so only the data required is returned. Then do 2 queries one in each action result for the same dataset passing only the page number to the Paging wrapper. But alas, this is for standard C# and Razor with EF and Linq. My wonderful controls require Json. This should be a lot easier but I don't know what I am missing.
It is hard to post much more code on this, I have tried so many different ways that it would make the post very long. But any one in isolation or any part of one will serve only to confuse issues.
Finally: I got some clues how to do this and started making progress but the examples I am looking for on the datatables site are not good. Here is one of my many attempts so far which is not working right (it just gives me a standard datatables error, not a JavaScript error):
$('#vitalsTable').live('page', function ()
{
var tbl = $('#vitalsTable').dataTable(
{
"aoColumnDefs": [{
"aTargets": [0],
"mData": function (source, type, val)
{
return "Hello";
}
}]
});
alert("Data ==> " + tbl);
Charts.initCharts();
});
Effectively what I am looking to do, is get a column of data when the page changes and plot this data on my chart. The page contains 10 items. So I should have a column of data with 10 items in it that can be passed to my chart for plotting.
Another snippet of code suggests that I should detect the page change event like above and before it I should do this:
var my_chart = $.plot($("#vitalsTable"), [{}]);
Then inside it I should do something like this:
my_chart.setData([new_data_set]);
my_chart.draw();
But again, I don't know how to make it work.
Thanks for any help.
This is really surprising for me. SO is a great resource, and I love it. But this is the first time I came across a problem that SO users never answered. Anyway, Finally after 8 days I worked out the answer to my question. So I am going to pop it here for reference for myself in the future cause I always come back here. S/O is like my new coding bible.
Essentially the controller was not the problem. Even the view was not the problem but instead the way I was doing the jQuery in the view.
I was advised to do something like this on other forums which essentially adds a new event handler to my data tables.
$('#vitalsTable').live('page', function ()
{
var tbl = $('#vitalsTable').dataTable(
{
"aoColumnDefs": [{
"aTargets": [0],
"mData": function (source, type, val)
{
return "Hello";
}
}]
});
alert("Data ==> " + tbl);
Charts.initCharts();
});
Above this code in my datatables code I had something like this:
<script>
$(document).ready(function ()
{
var urlRequest = $('#vitalsTable').data("request-url");
$('#vitalsTable').dataTable({
"bSort": false,
"bServerSide": true,
"sAjaxSource": urlRequest,
"sServerMethod": "POST",
"bProcessing": true,
"bFilter": false,
"aLengthMenu": [[10], [10]],
"aoColumns": [
{ "mDataProp": "VitalsDate" },
{ "mDataProp": "weight" },
{ "mDataProp": "height" },
{ "mDataProp": "bmi" },
{ "mDataProp": "bp" },
]
});
});
</script>
In actuality, all I needed to change was the code directly above, to the code below:
<script>
$(document).ready(function ()
{
var urlRequest = $('#vitalsTable').data("request-url");
$('#vitalsTable').dataTable({
"bSort": false,
"bServerSide": true,
"sAjaxSource": urlRequest,
"sServerMethod": "POST",
"bProcessing": true,
"bFilter": false,
"aLengthMenu": [[10], [10]],
"fnDrawCallback": function (oSettings)
{
Charts.initCharts(oSettings);
},
"aoColumns": [
{ "mDataProp": "VitalsDate" },
{ "mDataProp": "weight" },
{ "mDataProp": "height" },
{ "mDataProp": "bmi" },
{ "mDataProp": "bp" },
]
});
});
</script>
Once I did that, I simply needed to make minor adjustments to the client side chart.js file which takes in the data through the Charts.initCharts function and all worked well.
Later I had problems with the anonymous types, so I tried replacing them with proper classes like what C# does behind the scenes. But I found that it was even easier than this to solve. My tip, watch carefully the capitalisation of your variables on the view, controller and client side chart.js. They have to correspond exactly. Took me 2 days of messing around to find that out. It's surprising how simple changes sometimes take the longest.
I hope others looking at this find it useful. If not, post a comment and I will try to answer it.
I've used json_builder to generate the JSON file needed for the timeline from timeline.verite.co as it needs to be in a specific format. However, when I load the page, it gets stuck with a white background and a loading gif. It works if I give it a link to some sample data, but not the generated data for the user. The html page (users/1/events) works fine. Anyone have any idea why? I've run out of ideas now!!
UPDATE:
I got the JS to link to a static file with the pasted contents of the JSON from users/1/events.json, and it works fine. So I'm assuming the problem is that the page is blank when the JS tries to fetch it, and only get populated when you actually go to that URL. How do I get around this?
Generated JSON file (got by going to /users/1/events.json):
{
"timeline": {
"headline": "Emily",
"type": "default",
"text": "A Timeline",
"startDate": "1922,10,30",
"date": [
{
"startDate": "2012,11,17",
"endDate": "2012,11,17",
"headline": "My Birthday",
"text": "This is my birthday",
"asset": {
"media": "http://www.youtube.com/watch?v=dePMU8R131s",
"credit": "",
"caption": "Happy Birthday"
}
}
]
}
}
Required syntax:
{
"timeline":
{
"headline":"Stuff People Say",
"type":"default",
"text":"People say stuff",
"startDate":"2012,1,26",
"date": [
{
"startDate":"2012,1,26",
"endDate":"2012,1,27",
"headline":"Stuff Politicians Say",
"text":"<p>In true political fashion, his character rattles off common jargon heard from people running for office.</p>",
"asset":
{
"media":"http://youtu.be/u4XpeU9erbg",
"credit":"",
"caption":""
}
},
{
"startDate":"2012,1,10",
"headline":"Stuff Nobody Says",
"text":"<p>Have you ever heard someone say “can I burn a copy of your Nickelback CD?” or “my Bazooka gum still has flavor!” Nobody says that.</p>",
"asset":
{
"media":"http://youtu.be/f-x8t0JOnVw",
"credit":"",
"caption":""
}
}
]
}
}
controller (relevant bits):
class EventsController < ApplicationController
respond_to :json, :html
def myevents
#events = current_user.events
respond_with #users
end
end
routes:
resources :events do
member do
get 'myevents'
end
end
match 'users/:id/events' => 'events#myevents'
JS to call timeline:
<%= javascript_include_tag "/js/storyjs-embed.js" %>
<script>
$(document).ready(function() {
createStoryJS({
type: 'timeline',
width: '800',
height: '600',
source: '/users/<%= current_user.id %>/events.json',
embed_id: 'my-timeline'
});
});
</script>
I found the answer in the end, the js for the form wasn't reading the JSON file properly. I needed to add a callback.