show records in Angularjs - newbie - ruby-on-rails

This is a real newbie question:
I have a view for my index in Rails in erb:
<div ng-app="Donor">
<div ng-controller="DonorCtrl">
<ul>
<li ng-repeat="donor in donors">
{{donor}}
</li>
</ul>
</div>
</div>
my Donor json returned from Rails is:
class DonorSerializer < ActiveModel::Serializer
attributes :id, :tools_id, :first_name, :last_name
end
My javascript file has this;
var app;
app = angular.module("Donor", ["ngResource"]);
// separate view to Add new donors
$scope.addDonor = function() {
var donor;
donor = Entry.save($scope.newDonor);
$scope.donors.push(entry);
return $scope.newDonor = {};
};
$scope.showDonors = function() {
var Donor = $resource("/donors", {
update: {
method: "GET"
}
});
return $scope.donors = Donor;
}
this.DonorCtrl = function($scope, $resource) {
var Donor;
Donor = $resource("/donors/:id", {
id: "#id"
}, {
update: {
method: "PUT"
}
});
return $scope.donors = Donor.query();
};
How do I get a list of donors to in my index view?
I am missing something

One of your first issues was that you did not have the right code inside of the controller. I also turned your $resource's into factory's. I changed the Donors update method to 'PUT' since you have an 'addDonor' method.
Make sure you also have the proper libraries setup for angularjs. For this you will need:
angular.js
angular-resource.js
The altered Javascript:
var app;
app = angular.module("Donor", ["ngResource"]);
app.factory("Donors", [
"$resource", function($resource) {
return $resource("/donors", {}, {
update: {
method: "PUT"
}
});
}
]);
app.factory("Donor", [
"$resource", function($resource) {
return $resource("/donors/:id", {
id: "#id"
}, {
update: {
method: "GET"
}
});
}
]);
this.DonorCtrl = [
"$scope", "Donor", "Donors", function($scope, Donor, Donors) {
var donor;
$scope.donor = Donor.query();
$scope.donors = Donors.query();
$scope.addDonor = function() {};
donor = Donor.save($scope.newDonor)(function() {
return $scope.donors.push(donor);
});
return $scope.newDonor = {};
}
];
Since you are using rails, here is the coffeescript version (I find it elegant in combination with angularjs):
app = angular.module("Donor", ["ngResource"])
app.factory "Donors", ["$resource", ($resource) ->
$resource("/donors", {}, {update: {method: "PUT"}})
]
app.factory "Donor", ["$resource", ($resource) ->
$resource("/donors/:id", {id: "#id"}, {update: {method: "GET"}})
]
#DonorCtrl = ["$scope", "Donor", "Donors", ($scope, Donor, Donors) ->
$scope.donor = Donor.query()
$scope.donors = Donors.query()
$scope.addDonor = ->
donor = Donor.save($scope.newDonor) ->
$scope.donors.push donor
$scope.newDonor = {}
]
I would checkout EggHead.io for a better understanding of how to setup your angular javascript files.

Related

I have a 404 error in an Ajax call on Ruby on rails

