Check if subject exist and append next to text box - ruby-on-rails

I have a rails app that has a subject text field where the user input subject code id then beside the text field will the result of other details of the subjects when I blur the text field.
form:
SC_ID: <%= f.text_field "subject1", :id => "subject1"%>
jquery:
$('#subject1').blur(function() {
var field_value = $(this).val();
$.post("<%= validate_subject_path %>",{subject : field_value}, function(data) {
success: function() {
alert("Hahaha!");
},
error: function() {
alert("Subject not found!");
}
});
});
controller:
def validate_subject
sc_id = params[:subject].to_i
#subject = Subject.find_by_sc_id(sc_id)
string = "#{#subject.id}"
return string
render :layout => false
end
routes:
map.validate_subject '/subjects/validate_subject', :controller => "subjects", :action => 'validate_subject'
But when I try to blur no alert box is coming out.

Your $.post call is wrong, it should be something like this:
$.post("<%= validate_subject_path %>",{subject : field_value}, function(data) {
// not returning a hash
alert("Hahaha!");
});
If you really when to react on failures than you need to use $.ajax instead of $.post http://api.jquery.com/jQuery.ajax/

Related

Rails, Select2 and Ransack return emprty array

I have a City Model:
class Geo::City < Smth
self.table_name = 'cities_table'
has_many :streets, class_name: "Geo::Street", primary_key: :geo_code, foreign_key: :geo_code
The aim is, to search all streets in the city and print them as a search result. In my controller I have a filter method as follows:
def filter
#city_list = city_list
params[:q] ||= {}
params[:q][:ags8_id_eq] = #city_list[0][1]
if params[:q].present? && params[:q][:geo_code_eq].present?
#city = Geo::City.find_by(geo_code: params[:q][:geo_code_eq])
#collection = [["#{#city}", "#{params[:q][:geo_code_eq]}"]]
end
#streets = #city.streets.limit(15)
#q = #streets.ransack(params[:q])
end
I also have a search_city method as follows:
def search_city
render json: city_list.select {|city| city.first.include?(params[:q][:geo_code_eq])}
end
And a private method city_list which I am calling in methods above:
def city_list
all_cities = Geo::City.order('city_name').reduce([]) {|cities, c| cities << [c.name, c.geo_code]}
I had to change all the method names,cause it's for work, so the_city list is kind of an example and it also works fine, I assume, this is not the problem. I also have a js-file for select 2.
(function() {
$(function() {
return $('.city-select2').select2({
ajax: {
url: "/filter/search_city",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: {
geo_code_eq: params.term
}
};
},
processResults: function(data) {
return {
results: $.map(data, function(obj) {
return {
id: obj[1],
text: obj[0]
};
})
};
},
cache: true
},
minimumInputLength: 2,
placeholder: "City",
tags: false,
tokenSeparators: [","],
selectOnClose: true,
allowClear: true
});
});
}).call(this);
It seems to be working, cause when I type city name it finds the city with the letters I typed. What happens after I submit select form is that I just get an empty array, so basically like this:
The url looks the following:
http://localhost:3000/filter/search_city?q%5Bgeo_code_eq%5D=16071003&commit=Search
My view does this:
= search_form_for #q, url: search_city_path do |f|
.columns.is-centered{style: 'padding-top: 100px;'}
.column.is-half
= f.select(:geo_code_eq, options_for_select(collection: #collection.present? ? #collection : [], input_html: { class: "city-select2 select-input" })
= f.submit "Search"
What is wrong? How do I get streets in the cities printed? There might be some spelling mistakes in the code, as I had to replace names, this won't be the reason for my empty array. Also, in the url there is only B selected, maybe that the reason? But it also finds the geo_code, so it should be capable of giving the streets back linked to geo_code, as geo_code is also the part of streets_table..
Main reason for the array was the path in the view. Should have been filter_path ans not the search_city_path, as it was the same path my select2 was getting data from, redirection there on submit made no sence.

How can I check if a username is taken, while typing?

Many popular websites have a username field that, usually, turns red or blue as a user types in a new character, based on whether or not the characters entered correspond to an already-existing user.
Say I have the following username field:
<%= f.text_field :username, id:"username" %>
How could that functionality be added to this field?
Instead of checking the username and making request on every key, you can use the blur method to check the user name once the user leaves the username field, or else you need it on every key you can use keyup itself,
Your Javascript,
$( "#username" ).keyup(function() { # you can also try, $( "#username" ).blur(function() {
$.ajax({
url: '<%= check_duplicate_username_path %>', # your own route
type: "GET",
data: { username: $('#username').val() }, // This goes to Controller in params hash, i.e. params[:username]
complete: function() {},
success: function(data, textStatus, xhr) {
// do something with your returned data //
if (data.available == false)
{
$('#username').addClass("error"); // style the class with your required css
}
},
error: function() {
alert("Your Ajax error! message")
}
});
});
The route can be taken as,
get '/check_duplicate_username' => 'users#check_duplicate_username', as: :check_duplicate_username
The controller action can be something like,
def check_duplicate_username
#user = User.where('username = ?',params[:username]).first
if #user.present?
render json: {:success => 0, :message => 'User exists', :user_available => true}
else
render json: {:success => 1, :message => 'User Does not exist', :user_available => false}
end
end
You have to fire ajax request on textbox event.
write ajax function and add new function to you user_controller with GET http method and return suitable response for check availabilty of your username.
Trigger an ajax request while writing on the text box. Like:
$( "#username" ).keyup(function() {
$.ajax({
type: "GET",
url: '<%= username_availability_path %>', # replace by your route
data: {name: $('#username').prop('value')}
});
});
Create a new route on your routes.rb file with type GET. In the method access the typed name using params[:name] and then check if exists or not. Then do whatever you want.

How to Use Ajax in ruby on rails

I want send selected drop down menu value to controller by ajax
panel_controller.rb
class PanelController < ApplicationController
def insert
#city_ids = params[:city]
end
end
panel.js.erb
$(document).ready(function() {
$('#f_city_id').change(function() {
var city_js_id = this.value
$.ajax({
url: '/panel/insert',
type: 'GET',
data: {"city": city_js_id},
success: function (data,status)
{
alert(this.url);
}
});
return false;
});
});
routes.rb
get '/panel/insert' => 'panel#insert'
views/panel/insert.html.erb
<%= #city_ids %>
but #city_ids dont respond value after chenge drop down menu
You need to respond back from your insert method.
Try doing this
class PanelController < ApplicationController
def insert
#city_ids = params[:city]
respond_to do |format|
format.html { render partial: 'insert.html.erb' }
end
end
end
Create a partial file with the new content _insert.html.erb
<%= #city_ids %>
In you panel.js.erb try catching the response and append it in your DOM wherever necessary. Your updated value will be on the page.
$(document).ready(function() {
$('#f_city_id').change(function() {
var city_js_id = this.value
$.ajax({
url: '/panel/insert',
type: 'GET',
data: {"city": city_js_id},
success: function (res){
$("#somediv").html(res);
//You will get the partial's content with the new data and you'll only need to append it to your page.
}
});
return false;
});
});

Rendering JSON from AJAX call in Rails

I have an ajax call to fetch information from Flickr API which returns JSON data. I want to display values from JSON data in my view. I do this by editing some innerHTML with jQuery. The problem I am having is that the data is undefined, so it looks like a scoping problem.
photo.js
jQuery(function() {
$('#<%=p[:id]%>').click(function (e) {
//ajax call to fetch photo info
var fetch_id = '<%=p[:id]%>';
var fetch_secret = '<%=p[:secret]%>';
$.ajax({
type: 'GET',
url: '/photos/fetch_info',
dataType: 'json',
data: { 'id' : fetch_id, 'secret' : fetch_secret },
success: function(data){
console.log(data) //returns Object
console.log(data.title) //returns appropriate title
//edit innerHTML of basic_modal
$('.basic_modal').html(
"<div id='modal_image'><%= escape_javascript(image_tag p[:url]) %></div><div id='photo_title'><%=data.title %></div>"
);
//load modal
$('.basic_modal').modal({
overlayClose:true
});
} //end success: function(result)
});
When I print data.title to console, I get the appropriate title. However, when I try to edit HTML and render <%=data.title %>, I get an undefined variable/method error.
Any tip on how I can display the data in my modal in the view?
Here is my controller:
def fetch_info
#info = flickr.photos.getInfo(:photo_id => params[:id], :secret=> params[:secret])
respond_to do |format|
format.json { render :json => #info }
end
end
var result = jQuery.parseJSON(data);
You donot need to do this, Because datatype:JSON already parse the data
$('.basic_modal').html(
"<div id='modal_image'><%= escape_javascript(image_tag p[:url]) %>
</div><div id='photo_title'><%="+data.title+" %></div>"
);
this might help you

Check username availability

I have a form to user login:
<%= form_tag(#action, :method => "post", :name => 'signup' ,:onSubmit => 'return validate();') do %>
<%= label_tag(:user, "Username:") %>
<%= text_field_tag(:user) %>
I want to check if there is the username in the database immediately after :user-field lost focus. I can override this event on the form with javascript, but I can not send Ruby-AJAX request from javascipt code.
Is there any way to check username without adding additional controls (buttons, links) on the form?
You can use some JavaScript (this one written with jQuery) for AJAX cheking:
$(function() {
$('[data-validate]').blur(function() {
$this = $(this);
$.get($this.data('validate'), {
user: $this.val()
}).success(function() {
$this.removeClass('field_with_errors');
}).error(function() {
$this.addClass('field_with_errors');
});
});
});
This JavaScript will look for any fields with attribute data-validate. Then it assings onBlur event handler (focus lost in JavaScript world). On blur handler will send AJAX request to the URL specified in data-validate attribute and pass parameter user with input value.
Next modify your view to add attribute data-validate with validation URL:
<%= text_field_tag(:user, :'data-validate' => '/users/checkname') %>
Next add route:
resources :users do
collection do
get 'checkname'
end
end
And last step create your validation:
class UsersController < ApplicationController
def checkname
if User.where('user = ?', params[:user]).count == 0
render :nothing => true, :status => 200
else
render :nothing => true, :status => 409
end
return
end
#... other controller stuff
end
For what reason can you not send an ajax request from javascript code?
The best way would be to send a GET ajax request when the focus is lost. The get request could then return true or false and your javascript could then reflect this on the page.
I answered this in another post.
It is a friendly way for validating forms if you do not want to write it all from scratch using an existing jquery plugin. Check it out and if you like it let me know!
Check username availability using jquery and Ajax in rails
The solution that #Viacheslav has, works fine and my answer is a combination of his and my own changes (especially JS) part.
We will be using Ajax in order to achieve this.
Lets first create our function in the controller
def checkname
if !User.find_by_display_name(params[:dn])
render json: {status: 200}
else
render json: {status: 409}
end
return
end
and then adding our routes in routes.rb
resources :yourcontroller do
collection do
get 'checkname'
end
end
Now lets gets our hand on the view. Below you'll see the input:
.field
= f.text_field :display_name, onblur: "checkDisplayName.validate(this.value)"
%p.error-name.disp-none username exists
And now by help of JSwe get the magic rolling. Blow JS has few functions. validate does the actually validation. getStatus is our Ajax call to get the status and we use showError & disableSubmitButton to our form a bit more production ready to show errors and disabling the submit button.
var checkDisplayName = {
validate: function(dn){
checkDisplayName.getStatus(dn).then(function(result) {
if (!!result){
if (result.status != 200){
checkDisplayName.disableSubmitButton(true);
checkDisplayName.showError();
} else{
checkDisplayName.disableSubmitButton(false);
}
}
});
return false;
},
getStatus: async (dn) => {
const data = await fetch("/pages/checkname?dn=" + dn)
.then(response => response.json())
.then(json => {
return json;
})
.catch(e => {
return false
});
return data;
},
showError: function() {
let errEl = document.getElementsByClassName('error-name')[0];
if (!!errEl) {
errEl.classList.remove("disp-none");
window.setTimeout(function() { errEl.classList.add("disp-none"); },3500);
}
},
disableSubmitButton: function(status){
let button = document.querySelector('[type="submit"]');
button.disabled = status;
}
};

Resources