Value not bind to the view from controller - ruby-on-rails

I have two select tags as follow
<%= f.select(:floor_id, ProjectFloor.find(:all,:order => "name ASC",:conditions => ["project_id = ?", #project.id]).collect{|b|[b.name, b.id]}, {:include_blank => 'Select'}) %>
<%= f.select(:unit_id, #floor.collect{|b|[b.name, b.id]}, {:include_blank => 'Select'}) %>
When the user select the value on the first select tag called :floor_id then the value of the select tag data should be load to :unit_id select tag
I have try the following to read and fetch the data but. the floor_id always receiving null
My controller method is as follow :
#floor_id = params[:floor_id]
#project = Project.find(params[:project_id])
#proposed_customer = ProposedCustomer.new
#floor = ProjectFloorUnit.select_units(#project.id, #floor_id)
The select unit method is work fine for static values so it must work if we pass the proper param.

When a page is completely loaded, it disconnects from the server. So, you need to initiate a separate request, and the response of the request will change the values or whatever you want in the second dropdown.
You can use jQuery to send a new request:
$("#floorIDSelectTag").change(function() {
var floorID = $(this).val();
$.ajax({
type: '',
url: '',
// other things
success: function(data) {
// Here, you need to use the data from the request's response,
// and update the things in 2nd dropdown
}
});
});
What will be the URL that you will use in AJAX call? For it, you need to build a new route in config/routes.rb file, a new action in your controller, and send back the data in JSON format. Something like following:
def get_data_for_floor_id
#floor_id = params[:floor_id]
# Do the other stuff, and prepare the response you need to send.
respond_to do |format|
format.json { }
end
end

Related

View rails record details in bootstrap modal on row click

I have been stuck on this problem for quite some time now and looked through several posts as well, however I cannot achieve exactly what I want for my Rails application. Essentially, I want to be able to click on a table row on my page and have a modal pop up which displays all the information for that specific record. Here are the scenarios which I have thought of/attempted partially:
Set the data-link attribute in table row with some JS as follows
HTML:
<tr data-link="<%= kid_path %>">
...
</tr>
JS:
$("tr[data-link]").dblclick(function() {
window.location = $(this).data("link")
})
This worked fine to open the show path page generated by the scaffold, but I was not able to modify it to work with a modal and have the same data for the kid in the modal.
Use data-id and JavaScript to load onto the modal
HTML:
<tr data-id="<%= kid.id %>">
...
</tr>
JS:
$(function () {
$('#showModal').modal({
keyboard: true,
backdrop: "static",
show: false,
}).on('show', function () {
});
$(".table-striped").find('tr[data-id]').on('click', function () {
debugger;
$('#showDetails').html($('<p>' + 'Kid ID: ' + $(this).data('id') + '<%= Kid.find(30).first_name %>' + '</p>'));
$('#showModal').modal('show');
});
});
In this approach I am able to load the modal on row click and am able to access the Kid ID, however I cannot move further to access other attributes of the record. For example, I want to set #Kid = kid.find(id) using JS where id would be the extracted ID from the row. And then, I want to be able to write the generic modal template which displays other elements (ex. kid.first_name, kid.last_name, etc).
I am totally stuck and cannot find any approach that helps to accomplish my goal. Any help is appreciated, thank you.
You need to ajax call record attributes because the line Kid.find(30).first_name doesn't exist at the time page loaded.
Try this:
KidsController
def show
kid = Kid.find(params[:id])
respond_to do |format|
format.html { // Usually show.html.erb }
format.json do
# Return kid as json object
result = {
first_name: kid.first_name,
last_name: kid.last_name
}
# If you want to return the whole kid record attributes in json: result = kid.attributes.to_json
render json: result
end
end
end
Try /kid/[:id].json to verify that you are not getting UnknownFormat error.
JS
$(".table-striped").find('tr[data-id]').on('click', function () {
var kid_id = $(this).data('id');
$.getJSON("/kid/" + kid_id, function(data) {
// Render the modal body here
// first_name = data.first_name, last_name = data.last_name etc
$('#showDetails').html($('<p>'+ data.first_name + '</p>'));
$('#showModal').modal('show');
});
})
If you have setup correct route for Kid model then these are what you needed.
UPDATED: I made a typo in the result hash. FIXED

Should Backbone collection 'create' add new model to collection with id from server included?

In my Backbone view here, I want to be able to immediately add my model to my collection with an 'id' attribute included in the newly created model. In other words, I need to have access to this 'id' right away. With the id available, my removeCategory method can work. To "solve" that problem, I tried to add the line this.collection.fetch() directly below this.collection.add(model);, but it gave me very bad UI (the new <li> wouldn't even render, etc), plus it seems like very bad coding practice anyway.
I'm relatively new with Backbone, so I'm not sure if create (save/add) should automatically add the model to the collection with an id or not. If it should, then there must be something wrong with the JSON data I'm receiving from my Rails RESTful API. If create does NOT do that, then how can I instantly get access to this specific newly created model, with an id (other than by refreshing the browser -- ugh!)? I need the id for <li data-id={{id}}></li> in my Handlebars template as soon as I invoke the "addCategory" method.
Also (& this might be a related problem), when I do model.fetch();, I get back the model's entire collection, plus that newly-created server-side model without an id. Any help on this would be much appreciated.
window.CategoriesView = Backbone.View.extend({
index_template: HandlebarsTemplates['categories/index'],
events: {
'click .delete': 'removeCategory',
'click .category_add': 'addCategory'
},
initialize: function() {
_.bindAll(this, 'render');
this.collection.fetch();
this.listenTo(this.collection, 'all', this.render);
},
show: function() {
$("#categorymodal").modal();
},
addCategory: function(e) {
e.preventDefault();
// I wrote the next three lines here explicitly rather than using 'create'
var model = new Category({ name: $(this.el).find('.category_name').val() });
model.save();
this.collection.add(model);
this.show();
},
removeCategory: function(e) {
e.preventDefault();
var id = $(e.target).parents('li').data('id');
var model = this.collection.where({ id: id })[0];
this.collection.remove(model);
if (model) { model.destroy(); }
this.render();
},
render: function() {
$(this.el).html(this.index_template());
this.collection.models.forEach(function(cat) {
var li_template = HandlebarsTemplates['categories/show']
$(this.el).find('.categories').append(li_template({
id: cat.toJSON().id,
name: cat.toJSON().name
}));
}, this);
return this;
}
});
Here is my #create action in Rails....
def create
#category = Category.create(category_params)
render :nothing => true
end
I am using jbuilder to provide the JSON from the Rails API.
Here is my Backbone model and collection...
window.Category = Backbone.Model.extend({
urlRoot: "categories"
});
window.Categories = Backbone.Collection.extend({
model: Category,
url : function() {
return 'categories';
}
});
I figured out my problem. It was in my Rails controller, not with Backbone create. I changed my #create action from this...
def create
#category = Category.create(category_params)
render :nothing => true
end
...to this....
def create
#category = Category.create(category_params)
redirect_to category_path(#category)
end
...with my show action being this...
def show
#category = Category.find(params[:id])
end
...that provided me with http://localhost:3000/categories/752.json. I've gotta make sure my backend is providing what I need JSON-wise!

How to pass value through link in controller function

How to pass value through link in controller function.
I want to pass below rc value in link so that routes collect it and send to controller.I am new bies in rails.Anyone please help me to solve the problem.
my html.erb .which collect value from text box through jQuery function.
<script type="text/javascript">
var rc=jQuery("#commonid").val();
</script>
<div ><%=link_to "Alert By Region",alerts/filter_alert %></div>
my routes.rb
file which match the link and send to controller
match 'alerts/filter_alert', :controller => 'alerts', :action => 'filter_alert'
my controller
def filter_alert(x)
#message=x
#title = #title + ' - Alerts'
render :site_alerts
end
Javascript things belong to Javascript. You need to manipulate this value dynamically upon visitor's clicking this link.
In Rails' controller side, you can't hard code the method. You need to use params from query string because you won't know what the input is.
# Views
link_to 'Alert By Region', 'alerts/filter_alert', id: 'alert-link'
# Javascript
$('#alert-link').on('click', function() {
var rc = $("#commonid").val();
if rc {
this.attr['href'] += '?rc='+ encodeURI(rc);
return true;
} else {
alert 'input is blank!';
return false;
}
});
# Controller
def filter_alert
rc = params[:rc]
# Then process based on this
end

Can we pass additional parameters along with render method in rails

Controller method:
def add
#project = Project.find(1)
render xml: #project #wish to pass one more variable like this here
end
ajax call :
endpoint = ROOT_PATH + '/projects/add/'+data_type;
$.ajax({
url : endpoint,
type : "get",
dataType : "xml",
success : function(xml) {
id = $(xml).find('id').text();
title = $(xml).find('title').text();
// wish to display the sent additional parameter here.
}
});
I am able to get project instance parameters 'id' and 'title' in the ajax call.But I wish to send one more parameter along with the #project and wish to use the value of this parameter inside the ajax call. Could some one help me out pls. Thanks!
One of the ways could be:
render xml: #patient.as_json.merge({:YOUR_KEY => YOUR_VALUE})
if you want to send the requested params or nil #patient then:
requested_params = params.except(:controller, :action)
render xml: #patient.present? ? #patient.as_json.merge(requested_params) : requested_params`

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