I'm pretty new to ajax (and web development in general) and I'm trying to implement this code directly on my view:
<% content_for :after_js do %>
<script type="text/javascript">
//1st dropdown selection
const dropdownOne = document.querySelector('#order_credits_package_id');
//Listening to dropdown change
dropdownOne.addEventListener('change', (event) => {
const selectedPackage = event.target.value
console.log(selectedPackage)
// document.getElementById("order_amount_centavos").value = event.target.value
// Params for AJAX call
const url = "/dynamic_dropdown_method";
const data = {'selection': selectedPackage }
// Storage of AJAX call answer (NB: can be refactored to avoid 2 calls)
// the ['id'] must match the one defined in your controller
const level_1_selected = ajaxCall(url, data)['dropdown_1_selected'];
const level_2_array = ajaxCall(url, data)['dropdown_2_array'];
// Identification of 2nd dropdown
const dropdownTwo = document.querySelector('#order_amount_centavos');
// Delete and replace options in 2nd dropdown
removeOptions(dropdownTwo);
addOptions(level_2_array, dropdownTwo)
});
// AJAX call
function ajaxCall(url,data) {
var result = "";
console.log("call Ajax")
console.log(url)
console.log(data)
$.ajax({
url: url,
async: false,
dataType: 'json',
type: 'POST',
data: data,
success: function (response) {
console.log("ajax Call")
console.log(response)
result = response;
}
});
return result;
}
// Delete existing select options
function removeOptions(selectElement) {
console.log("fonction remove")
var i, L = selectElement.options.length - 1;
for(i = L; i >= 0; i--) {
selectElement.remove(i);
}
}
// Add select option
function addOptions(optionsArray, dropdown) {
optionsArray.forEach(function (item) {
const new_option = document.createElement('option');
new_option.value = item;
new_option.innerHTML = item;
dropdown.appendChild(new_option);
});
}
</script>
<% end %>
I then added this method to the controller related to this view:
def dynamic_dropdown_method
#selection = params[:credits_package_id]
#array_dropdown_2 = CreditsPackage.find(#selection).price_centavos
return render json: {level_1_selected: #selection, level_2_array: #array_dropdown_2}.to_json
end
And the following route:
post "/dynamic_dropdown_method", to: "orders#dynamic_dropdown_method", as: :dynamic_dropdown_method
But when I try to run my code, I get the following error message in the console:
POST http://localhost:3000/dynamic_dropdown_method 404 (Not Found)
Does anyone have any idea how to fix it?
Thank you very much!

select2 with ajax not displaying results

I'm trying to retrieve suppliers with select2 and ajax.
So this is my js code,
$(document).ready(function(){
$('.supplier_suggestion').select2({
placeholder: 'Search for supplier',
ajax: {
type: 'GET',
url: '/search_supplier',
delay: 250,
data: function(params){
var query = {
q: params.term
}
return query;
},
dataType: 'json',
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.text,
id: item.id
}
})
};
}
}
});});
I got this in my haml (which called the js file above)
%b.tosca XXX
.input-field
= f.text_field :supplier_name, class: "supplier_suggestion browser-default"
= error_for #ro_nonreg, :supplier_name
and this ini search_controller.rb
def search_supplier
search = params[:q]
search_pattern = '%' + search.downcase + '%'
result_raw = Supplier.where('lower(supplier_name) LIKE ? OR lower(shadow_id) LIKE ?', search_pattern, search_pattern)
result = []
result_raw.each do |data|
data_hash = {}
data_hash[:id] = data.shadow_id
data_hash[:text] = data.supplier_name
result << data_hash
end
render_secure_json supplier: result
end
what am i missing here?

Ruby on Rails textfield to route or specific webpage or to show action rather than list

The website i am building is in ruby on rails and it is about agriculture equipments. I have build a regular search page with input text field which when used list all items containing keyword
What i am planning to do is to have a textfield with bootstrap autocomplete feature. The text field will show options depending on input and when a single option is selected, i need it route to the particular items detail page i.e. show page rather than listing the results.
I need help with how to route directly to an items show page using the textfield value.
How can i do that?
Further to the comments, it sounds like you'll be wanting to create some sort of livesearch functionality, which basically uses ajax to send requests on keyup to your backend (PHP, Rails, etc)
We've done something like this here (search at the top):
--
The way to make this work is 3 fold:
Specific ajax route
Javascript to handle keyup
Controller action to send response
I understand this is not exactly what you want, but hopefully it will point you in the right direction
Routes
#config/routes.rb
resources :controller do
collection do
get "search(/:query)" #-> domain.com/controler/search/your_query
end
end
Controller
#app/controllers/your_controller.rb
class YourController < ApplicationController
respond_to :json, :js, :html
def search
#response = Model.where value: params[:query]
respond_with #response
end
end
JS
#app/assets/javascripts/jquery.livesearch.js
// Author: Ryan Heath
// http://rpheath.com
(function($) {
$.searchbox = {}
$.extend(true, $.searchbox, {
settings: {
url: 'search',
param: 'search',
dom_id: '#livesearch',
minChars: 2,
loading_css: '#livesearch_loading',
del_id: '#livesearch_del'
},
loading: function() {
$($.searchbox.settings.loading_css).show()
},
idle: function() {
$($.searchbox.settings.loading_css).hide()
},
start: function() {
$.searchbox.loading()
$(document).trigger('before.searchbox')
},
stop: function() {
$.searchbox.idle()
$(document).trigger('after.searchbox')
},
kill: function() {
$($.searchbox.settings.dom_id).fadeOut(50)
$($.searchbox.settings.dom_id).html('')
$($.searchbox.settings.del_id).fadeOut(100)
},
reset: function() {
$($.searchbox.settings.dom_id).html('')
$($.searchbox.settings.dom_id).fadeOut(50)
$('#SearchSearch').val('')
$($.searchbox.settings.del_id).fadeOut(100)
},
process: function(terms) {
if(/\S/.test(terms)) {
$.ajax({
type: 'GET',
url: $.searchbox.settings.url,
data: {search: terms.trim()},
complete: function(data) {
$($.searchbox.settings.del_id).fadeIn(50)
$($.searchbox.settings.dom_id).html(data.responseText)
if (!$($.searchbox.settings.dom_id).is(':empty')) {
$($.searchbox.settings.dom_id).fadeIn(100)
}
$.searchbox.stop();
}
});
return false;
}else{
$.searchbox.kill();
}
}
});
$.fn.searchbox = function(config) {
var settings = $.extend(true, $.searchbox.settings, config || {})
$(document).trigger('init.searchbox')
$.searchbox.idle()
return this.each(function() {
var $input = $(this)
$input
.keyup(function() {
if ($input.val() != this.previousValue) {
if(/\S/.test($input.val().trim()) && $input.val().trim().length > $.searchbox.settings.minChars){
$.searchbox.start()
$.searchbox.process($input.val())
}else{
$.searchbox.kill()
}
this.previousValue = $input.val()
}
})
})
}
})(jQuery);
#app/assets/javascripts/application.js
//Livesearch
$(document).ready( function() {
var base_url = window.location.protocol + "//" + window.location.host;
$('#SearchSearch').searchbox({
url: base_url + '/search/',
param: 'search',
dom_id: '#livesearch',
loading_css: '#livesearch_loading'
})
});

