Getting has_many association from ngResource in rails - ruby-on-rails

I'm trying to recreate the following erb template in angularjs using ngResource, but can't seem to figure out how to access the event.spikes (it's a has_many relationship).
The erb file I want to change:
<div class='event-list'>
<ul>
<% #events.each do |event| %>
<li><%= event.name %> || <small><%= event.date %></small>
<ul>
<% event.spikes.each do |spike| %>
<li>Time of Spike: <%= spike.date_time %> || Spike Velocity: <%= spike.peak_velocity %></li>
<% end %>
</ul>
</li>
<% end %>
</ul>
</div>
The half finished .html without erb:
<div class='event-list' ng-controller='EventsCtrl'>
<ul>
<li ng-repeat='event in events'>
{{ event.name }} || <small>{{ event.date }}</small>
<ul>
<<<<<SOMETHING GOES HERE???>>>>>>>>
</ul>
</li>
</ul>
</div>
Here's my service, app/assets/javascripts/angular/controllers/event.js:
App.factory('Event', ['$resource', function($resource) {
return $resource('/events/:id', { id: '#id' });
}]);
My angular controller, app/assets/javascripts/angular/controllers/events.ctrl.js:
App.controller('EventsCtrl', ['$scope', 'Event', function($scope, Event) {
$scope.events = Event.query();
}]);
And where my angular app is defined, app/assets/javascripts/app.js:
window.App = angular.module('sportsSpike', ['ngResource']);

You can nest in Angular like this
<li ng-repeat='event in events'>
{{ event.name }} || <small>{{ event.date }}</small>
<ul>
<li ng-repeat='spike in event.spikes'>
{{ spike.some_output_value }}
</li>
</ul>
</li>
You will, however need to ensure that the way you are passing the data to angular has already resolved the spike property of events.
Hope this helps

Following the answer from muttonlamb here it is a complete HTML file. As explained before you can easily nest ng-repeat with AngularJS and new child isolated scopes will be created.
You can see full code below or plunker here (http://plnkr.co/edit/jRG4xcRIab8sgHJFffWV)
P.S.: I am not using any ngResource just for simplicity as I am fetching the data via an array, but the ng-repeat code will work either way.
<!doctype html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>Events</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script>
'use strict';
var myApp = angular.module('myApp',[]);
myApp.events = [
{
name: 'Event 1',
date: '01/02/2013',
spikes: [
{
date_time : '1288323623006',
peak_velocity: '10m/s'
},
{
date_time : '1288323623004',
peak_velocity: '20m/s'
},
{
date_time : '1288323623003',
peak_velocity: '10m/s'
},
{
date_time : '1288323623001',
peak_velocity: '20m/s'
}
]
},
{
name: 'Event 2',
date: '05/03/2013',
spikes: [
{
date_time : '1288323623003',
peak_velocity: '40m/s'
},
{
date_time : '1288323623002',
peak_velocity: '50m/s'
},
{
date_time : '1288323623007',
peak_velocity: '80m/s'
},
{
date_time : '1288323623001',
peak_velocity: '60m/s'
}
]
},
{
name: 'Event 2',
date: '05/03/2013',
spikes: [
{
date_time : '1288323623005',
peak_velocity: '40m/s'
},
{
date_time : '1288323623009',
peak_velocity: '50m/s'
},
{
date_time : '1288323623003',
peak_velocity: '80m/s'
},
{
date_time : '1288323623002',
peak_velocity: '60m/s'
}
]
}
];
myApp.controller('EventsCtrl', ['$scope', 'Event', function($scope, Event) {
$scope.events = Event.query();
}]);
myApp.factory('Event', function() {
return {
query: function() {
return myApp.events;
}
}
});
</script>
</head>
<body>
<div class='event-list' ng-controller='EventsCtrl'>
<ul>
<li ng-repeat='event in events'>
<h3>{{ event.name }} || {{ event.date }}</h3>
<ul>
<li ng-repeat='spike in event.spikes'>
Time of Spike: {{ spike.date_time | date : 'short' }} || Spike Velocity: {{ spike.peak_velocity }}
</li>
</ul>
</li>
</ul>
</div>
</body>
</html>

Related

Starting owlCarousel in rails

I am new to rails and this is the first time I want to use a carousel in a web application. My carousel appears, but it does not auto-play.
This is what I have in my application.js :
//= require owl.carousel
$(function(){ $(document).foundation(); });
var owl = $('.owl-carousel');
owl.owlCarousel({
items:5,
loop:true,
margin:10,
autoplay:true,
autoplayTimeout:1000,
autoplayHoverPause:true
});
And this is from my view:
<div id="owl" class="owl-carousel">
<% #artists.each do |artist| %>
<div class="artist-card ">
<%= link_to artist, class: "poster" do %>
<%= image_tag artist.image.url(:thumb) %>
<% end %>
<div class="artist-info ell glassy-bg padmy padlx">
<div class="artist-card ">
<h6><%= artist.name %> <span>(<%= artist.instrument %>)</span></h6>
</div>
</div>
</div>
<% end %>
</div>
Is there also a way to display every artist from my database in the carousel? I've seen that the default number of items for the carousel is 5. Can I make it dynamic ?
I managed to solve the issue. Here is what I've done:
(function ($) {
$(document).ready(function() {
if ($('.carousel .owl-wrapper-outer').length === 0) {
var owl = $('.carousel').owlCarousel({
items:5,
loop:true,
margin:10,
autoPlay:1000,
autoplayHoverPause:true,
responsive: true,
responsiveRefreshRate : 200,
responsiveBaseWidth: window,
});
$('.carousel').hover(function() {
owl.trigger('owl.stop');
}, function(){
owl.trigger('owl.play', 1000);
});
}

Algolia Typeahead retrieve results

I am trying to create a discussion tool in my Rails app. I'd like to add users to a discussion like in Facebook messenger.
To do so, I implemented Algolia instant search sith Typeahead. It works fine to show th results but when I click on a result it does nothing at all. It looks like if the event I am using was not working.
I cannot use my keyboard to go up or down the results, it's very strange. Could you help me? I tried all the events on the Typeahead documentation but no one is working.
Thank you so much.
<div class="uk-grid message">
<div class="uk-width-medium-2-6"></div>
<div class="uk-width-medium-3-6 bubble">
<%= form_tag create_discussion_path, method: :post, remote: true, class: 'uk-form', id: 'createDiscussionForm' do %>
<div class="form-group">
<div class="uk-grid">
<div class="uk-width-1-6">
<span><%= t('to') %></span>
</div>
<div class="uk-width-5-6">
<%= text_field_tag 'recipients', '', class: 'recipients typeahead', id: 'typeahead-algolia-template', spellcheck: false %>
</div>
</div>
<%= text_area_tag 'body', nil, cols: 3, class: 'form-control uk-width-1-1 body', placeholder: 'Ask something or just say hi!', required: true %>
</div>
<%= submit_tag t('dashboard.discussions.send_message'), class: 'uk-button uk-width-1-1' %>
<% end %>
<div class="arrow-right"></div>
</div>
<div class="uk-width-medium-1-6 text-center">
<%= link_to user_path(current_user) do %>
<%= image_tag(current_user.pictures.first.image(:square_thumb)) %>
<% end %>
<p><%= current_user.first_name %></p>
</div>
</div>
<!-- Algolia search callback -->
<script type="text/javascript">
function searchCallback(success, content) {
if (content.query != $("#typeahead-algolia-template").val()) {
// do not take out-dated answers into account
return;
}
if (content.hits.length == 0) {
// no results
$('#hits').empty();
return;
}
} // end search callback
</script>
<!-- end Algolia search callback -->
<!-- Algolia with typehead and hogan -->
<script type="text/javascript">
$(document).ready(function() {
// Algolia initialization
var $inputfield = $("#typeahead-algolia-template");
var algolia = algoliasearch('<%= ENV['ALGOLIA_ID'] %>', '<%= ENV['ALGOLIA_PUBLIC_KEY'] %>');
var index = algolia.initIndex('<%= 'User_' + Rails.env %>');
var ttAdapterParams = {
hitsPerPage: 5,
facets: '*',
tagFilters: ''
};
// Templating
var templates = {
algolia: {
hit: Hogan.compile(
'<div class="uk-grid">' +
'<div class="uk-width-1-4">' +
'<img src="{{{_highlightResult.picture.value}}}">' +
'</div>' +
'<div class="uk-width-3-4">' +
'<span class="name">' +
'{{{_highlightResult.first_name.value}}}, ' +
'</span>' +
'<span class="occupation">' +
'{{{_highlightResult.occupation.value}}}' +
'</span>' +
'</div>' +
'</div>'
)
}
};
// Search?
$inputfield.typeahead({
highlight: true,
hint: true,
minLength: 1
},
{
source: index.ttAdapter(ttAdapterParams),
displayKey: 'name',
templates: {
suggestion: function(hit) {
var tpl = templates.algolia.hit.render(hit);
//console.log(tpl, 'hit');
return tpl;
}
}
}).on('typeahead:open', function(event, data) {
// var $form = $(this).closest('form');
// $form.data('sendToServer', true);
// $form.submit();
});
var val = $inputfield.typeahead('val');
console.log(val);
$("#typeahead-algolia-template").bind('typeahead:open', function(ev, suggestion) {
console.log('Selection: ' + suggestion);
});
});
</script>
Thanks to the great Algolia support team I managed to make it work!
As suggested, I switched to https://github.com/algolia/autocomplete.js and it's just perfect. I changed a few things, basically replacing .typeahead by .autocomplete and the event listener name.
Here is the snippet:
$inputfield.autocomplete({
highlight: true,
autoselect: true,
openOnFocus: true
}, [
{
source: $.fn.autocomplete.sources.hits(index, ttAdapterParams),
displayKey: 'first_name',
templates: {
suggestion: function(hit) {
var tpl = templates.algolia.hit.render(hit);
//console.log(tpl, 'hit');
return tpl;
}
}
}]).on('autocomplete:selected', function(event, suggestion, dataset) {
console.log(suggestion);
});

Create toggle-able Bootstrap tabs from Ruby hash

So I'm trying to create toggle-able tabs from a Ruby hash. For example, let's say that I have the following hash:
tabs = {
:Friends =>
[
[name: 'john', age: 20, sex: 'M'],
[name: 'elma', age: 21, sex: 'F']
],
:Family =>
[
[name: 'father', age: 50, sex: 'M'],
[name: 'mother', age: 48, sex: 'F'],
[name: 'sister', age: 17, sex: 'F']
]
}
This would result in the two tabs 'Friends' and 'Family' respectively which would list either friends or family members as an unordered list.
I would like to make this tabs toggle-able without Ajax if possible, so basically if I click the Friends tab it would access the appropriate value from the tabs[:Friends] hash.
Thanks!
Try this if it help you
Link to ur partial
<div id="toggle_div" style="display:none">
<%= render partial => "ur_partial" %>
</div>
By using JQuery
<script type="text/javascript">
$(function(){
$('.toggleLink').click(function(){
$('#toggle_div').toggle();
});
});
</script>
add different IDs to both tabs and toggle them...
Found the solution yesterday:
<div class="tabbable tabs-left">
<ul class="nav nav-tabs">
<li>
All
</li>
<% tabs.each do |k,v| %>
<li>
<a href="#<%= k.to_s %>" data-toggle="tab">
<%= k.to_s %>
</a>
</li>
<% end %>
</ul>
<div class="tab-content">
<div class = "tab-pane active" id = "all_tabs">
<ul>
<% tabs.each do |k,v| %>
<li>
<%=k%>
</li>
<% end %>
</ul>
</div>
<% tabs.each do |k,v| %>
<div class = "tab-pane" id = "<%= k.to_s %>">
<strong><%= k.to_s %></strong>
<ul>
<% v.each do |key,val| %>
<li>
<%=val.name%>
</li>
<% end %>
</ul>
</div>
<% end %>
</div>
</div>
Here is the generated html output:
http://www.bootply.com/0sWdURMEPY

save position of draggable li jQuery Rails 3

I have page with a map on my web-site where administrator can drag and drop icons to the specific position. After reading some examples, icons can be draggable, but when i try to refresh the page all icons revert to their default positions. I can't figure out how to save the position of elements to the database. I'm using jQuery and Rails 3. Help me please!
Thank you!
Here's the code of my page:
<div class="map">
<ul class="departments-map" id="departments-map">
<%= render :partial => 'departments/departments_short_map', :collection => #departments %>
</ul>
</div>
Departments_short_map:
<% department ||= departments_short_map %>
<% if department.map_x.nil? or department.map_y.nil? %>
<li id="<%= department.id %>" class="department-short-map">
<%= department_for_collage(department) %>
</li>
<% else %>
<li id="<%= department.id %>" class="department-short-map" style="position:absolute; top:#{ department.map_y}px; left:#{ department.map_x}px;">
<%= department_for_collage(department) %>
</li>
<% end %>
And here is my jQuery code:
var Collage = {
init: function() {
$("#departments-map li").draggable({
scroll: false,
stop: function(event, ui) {
var img = {
"id": $(this).attr('id'),
"map_y": $(this).position().top.toString(),
"map_x": $(this).position().left.toString()
};
$.ajax({
type: "put",
url: "/departments/" + $(this).attr('id') + ".json",
data: JSON.stringify(img),
contentType: 'application/json',
dataType: 'json',
})
}
});
}
}
What am i doing wrong?

Binding backbone collection to view and underscore template on front end

I am using backbone + jquery mobile and couldn't get my array of models (collections) to output to the UI via underscore template.
My model is as follows:
var shortcake = Backbone.Model.extend({
defaults: function() {
return {
name: "No Slot",
butter: false,
time: "3pm",
icon: "plus",
deladd: "ADD"
};
},
initialize: function() {
this.bind("change:butter", function(){
if (this.model.butter == false) {
this.set({name: this.defaults.name});
};
}),
}
});
My collection is as follows:
var shortcakes = Backbone.Collection.extend ({
model: shortcake
});
var shortcake1 = new shortcake({ name: "How Bizarre", butter: "true", time: "1", icon:"plus", deladd:"ADD" });
var shortcake2 = new shortcake({ name: "Sexual Healing", butter: "true", time: "1", icon:"plus", deladd:"ADD" });
var shortcakeAlbum = new shortcakes([ shortcake1, shortcake2]);
And my view:
var shortcakeUI = Backbone.View.extend ({
tagName: "li",
template: _.template($('#shortcakeTemplate').html()),
initialize: function(){
this.render();
},
render: function() {
var variables = { namee: name };
if (this.model.butter == false) {
this.model.deladd = "ADD";
this.model.icon= "plus";
this.el.html( template );
}
else {
this.model.deladd = "DELETE";
this.model.icon= "minus";
this.el.html( template );
}
},
)};
var ShortcakeUI = new shortcakeUI({
collection : shortcakeAlbum,
el: $("#shortcakeinterface")[0]
});
ShortcakeUI.render();
And my html is:
<ul data-role="listview" data-split-icon="gear" data-split-theme="d">
<div id="shortcakeinterface"></div>
</ul>
<!---Templates--->
<script id="shortcakeTemplate" type="text/template">
<% for(var i = 0; i < shortcakeAlbum.length; i++){ %>
<% var shortcakez = shortcakeAlbum[i]; %>
<fieldset class="ui-grid-a">
<div class="ui-block-a">
<h3><%= shortcakez.time %></h3>
<p><%= shortcakez.name %></p>
</div>
<div class="ui-block-b">
<div id="8" data-role="controlgroup" data-type="horizontal" >
<%= shortcakez.deladd %>
Test
</div>
</div>
</fieldset>
<% } %>
</script>
So with these, my UI does not show the list of models on load.
Just starting out on backbone and js, am I doing things right here?
You need to pass the model to your template in render().
Instead of
this.el.html( template );
do this
$(this.el).html( this.template(this.model.toJSON()) );

Resources