Rails 4 - How to populate remote content in a form? - ruby-on-rails

Here is what I have
I have a method like this in my bookmarks_controller.rb
def fetch
#result = LinkThumbnailer.generate(params[:url])
end
I have the following form fields to create new bookmarks
url
title
description
thumbnail
tags
So my new.html.erb looks like this
<%= form_for(#bookmark, :html => {class: "panel-body"}) do |f| %>
<% if #bookmark.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#bookmark.errors.count, "error") %> prohibited this bookmark from being saved:</h2>
<ul>
<% #bookmark.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="block">
<%= f.label :url, :class => 'control-label' %>
<%= f.text_field :url, :class => 'form-control', :placeholder => 'URL' %>
</div>
<div class="block">
<%= f.label :title, :class => 'control-label' %>
<%= f.text_field :title, :class => 'form-control', :placeholder => 'Title' %>
</div>
<div class="block">
<%= f.label :description, :class => 'control-label' %>
<%= f.text_area :description, rows: 6, :class => 'form-control', :placeholder => 'Description' %>
</div>
<div class="block">
<%= f.label :thumbnail, :class => 'control-label' %>
<%= f.text_field :thumbnail, :class => 'form-control', :placeholder => 'Thumbnail url' %>
</div>
<div class="block">
<%= f.label :tag_list, :class => 'control-label' %>
<%= f.text_field :tag_list, :class => 'form-control', :placeholder => 'Tags (separated by commas)' %>
</div>
<div class="actions">
<%= f.submit :class => "btn btn-info" %>
</div>
<% end %>
I would like to have a button called Fetch right next to url field.
When user click Fetch button, I would like to populate the form fields using ajax.
I viewed rails documentation. It says to add remote: true attribute to the form.
But I wanna use ajax function only when the user click fetch button.
Can someone help me with this?
Thankyou

You can generate an object using the LinkThumbnailer gem and than convert it to json
with this action:
def fetch
#result = LinkThumbnailer.generate(params['given_url'])
respond_to do |format|
format.json do
result.to_json
end
end
end
And in your view you could use the Jquery getJSON method to access the #fetch action and pass the given url as a parameter:
<script type="text/javascript">
require(['jquery'], function($) {
$('.fetch-button-class').change(function() {
var given_url = $('.url-class').val();
$.getJSON('<%= fetch_action_url %>', {'given_url': given_url }, function(obj) {
$('.title-class').val(object.title);
$('.description-class').val(object.description);
});
});
});
</script>

Related

What is a better way of collection_select for large datasets?

Currently, I have a model with 100+ records. I have a second model that has_one of the first model. In my form to create the second model, I'm using collection_select calling the first model. The user ends up having to scroll and look through each record. Is there a searchable collection_select or some other form helper that would make this a better experience? Below is my current solution:
<%= form.collection_select :thing_id, Thing.all, :id, :name, {class: "form-control"} %>
_form.html.erb
<%= form_with(model: order) do |form| %>
<% if order.errors.any? %>
<div style="color: red">
<h2><%= pluralize(order.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% order.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= form.label 'Status:' %>
<%= form.collection_select :order_status_id, OrderStatus.all, :id, :status, #order.persisted? ? {class: "form-control"} : {:selected => 1}, {class: "form-control"} %>
</div>
<div>
<%= form.label :subject, style: "display: block" %>
<%= form.text_field :subject %>
</div>
<div>
<%= form.label :body, style: "display: block" %>
<%= form.text_area :body %>
</div>
<div>
<%= form.label 'Asset:' , style: "display: block" %>
<%= form.collection_select :thing_id, Thing.all, :id, :name, {class: "form-control"} %>
</div>
<div class="form-group">
<%= form.label :assigned_to %>
<%# form.collection_select :assigned_to_id, User.all, :id, :email, {:include_blank => true}, {class: "form-control"} %>
<%= form.collection_select :assigned_to_id, User.all, :id, :email, {:prompt => true}, {class: "form-control"} %>
</div>
<div class="mb-3">
<%= form.label :images, class: "form-label" %>
<%= form.file_field :images, {multiple: true, class: "form-control", id: "formFileMultiple", type: "file"} %>
</div>
<%= form.hidden_field :requested_by_id, value: current_user.id %>
<div>
<%= form.submit %>
</div>
<% end %>
I'd be happy to include any other code if requested.
You could use select2
Select2 is a jQuery replacement for dropdown boxes and it contains a searchbox to filter through data and other features too such as lazy loading dropdown options. Check it out
https://select2.org/getting-started/basic-usage

No route matches [POST] "/links/new"

I have a model called 'links.' In routes.rb I have defined it with:
resources :links
I have a form in /links/new it looks like this:
<%= form_for :links do |f| %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :url %>
<%= f.url_field :url, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit :"Create Link", class: "btn btn-primary" %>
</div>
<% end %>
When I submit it, I get the error No route matches [POST] "/links/new"
even though this is in the list of routes:
new_link_path GET /links/new(.:format) links#new
What is the problem?
Try this:
<%= form_for(Link.new) do |f| %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :url %>
<%= f.url_field :url, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit "Create Link", class: "btn btn-primary" %>
</div>
<% end %>
add NEW route method in controller Controller
def new
#link = Link.new
end
When you will visit to links/new then new route method will call and render links/new template. so add below code in tamplete
<% form_for(:link, #link, :url => {:action => 'create'}) do |f| %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :url %>
<%= f.url_field :url, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit "Create Link", class: "btn btn-primary" %>
</div>
<% end %>
and handle create request in create action of link controller
def create
#link = Link.new params[:link]
if #link.save
redirect_to :action => 'show', :id => #link.id
else
render :action => 'new'
end
end
dont forget to allow params for link in controller.
this is a proper way to create a new record in ror

My submit button won't work in rails and I'm not sure why

I'm creating a simple form in rails and the submit button doesn't work. I think I'm missing something obvious here but the html seems to be fine (I'm far froma front end expert). Any advice or pointers?
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h2>Apply</h2>
<hr class="star-primary">
</div>
</div>
<div class="row">
<div class="col-lg-8 col-lg-offset-2">
<div class="row control-group">
<% if #user.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(#user.errors.count, "error") %>.
</div>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="col-xs-12 floating-label-form-group controls">
<%= form_for #user, url: users_path(#user), :html => {:method => :post} do |f| %>
<%= f.label :name %>
<%= f.text_field :name, class: "form-control", placeholder: 'Name' %>
<%= f.label :email%>
<%= f.text_field :email, class: "form-control", placeholder: "Email" %>
<%= f.label :address%>
<%= f.text_field :address, class: "form-control", placeholder: "Address" %>
<%= f.label :phone %>
<%= f.text_field :phone, class: "form-control", placeholder: "Phone Number" %>
<%= f.submit "Apply"%>
<%end%>
</div>
</div>
</div>
</div>
</div>
Also, when the submit button fails, nothing happens. No error messages, no console errors. Nothing.
Take method out from the html hash?
form_for #user, url: users_path(#user), :method => :post do |f|
Try this:
<%= form_for #user, :url => {:controller => "your-controller-name", :action => "your-action-name"} do |f| %>
Can you try this one:
<%= form_for #user, url: {action: "create"} do |f| %>
...
...
<%= f.submit "Apply" %>
<% end %>
But I strongly suggest you to use simple_form gem.

Active Merchant and f.submit button on the same view

I have active merchant the i am using simple form.
Is there a way that i can submit the form and also submit the simple_form data at the same time?
Example:
<%= simple_form_for #billing, url: checkout_shopping_cart_path do |f| %>
<h3>Billing & Registration Details</h3>
<hr>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="inputFirstName" class="control-label">Title:</label>
<div>
<%= f.input :title, collection: [ 'Mr', 'Mrs', 'Ms' ], selected: 'Mr', label: false %>
</div>
</div>
</div>
<%= f.submit 'Submit', class: 'btn btn-default-1' %>
<% end %>
</div>
<% payment_service_for #order.reference_id, 'XXXXXXXXXXXX',
:amount => #order.total*100.round,
:currency => 'SGD',
:credential2 => 'xxxxxxxxxx',
:service => :ipay88 do |service| %>
<% service.customer :first_name => #user.account.first_name,
:last_name => #user.account.last_name,
:email => #user.email,
:phone => #user.phone %>
<% #shopping_cart.shopping_cart_items.each do |shopping| %>
<% service.description shopping.item.name %>
<% end %>
<% service.return_url url_for(:only_path => false,
:controller => 'pay', :action => 'return') %>
<%= submit_tag "Pay", class: 'btn-default-1' %>
<% end %>
The result that i have is having two buttons. How do i make it all at one page?

Rails - prepopulate textarea with existing attribute

I have following situation:
I've got two models
a Risk model with the attributes name, risk_class_id, description, level
a Risk_Class model with the attributs name and description
A Risk has one Risk Class and a Risk Class has many Risks. This association works fine. I can assign a Risk Class to a Risk. To create a Risk I use the following form:
<%= form_for #risk, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<%= f.label :name, :class => 'control-label' %>
<div class="controls">
<%= f.text_area :name, :class => 'text_area' %>
</div>
</div>
<div class="control-group">
<%= f.label :risk_class_id, :class => 'control-label' %>
<div class="controls">
<%= collection_select( :risk, :risk_class_id, RiskClass.all, :id, :name, :prompt => true ) %>
</div>
</div>
<div class="control-group">
<%= f.label :description, :class => 'control-label' %>
<div class="controls">
<%= f.text_area :description, :class => 'text_area' %>
</div>
</div>
<div class="control-group">
<%= f.label :level, :class => 'control-label' %>
<div class="controls">
<%= f.text_area :level, :class => 'text_area' %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
</div>
<% end %>
Now i would like to have that the textarea field for the description gets prepopulated based on the selected risk class, as a risk class has a description.
Thankful for any help!
EDIT
I've added following javascript code to the form and edited the collection select the following way:
<%= javascript_tag do %>
function risk_class_selection(riskclassId){
window.alert(riskclassId);
}
<% end %>
<div class="control-group">
<%= f.label :risk_class_id, :class => 'control-label' %>
<div class="controls">
<%= collection_select( :risk, :risk_class_id, RiskClass.all, :id, :name, {:prompt => true} , {:onchange => "risk_class_selection(this.value)"}) %>
</div>
</div>
SOLUTION:
in case anyone is interested i followed the way grotori described and my solution looks now like this:
I've got this risk.js file:
function risk_class_selection(riskclassId){
if (riskclassId != ""){
$.getJSON("/risk_classes/"+riskclassId+".json", function(data){
if ( $('#risk_description').val() == "" ){
$("#risk_description").val(data.description);
}
else{
if ( confirm('Are you sure you want to change the risk description?') ){
$("#risk_description").val(data.description);
}
else{
}
}
}
)
}
else{}
}
And in the Risk Form i've got the first div with the onchange event and the second where the textarea should be prepopulated:
<div class="control-group">
<%= f.label :risk_class_id, :class => 'control-label' %>
<div class="controls">
<%= collection_select( :risk, :risk_class_id, RiskClass.all, :id, :name, {:prompt => true} , {:onchange => "risk_class_selection(this.value)"}) %>
</div>
</div>
<div class="control-group">
<%= f.label :description, :class => 'control-label' %>
<div class="controls">
<%= f.text_area :description, :class => 'text_area' %>
</div>
</div>
You must bind an onchange event to your select field that will post back to your server the user's selection and respond with javascript that will re-render the textarea with the desired value you want.
You can do it in controller when preparing the object #risk. Something like this:
#risk = Risk.new(description: "blah blah")
Then the form will have this value with form_for tag.

Resources