How to fetch index data in Angular using rails server

I am starting with Angularjs + rails backend and trying to fetch users data from the server - equivalent to to controller/index action in rails.
I have followed several tutorials and found this code as the most clear one....
questions
1. How to properly link angular module into views ?
2. How to fetch data using typeahead and sample data in this post.
here is plunker version of the code
Code is as follows:
views
<div ng-app='users'>
<div class='container-fluid' ng-controller="UsersIndexCtrl">
<pre>Model: {{result | json}}</pre>
<input type="text" ng-model="result" typeahead="suggestion for suggestion in users($viewValue)">
</div>
</div>
controller
<script>
// ['ui.bootstrap', 'ngResource'])
var app = angular.module('users', ['ui.bootstrap', 'ngResource']);
// factory - resources users
// equivalent to rails users/index
app.factory('Users', function($resource) {
return $resource('/users.json', {}, {
index: { method: 'GET', isArray: true}
});
});
// factory - user resource
// equivalent to users show, update
app.factory('User', function($resource) {
return $resource('/users/:user_id.json', {}, {
show: { method: 'GET' },
update: { method: 'PUT' }
});
});
// controller - users/ index
// equivalent to rails controller rails/index
var UsersIndexCtrl = function($scope, users) {
$scope.users = users;
};
</script>
and I am stack here, as I am getting this error:
Error: Unknown provider: usersProvider <- users
The goal of this code is to use typehead and provide data to the user.
My '/users.json' url is as follows:
[{"full_name":"Lia Cartwright","id":1,"image_url":"no-icon.jpg"},{"full_name":"Hilton Turner","id":2,"image_url":"no-icon.jpg"},{"full_name":"Aubrey Barrows","id":3,"image_url":"no-icon.jpg"},{"full_name":"Donnie Kris","id":4,"image_url":"no-icon.jpg"},{"full_name":"Eryn Rath","id":5,"image_url":"no-icon.jpg"},{"full_name":"Caden Fay","id":6,"image_url":"no-icon.jpg"},{"full_name":"Arlie Tromp","id":7,"image_url":"no-icon.jpg"},{"full_name":"Rico Klein","id":8,"image_url":"no-icon.jpg"},{"full_name":"Gudrun Dare","id":9,"image_url":"no-icon.jpg"},{"full_name":"Nathan Langworth","id":10,"image_url":"no-icon.jpg"},{"full_name":"Deanna Stroman","id":11,"image_url":"no-icon.jpg"},{"full_name":"Shania Stroman","id":12,"image_url":"no-icon.jpg"},{"full_name":"Lupe Harvey","id":13,"image_url":"no-icon.jpg"},{"full_name":"Constance Armstrong","id":14,"image_url":"no-icon.jpg"},{"full_name":"Reagan Tremblay","id":15,"image_url":"no-icon.jpg"},{"full_name":"Murray Sipes","id":16,"image_url":"no-icon.jpg"},{"full_name":"Dandre Klocko","id":17,"image_url":"no-icon.jpg"},{"full_name":"Haylee Monahan","id":18,"image_url":"no-icon.jpg"},{"full_name":"Florence Harber","id":19,"image_url":"no-icon.jpg"},{"full_name":"Norberto Hoppe","id":20,"image_url":"no-icon.jpg"}]
You must inject Users not users, it's case sensitive.
Side notes:
No need to create two models, replace:
app.factory('Users', function($resource) {
return $resource('/users.json', {}, {
index: { method: 'GET', isArray: true}
});
});
app.factory('User', function($resource) {
return $resource('/users/:user_id.json', {}, {
show: { method: 'GET' },
update: { method: 'PUT' }
});
});
with:
app.factory('User', function($resource) {
return $resource("users/:id", { id: '#id' }, {
index: { method: 'GET', isArray: true, responseType: 'json' },
show: { method: 'GET', responseType: 'json' },
update: { method: 'PUT', responseType: 'json' }
});
})
Other thing, in your controller, do:
var UsersIndexCtrl = function($scope, User) {
$scope.users = User.index();
};
Last thing, consider using: Angular Rails resource

