how to render partial without variable with turbo - ruby

I search trough internet, but I only find 'how to render partial after update' etc. For now I click on the image, page is refereshing and partial appear. But this refreshing part is... not good for me, so I wonder.. Can I render partial (or replace if I rendered one already) with Turbo?
Ruby version: 3.0.4
Rails version: 6.1.6
My view:
.container.flex.flex-col.mx-auto.w-full.py-16
.text-center
%h1.text-2xl.font-extrabold.text-gray-700.md:text-4xl
= t('pages.partners.title')
%p.mt-2.md:text-xl
= t('pages.partners.subtitle')
%h2.my-6.text-xl.font-extrabold.text-gray-700.md:text-2xl
= t('pages.partners.foreign_partners')
.grid.grid-cols-5.gap-x-4
= link_to partners_path(foreign_partner: '2'), class: 'border-2 border-black transform hover:-translate-y-1 hover:scale-110' do
.flex.h-full.w-full
= image_tag '/partners/logo2.png', size: '100x100', class: 'h-full w-full p-1 object-scale-down'
= link_to partners_path(foreign_partner: '1'), class: 'border-2 border-black transform hover:-translate-y-1 hover:scale-110' do
.flex.h-full.w-full
= image_tag '/partners/logo1.png', size: '100x100', class: 'h-full w-full p-1 object-scale-down'
= link_to partners_path(foreign_partner: '3'), class: 'border-2 border-black transform hover:-translate-y-1 hover:scale-110' do
.flex.h-full.w-full
= image_tag '/partners/logo3.png', size: '100x100', class: 'h-full w-full p-1 object-scale-down'
= link_to partners_path(foreign_partner: '4'), class: 'border-2 border-black transform hover:-translate-y-1 hover:scale-110' do
.flex.h-full.w-full
= image_tag '/partners/logo4.png', size: '100x100', class: 'h-full w-full p-1 object-scale-down',
-if params[:foreign_partner]
= render 'pages/partials/foreign_partners'
%h2.text-center.my-6.text-xl.font-extrabold.text-gray-700.md:text-2xl
= t('pages.partners.domestic_partners')
.grid.grid-cols-5.gap-x-4
%div
= link_to partners_path(domestic_partner: '5'), class: 'border-2 border-black transform hover:-translate-y-1 hover:scale-110' do
.flex.h-full.w-full
= image_tag '/partners/logo5.png', size: '100x100', class: 'h-full w-full p-1 object-scale-down'
= link_to partners_path(domestic_partner: '6'), class: 'border-2 border-black transform hover:-translate-y-1 hover:scale-110' do
.flex.h-full.w-full
= image_tag '/partners/logo6.png', size: '100x100', class: 'h-full w-full p-1 object-scale-down'
-if params[:domestic_partner]
= render 'pages/partials/domestic_partners'
My 'foreign partners' partial:
.flex.flex-col.border-2.mt-6.p-8.relative.sm:flex-row.md::flex-row.lg::flex-row.xl:flex-row.2xl:flex-row{ :role => "region", :'aria-label' => "#{t("pages.partners.partners.#{params[:foreign_partner]}.company_name")}" }
.absolute.right-0.top-0
= link_to 'X', partners_path, class: 'w-7 h-7 bg-gray-100 flex justify-center items-center hover:bg-gray-300', role: "button", 'aria-label': "#{t("a11y.close") + " " + t("pages.partners.partners.#{params[:foreign_partner]}.company_name")}"
.flex.flex-col.mr-2.w-full{class: 'sm:w-1/2 md:w-1/2 lg:w-1/2 xl:w-1/2 2xl:w-1/2'}
.flex.justify-center.items-center.w-full.h-72
= image_tag "/partners/#{params[:foreign_partner]}-logo.png", size: '250x250', class: 'object-scale-down p-1', alt: "Logo #{t("pages.partners.partners.#{params[:foreign_partner]}.company_name")}"
%p.py-3.text-xl.font-extrabold
= t("pages.partners.partners.#{params[:foreign_partner]}.company_name")
.bg-gray-100.h-max.flex.items-center
= image_tag '/partners/link.ico', size: '25x25', alt: "#{t("a11y.link")}"
= link_to t("pages.partners.partners.#{params[:foreign_partner]}.website_link"), t("pages.partners.partners.#{params[:foreign_partner]}.website_link"), target: "_blank", class: 'ml-3 hover:text-primary-500'
.bg-gray-100.my-2.h-max.flex.items-center
= image_tag '/partners/email.ico', size: '25x25', alt: 'E-Mail:'
= mail_to t("pages.partners.partners.#{params[:foreign_partner]}.company_email"), t("pages.partners.partners.#{params[:foreign_partner]}.company_email"), class: 'ml-3 hover:text-primary-500'
.bg-gray-100.h-max.flex.items-center
= image_tag '/partners/phone.ico', size: '25x25', alt: "#{t("a11y.phone")}"
%span.ml-3= t("pages.partners.partners.#{params[:foreign_partner]}.company_phone_number")
.flex.flex-col.border-t-2.mt-3.w-full.sm:border-t-0.sm:border-l-2.sm:mt-0{class: 'sm:w-1/2 md:w-1/2 lg:w-1/2 xl:w-1/2 2xl:w-1/2'}
.flex.flex-col.p-4.overflow-y-auto.h-96.md:p-8
%p.text-2xl.font-extrabold= t('pages.partners.about_company')
%p.mt-5.text-justify.overflow-y-auto= t("pages.partners.partners.#{params[:foreign_partner]}.content")
My 'domestic_partners' partial:
.flex.flex-col.border-2.mt-6.p-8.relative.sm:flex-row.md::flex-row.lg::flex-row.xl:flex-row.2xl:flex-row{ :role => "region", :'aria-label' => "#{t("pages.partners.partners.#{params[:domestic_partner]}.company_name")}" }
.absolute.right-0.top-0
= link_to 'X', partners_path, class: 'w-7 h-7 bg-gray-100 flex justify-center items-center hover:bg-gray-300', role: "button", 'aria-label': "#{t("a11y.close") + " " + t("pages.partners.partners.#{params[:domestic_partner]}.company_name")}"
.flex.flex-col.mr-2.w-full{class: 'sm:w-1/2 md:w-1/2 lg:w-1/2 xl:w-1/2 2xl:w-1/2'}
.flex.justify-center.items-center.w-full.h-72
= image_tag "/partners/#{params[:domestic_partner]}-logo.png", size: '250x250', class: 'object-scale-down p-1', alt: "Logo #{t("pages.partners.partners.#{params[:domestic_partner]}.company_name")}"
%p.py-3.text-xl.font-extrabold
= t("pages.partners.partners.#{params[:domestic_partner]}.company_name")
.bg-gray-100.h-max.flex.items-center
= image_tag '/partners/link.ico', size: '25x25', alt: "#{t("a11y.link")}"
= link_to t("pages.partners.partners.#{params[:domestic_partner]}.website_link"), t("pages.partners.partners.#{params[:domestic_partner]}.website_link"), target: "_blank", class: 'ml-3 hover:text-primary-500'
.bg-gray-100.my-2.h-max.flex.items-center
= image_tag '/partners/email.ico', size: '25x25', alt: 'E-Mail:'
= mail_to t("pages.partners.partners.#{params[:domestic_partner]}.company_email"), t("pages.partners.partners.#{params[:domestic_partner]}.company_email"), class: 'ml-3 h hover:text-primary-500'
.bg-gray-100.h-max.flex.items-center
= image_tag '/partners/phone.ico', size: '25x25', alt: "#{t("a11y.phone")}"
%spna.ml-3= t("pages.partners.partners.#{params[:domestic_partner]}.company_phone_number")
.flex.flex-col.border-t-2.mt-3.w-full.sm:border-t-0.sm:border-l-2.sm:mt-0{class: 'sm:w-1/2 md:w-1/2 lg:w-1/2 xl:w-1/2 2xl:w-1/2'}
.flex.flex-col.p-4.overflow-y-auto.h-96.md:p-8
%p.text-2xl.font-extrabold= t('pages.partners.about_company')
%p.mt-5.text-justify.overflow-y-auto= t("pages.partners.partners.#{params[:domestic_partner]}.content")
controller:
def partners
set_meta_tags(title: t('navbar.partners'))
end

Ok, so I did it like this:
In routes.rb I added this route:
post 'partners/:partner', to: 'pages#partners_partial', as: 'partners_partial'
In pages_controller.rb:
def partners
set_meta_tags(title: t('navbar.partners'))
end
def partners_partial
#parameter = params[:partner]
respond_to do |format|
format.turbo_stream
end
end
In partials I removed 'params[..._partner] and replace it with local variable 'parameter'.
Next i change 'partners_path', to "partners_partial_path(partner: 'string')" in partial and view.
And last part. I Added 'partners_partial.turbo_stream.haml' file in 'pages' directory.
-if #parameter == 'close'
= turbo_stream.replace 'partner' do
%div#partner
-else
= turbo_stream.replace 'partner' do
= render partial: 'pages/partials/foreign_partners', locals: {parameter: #parameter}

Related

Rails Simple Form input with Font-Awesome

I want to use icons instead of text for labels in a horizontal simple_form. However, I am unable to separate the text from the icons
= simple_form_for #user, html: { class: 'form-horizontal' }, wrapper: :horizontal_form do |f|
# shows 'username' label only
= f.input :username
# shows icon with 'username'
= f.input :username, label_html: {class: "fas fa-user"}
# shows nothing
= f.input :username, label_html: {class: "fas fa-user"}, label: false
For those who want to do the same, there is a simpler/cleaner way :
= f.label :username, label: ('<i class="fas fa-user"></i>').html_safe
= f.text_field :username
Also work with I18n localization file :
(en.yml)
username: '<i class="fas fa-user"></i>'
then
= f.label :name, label: t(:username).html_safe
= f.text_field :username
Using simple_form (4.1.0)
Hope this help.
You can use the wrapper_html option:
= f.input :username, label: false, wrapper_html: { class: 'fa fa-user' }
You will probably have to add some css to make it look the way you want. For example, to get the icon on a different line than the input, I had to add display: block to the icon.
wrapper_html: and label_html: were complicated, so I just did it manually
.row
.col-3
.text-right
i.fas.fa-user
.col-9
= f.input_field :username, label: false, class: 'form-control'
I've just implemented this very thing on my own project. There was a really simple solution.
First, I created a helper for outputting fontawesome icons. In app/helpers/font_awesome_helper.rb:
module FontAwesomeHelper
def fa_icon(icon, style: :regular)
content_tag(:i, "", class: [icon_style_class(style), icon_class(icon)].join(" "))
end
private
def icon_class(icon)
"fa-#{icon}"
end
def icon_style_class(style)
case style
when :light, :l
"fal"
when :regular, :r
"far"
when :solid, :s
"fas"
when :duotone, :duo, :d
"fad"
else
"fa"
end
end
end
You can extend this further to support inverting icon colours, flipping horizontally, etc.
Finally, you can use your fa_icon helper in your simple-form input:
= f.input :username, label: fa_icon("user", style: :solid)

Ruby on Rails - update fields based on f.select value

I have a dropdown box to chose the number of tickets that one wants to buy. I want to update the fields after it to reflect the value once it is clicked. Here is a snippet of my form currently:
<%= form_for :transaction, :url => new_transaction_path(:event_id => #event.id), :method => 'GET' do |f| %>
<table style="width:100%">
<tr style="border-bottom: 1px solid #999999">
<td><h4>Number of Guests</h4></td>
<td>
<%= f.select(:quantity, (1..20))%>
</td>
</tr>
<tr style="border-bottom: 1px solid #999999">
<!-- replace (1) with the value from the f.select dropdown -->
<td><h4><%= #original_event_price %> x (1) guest(s)</h4></td>
</tr>
</table>
<%= f.submit 'Request to Book', class: 'button mt1 btn-request-to-book' %>
<% end %>
I want to replace (1) with the value from the f.select dropdown in the last table row to the value of guests that the user chooses.
EDIT WITH WORKING SOLUTION
<%= form_for :transaction, :url => new_transaction_path(:event_id => #event.id), :method => 'GET' do |f| %>
<table style="width:100%">
<tr style="border-bottom: 1px solid #999999">
<td><h4>Number of Guests</h4></td>
<td>
<%= f.select :quantity, (1..20), {}, { :onChange=>'mytest()', :id=>'quantitySelect' } %>
</td>
</tr>
<tr style="border-bottom: 1px solid #999999">
<!-- replace (1) with the value from the f.select dropdown -->
<td><h4><%= #original_event_price %> x (1) guest(s)</h4></td>
</tr>
</table>
<%= f.submit 'Request to Book', class: 'button mt1 btn-request-to-book' %>
<% end %>
SCRIPT
<script type="text/javascript">
function mytest() {
var quantity = $('#quantitySelect').val();
$('#quantityRow').html("<h4><%= #original_event_price %> x (" + quantity + ") guest(s)");
}
</script>
Problem : How to load value in other field based on drop-down selection
Solution:
<div class="field form-group">
<%= form.label :grade %>
<%= form.select(:grade, options_for_select(['A', 'B', 'C', 'D', 'E', 'F']), {:include_blank => 'Select Grade'}, class:"form-control", placeholder:"Grade", onchange: "loadRemarksBasedOnGrade()") %>
</div>
<div class="field form-group">
<%= form.label :remarks %>
<%= form.text_field :remarks, class:"form-control", placeholder:"Remarks", readonly: true %>
</div>
JavaScript :
<script type="text/javascript">
function loadRemarksBasedOnGrade() {
var grades = [];
grades['A'] = "Excellent";
grades['B'] = "Very Good";
grades['C'] = "Good";
grades['D'] = "Average";
grades['E'] = "Below average";
grades['F'] = "Failed";
let grade = document.getElementById("student_grade");
if(grades[grade.value] !== undefined) {
document.getElementById("student_remarks").value = grades[grade.value];
} else {
document.getElementById("student_remarks").value = "";
}
}
</script>
Note: So onchnage event loadRemarksBasedOnGrade update value based on id.
You can do this with jQuery:
Let's add an id: "quantitySelect" on the quantity field
Let's also add an id: "quantityRow" on the td field
$(function(){
$('.quantitySelect').change(function(e){
e.preventDefault();
var quantity = $('.quantitySelect').val();
$('.quantityRow').html("<h4><%= #original_event_price %> x (" + quantity + ") guest(s)");
});
});
You can also add if checks to see if the quantity is > 1 and append the word guest to guests.

Ruby templating engine Slim block confusion

I am new to slim and I find it a bit confusing.. so I have this code
td Tags: == item.tag_list.map { |t| link_to t,tag_path(t) }.join(', ')
I am having this output
<td tags:="#<Enumerator:0xbb6e8b4>">{ |t| link_to t,tag_path(t) }.join(', ') </td>
Basically I want the output to be "Tags: tag1,tag2,tag3"
How to get out of the td tag in slim?
edit:
Added a bit more code:
-#items.each do |item|
tr
td = item.title
td = item.description
td = item.price
td = item.user.username
td = item.categories.map { |c| c.name }.join{', '}
- if params[:user_id].nil?
td = link_to 'Show', item_path(item)
- else
td = link_to 'Show', edit_user_item_path(#user,item)
td = link_to 'Edit', edit_user_item_path(#user,item)
td = link_to 'Destroy', user_item_path(#user,item), method: :delete, data: { confirm: 'Are you sure?' }
td Tags: == item.tag_list.map { |t| link_to t,tag_path(t) }.join(', ')
edit: I tried this
- tags = item.tag_list.map { |t| link_to t,tag_path(t) }.join(', ').html_safe
td = "Tags: #{tags}"
but now html_safe is not working so I have this output
Tags:<a href="/tag/tag3">tag3</a>, <a href="/tag/tag2">tag2</a>, <a href="/tag/tag1">tag1</a>
I solved my own problem here is what I did
- tags = item.tag_list.map { |t| link_to t,tag_path(t) }.join(', ').html_safe
<td>Tags: #{tags}</td>
Got it working now like it supposed to.

bringing xml data into the application controller through xpath and posting to a high chart on the application.html.erb page

Below is my code in full for both the application controller and the application.html.erb, I really can't work this out, what is wrong?! this accepts standard values in the high chart, for example, just straight numbers but once I try to call values stored in the array it rejects it. I don't know why. Thanks
class ApplicationController < ActionController::Base
require 'nokogiri'
require 'open-uri'
protect_from_forgery
before_filter :set_locale
def index
#doc= Nokogiri::XML(open("http://api.worldbank.org/countries/BRA/indicators/1.0.HCount.2.5usd?per_page=10&date=1960:2014"))
m = #doc.xpath("//wb:value").collect(&:text)
#values = Array.new
m.each do |m|
#values << m
end
end
end
complete application.html.erb code below:
<!DOCTYPE html>
<html>
<head>
<title>Project</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tags %>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<script>
$(function () {
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Brazil Poverty Headcount'
},
subtitle: {
text: 'Source: WorldBank.com'
},
xAxis: {
categories: [
'2009',
'2008',
'2007',
'2006',
'2005',
'2004',
'2003',
'2002',
'2001',
]
},
yAxis: {
min: 0,
title: {
text: 'X-Axis Data'
}
},
tooltip: {
headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y:.1f} mm</b></td></tr>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [{
name: 'Brazil',
data: <%=#values.inspect%>
}]
});
});
</script>
</head>
<body>
<div style= "margin:50px">
<div id="container" style="min-width: 310px; height: 600px; margin: 15 auto"></div>
<div id ="signing" style="width:200px; height:200px; float:right;">
<% if current_user %>
Logged in as <%= current_user.email %>
<%= link_to "Log Out", logout_path %>
<% else %>
<%= link_to "Sign Up", signup_path %>
<%= link_to "Log In", login_path %>
<% end %>
</div>
<div id="admin" style="width:100px; height:100px; float:right;">
<%= link_to "Admin", new_admin_user_session_path %>
</div>
<div>
Language:
<%= link_to_unless_current "English", locale: "en" %> |
<%= link_to_unless_current "Spanish", locale: "sp" %>
</div>
<%= yield %>
</div>
</body>
</html>
I have actually deployed your app and try the following.
Create controller chart:
rails g controller chart
Edit app/controllers/chart_controller.rb and add the following:
def index
#doc = Nokogiri::XML(open("http://api.worldbank.org/countries/BRA/indicators/1.0.HCount.2.5usd?per_page=10&date=1960:2014"))
m = #doc.xpath("//wb:value").collect(&:text)
#values = Array.new
m.each do |m|
#values << m.to_f
end
end
Now create file views/chart/index.html.erb and paste following:
<!DOCTYPE html>
<html>
<head>
<title>Maxo</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= javascript_include_tag "http://code.highcharts.com/highcharts.js" %>
<%= javascript_include_tag"http://code.highcharts.com/modules/exporting.js" %>
<%= csrf_meta_tags %>
<script>
$(function () {
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Brazil Poverty Headcount'
},
subtitle: {
text: 'Source: WorldBank.com'
},
xAxis: {
categories: [
'2009',
'2008',
'2007',
'2006',
'2005',
'2004',
'2003',
'2002',
'2001',
]
},
yAxis: {
min: 0,
title: {
text: 'X-Axis Data'
}
},
tooltip: {
headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y:.1f} mm</b></td></tr>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [{
name: 'Brazil',
data: <%= #values.inspect %>
}]
});
});
</script>
</head>
<body>
<div style= "margin:50px">
<div id="container" style="min-width: 310px; height: 600px; margin: 15 auto"></div>
</div>
<%= yield %>
</div>
</body>
</html>
Also make sure that you have proper routing rule added to: config/routes.rb. For just simplicity you could just add:
root :to => 'chart#index'
In that case when you localhost:3000, you will get the chart/index view automatically. I have tested it and it works fine.
Just for any case views/layouts/application.html.erb should look:
<!DOCTYPE html>
<html>
<head>
<title>Test2</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>

Why can't I display the next three future events from my model?

I am attempted to display the next three future events from my database but the code below displays nothing. I can't see what I have done wrong.
This is the event controller:
class EventsController < ApplicationController
def show
#event = Event.where(:slug => params[:slug]).first
#future_events = Event.where('end_date > ?', Date.today).order('end_date ASC').limit(3)
General.first.get_blog
General.first.get_twitter
if #event.nil?
#event = Event.first
end
#days = [
{ speakers: #event.sessions.day1_speakers, workshops: #event.sessions.day1_workshops },
{ speakers: #event.sessions.day2_speakers, workshops: #event.sessions.day2_workshops }
]
end
end
And this is the event view:
<% #future_events.first(3).each do |e | %>
<div class="fourcol aboutColumn">
<h3><%= e.title %></h3>
<p><%= e.start_date.strftime("%e %B %Y") %>, <%= e.venue_title %></p>
<p><%= e.event_description %></p>
</div>
<% end %>
You should structure your query to return only the events you need:
Event.where('end_date > ?', Date.today).order('end_date ASC').limit(3)
Beyond that, I can't see why nothing is displayed. Can you post your entire controller method?
Update:
This is the equivalent query for Mongoid:
Event.where(:end_date.gt => Date.today).sort(:end_date => 1).limit(3)

Resources