Backbone.js router instance is somehow invalid

I have the following chunk of code. It works perfectly.
<div id="restaurant_locations"></div>
<script type="text/javascript">
$(function() {
window.router = new Lunchhub.Routers.RestaurantLocationsRouter({restaurantLocations: <%= #restaurant_locations.to_json.html_safe -%>});
var Foo = Backbone.Router.extend({routes: {"foo":"bar"}});
r = new Foo();
Backbone.history.start();
});
</script>
However, THIS does NOT work:
<div id="restaurant_locations"></div>
<script type="text/javascript">
$(function() {
window.router = new Lunchhub.Routers.RestaurantLocationsRouter({restaurantLocations: <%= #restaurant_locations.to_json.html_safe -%>});
// All I did was delete the two lines that used to be here
Backbone.history.start();
});
</script>
The latter snippet gives me this error:
Uncaught TypeError: Cannot call method 'start' of undefined
So my Foo router instance triggers a proper initialization of Backbone.history, just like you would expect a router instance to do, but my Lunchhub.Routers.RestaurantLocationsRouter instance does not.
Here's my router definition in CoffeeScript (generated automatically by the backbone-rails gem):
class Lunchhub.Routers.RestaurantLocationsRouter extends Backbone.Router
initialize: (options) ->
#restaurantLocations = new Lunchhub.Collections.RestaurantLocationsCollection()
#restaurantLocations.reset options.restaurantLocations
routes:
"new" : "newRestaurantLocation"
"index" : "index"
":id/edit" : "edit"
":id" : "show"
".*" : "index"
newRestaurantLocation: ->
#view = new Lunchhub.Views.RestaurantLocations.NewView(collection: #restaurant_locations)
$("#restaurant_locations").html(#view.render().el)
index: ->
#view = new Lunchhub.Views.RestaurantLocations.IndexView(restaurant_locations: #restaurant_locations)
$("#restaurant_locations").html(#view.render().el)
show: (id) ->
restaurant_location = #restaurant_locations.get(id)
#view = new Lunchhub.Views.RestaurantLocations.ShowView(model: restaurant_location)
$("#restaurant_locations").html(#view.render().el)
edit: (id) ->
restaurant_location = #restaurant_locations.get(id)
#view = new Lunchhub.Views.RestaurantLocations.EditView(model: restaurant_location)
$("#restaurant_locations").html(#view.render().el)
And here's the compiled JavaScript:
(function() {
var __hasProp = Object.prototype.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
Lunchhub.Routers.RestaurantLocationsRouter = (function(_super) {
__extends(RestaurantLocationsRouter, _super);
function RestaurantLocationsRouter() {
RestaurantLocationsRouter.__super__.constructor.apply(this, arguments);
}
RestaurantLocationsRouter.prototype.initialize = function(options) {
this.restaurantLocations = new Lunchhub.Collections.RestaurantLocationsCollection();
return this.restaurantLocations.reset(options.restaurantLocations);
};
RestaurantLocationsRouter.prototype.routes = {
"new": "newRestaurantLocation",
"index": "index",
":id/edit": "edit",
":id": "show",
".*": "index"
};
RestaurantLocationsRouter.prototype.newRestaurantLocation = function() {
this.view = new Lunchhub.Views.RestaurantLocations.NewView({
collection: this.restaurant_locations
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.index = function() {
this.view = new Lunchhub.Views.RestaurantLocations.IndexView({
restaurant_locations: this.restaurant_locations
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.show = function(id) {
var restaurant_location;
restaurant_location = this.restaurant_locations.get(id);
this.view = new Lunchhub.Views.RestaurantLocations.ShowView({
model: restaurant_location
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.edit = function(id) {
var restaurant_location;
restaurant_location = this.restaurant_locations.get(id);
this.view = new Lunchhub.Views.RestaurantLocations.EditView({
model: restaurant_location
});
return $("#restaurant_locations").html(this.view.render().el);
};
return RestaurantLocationsRouter;
})(Backbone.Router);
}).call(this);
What could be going wrong here?
EDIT: I've figured out part of the problem. In the CoffeeScript, it was using restaurant_locations in some places where it should have been using restaurantLocations. I'm having a strange problem now, but potentially an easier one: when I copy and paste the compiled JavaScript directly into <script> area, right before the window.router = assignment, everything works perfectly. However, when I try to use the compiled JS as an external file (and I know it's being included - I checked), I get that same Cannot call method 'start' of undefined error.
Here's my updated CoffeeScript:
class Lunchhub.Routers.RestaurantLocationsRouter extends Backbone.Router
initialize: (options) ->
#restaurantLocations = new Lunchhub.Collections.RestaurantLocationsCollection()
#restaurantLocations.reset options.restaurantLocations
routes:
"new" : "newRestaurantLocation"
"index" : "index"
":id/edit" : "edit"
":id" : "show"
".*" : "index"
newRestaurantLocation: ->
#view = new Lunchhub.Views.RestaurantLocations.NewView(collection: #restaurantLocations)
$("#restaurant_locations").html(#view.render().el)
index: ->
#view = new Lunchhub.Views.RestaurantLocations.IndexView(restaurantLocations: #restaurantLocations)
$("#restaurant_locations").html(#view.render().el)
show: (id) ->
restaurant_location = #restaurantLocations.get(id)
#view = new Lunchhub.Views.RestaurantLocations.ShowView(model: restaurant_location)
$("#restaurant_locations").html(#view.render().el)
edit: (id) ->
restaurant_location = #restaurantLocations.get(id)
#view = new Lunchhub.Views.RestaurantLocations.EditView(model: restaurant_location)
$("#restaurant_locations").html(#view.render().el)
And here's my updated compiled JavaScript:
(function() {
var __hasProp = Object.prototype.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
Lunchhub.Routers.RestaurantLocationsRouter = (function(_super) {
__extends(RestaurantLocationsRouter, _super);
function RestaurantLocationsRouter() {
RestaurantLocationsRouter.__super__.constructor.apply(this, arguments);
}
RestaurantLocationsRouter.prototype.initialize = function(options) {
this.restaurantLocations = new Lunchhub.Collections.RestaurantLocationsCollection();
return this.restaurantLocations.reset(options.restaurantLocations);
};
RestaurantLocationsRouter.prototype.routes = {
"new": "newRestaurantLocation",
"index": "index",
":id/edit": "edit",
":id": "show",
".*": "index"
};
RestaurantLocationsRouter.prototype.newRestaurantLocation = function() {
this.view = new Lunchhub.Views.RestaurantLocations.NewView({
collection: this.restaurantLocations
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.index = function() {
this.view = new Lunchhub.Views.RestaurantLocations.IndexView({
restaurantLocations: this.restaurantLocations
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.show = function(id) {
var restaurant_location;
restaurant_location = this.restaurantLocations.get(id);
this.view = new Lunchhub.Views.RestaurantLocations.ShowView({
model: restaurant_location
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.edit = function(id) {
var restaurant_location;
restaurant_location = this.restaurantLocations.get(id);
this.view = new Lunchhub.Views.RestaurantLocations.EditView({
model: restaurant_location
});
return $("#restaurant_locations").html(this.view.render().el);
};
return RestaurantLocationsRouter;
})(Backbone.Router);
}).call(this);
Okay, this turned out to be a pretty esoteric problem. I had had a leftover backbone-min.js sitting in my app/assets/javascripts directory, even though I had switched to using a different Backbone file. This "old" backbone-min.js was getting loaded after my route definition and that's what was messing things up. After I deleted backbone-min.js, things started working.

Resources