How to route navbar search to a specific index view? - html

I'm trying to implement a navbar search and have attempted to follow these solutions https://stackoverflow.com/a/19929707/5101493 and
https://stackoverflow.com/a/52538766/5101493.
Unfortunately my navbar search only works when on the /businesses index page and not otherwise. After search submission the app stays on the same page instead of directing to /businesses.
How can I fix this? Here are my relevant files:
application_controller
before_action :set_global_search_variable
def set_global_search_variable
#p = Business.search(params[:q])
end
businesses_controller
def index
#businesses = #p.result(distinct: true).sort_by(&:name)
end
def search
index
render :index
end
routes
resources :businesses do
collection do
match 'search' => 'businesses#search', via: [:get, :post], as: :search
end
end
_header partial
<form class="form-inline" style='display:show'>
<%= search_form_for #p , url: search_businesses_path, :html => { method: :post } do |f| %>
<%= f.search_field :name_cont, {placeholder: " Find a business...", class: 'form-control mr-sm-2'} %>
<%= f.submit "Search", class: "btn look-red my-2 my-sm-0 navsearch" %>
<% end %>
</form>

You can't have a form inside another form. The outermost form is always routing to the current page.
Instead make the outermost form a div.
<div class="form-inline" style='display:show'>
<%= search_form_for #p , url: search_businesses_path, :html => { method: :post } do |f| %>
<%= f.search_field :name_cont, {placeholder: " Find a business...", class: 'form-control mr-sm-2'} %>
<%= f.submit "Search", class: "btn look-red my-2 my-sm-0 navsearch" %>
<% end %>
</div>

Related

How can I filter a specific params key from params passed in a link_to?

I have an index where users can apply many different kinds of filters through checkboxes.
Each filter has an "X" link_to button that dismisses the filter, which basically makes a request to the same index page permiting the current params with the exception of the dismissed filter's param key.
For example:
<div class="form-group <%= 'hidden' unless params.dig(:q, "subscription_payment_type_eq").present? %>" id="subscription_payment_type_eq" data-toggle-target="objective">
<%= f.select :subscription_payment_type_eq, payment_types_selector_for_filter, { include_blank: "Forma de pago..."}, class: "form-control gray my-2 " %>
<% if params.dig(:q, "subscription_payment_type_eq").present? %>
<%= link_to admin_users_path(params: params.permit(q: [:extra_params, :address_province_eq, :subscription_status_eq, :created_at_gteq, :created_at_lteq])) do %>
<span class="dismiss-box glyphicon glyphicon-remove-circle">
<% end %>
<% end %>
</div>
<div class="form-group <%= 'hidden' unless params.dig(:q, "address_province_eq").present? %>" id="address_province_eq" data-toggle-target="objective">
<%= f.select :address_province_eq, user_provinces_selector_for_filter, { include_blank: "Provincia..."}, class: "form-control gray my-2 " %>
<% if params.dig(:q, "address_province_eq").present? %>
<%= link_to admin_users_path(params: params.permit(q: [:extra_params, :subscription_payment_type_eq, :subscription_status_eq, :created_at_gteq, :created_at_lteq])) do %>
<span class="dismiss-box glyphicon glyphicon-remove-circle">
<% end %>
<% end %>
</div>
The approach works, but it's very cumbersome to manually add the excepted param key to each new filter that is added to the index page.
Is there a way to pass params excluding the param key that belongs to the filter being dismissed?
I've tried the following but no params are passed:
<% if params.dig(:q, "subscription_payment_type_eq").present? %>
<%= link_to admin_users_path(params: params[:q].except(:subscription_payment_type_eq).permit) do %>
<span class="dismiss-box glyphicon glyphicon-remove-circle">
<% end %>
<% end %>
Also tried this but got undefined method 'exclude' for #<ActionController::Parameters:0x00007f6331b00dd8>
<%= link_to admin_users_path(params: params.exclude(:subscription_payment_type_eq).permit) do %>
Permit expects a list of args and since you're not sending any no params will be passed to your controller. I'm actually not sure how your calling permit without args is even working. Anyway maybe you can try it like this instead:
<%= link_to admin_users_path(params: params[:q].except(:subscription_payment_type_eq.permit!)
In the end we decided to implement it this way:
<%= link_to admin_users_path(
params: { q: params.require(:q).permit(params[:q].keys - ["address_province_eq"]) }
) do %>
We basically substract the filter's key from the current params when passing it in the link_to

Rails use content_for and render the same layout twice

I am using a theme that has very specific layouts and I wanted to make a failsafe way to you rails forms.
I have a layout app/views/shared/forms/fields/_layout.html.erb
<div class="js-form-message mb-4">
<div class="js-focus-state input-group u-form">
<div class="input-group g-brd-primary--focus">
<%= yield(:field) %>
</div>
</div>
</div>
And I have two partials.
1-st partial: app/views/shared/forms/fields/_email.html.erb
<% form = locals[:form] %>
<% locals[:required] = locals[:required].nil? ? true : locals[:required] %>
<% locals[:placeholder] = locals[:placeholder] || t('forms.shared.email.placeholder') %>
<%= render layout: "shared/forms/fields/layout", locals: locals do %>
<% content_for(:field) do %>
<%= form.email_field :email,
placeholder: locals[:placeholder],
class: "form-control g-py-15 g-px-15",
"data-error-class"=>"u-has-error-v1-3",
"data-success-class"=>"u-has-success-v1-2",
"data-msg-email" => t('forms.shared.email.validate'),
"data-msg" => t('forms.shared.required'),
autofocus: locals[:autofocus],
required: locals[:required] %>
<% end %>
<% end %>
2-nd partial: app/views/shared/forms/fields/_login.html.erb
<% form = locals[:form] %>
<% locals[:required] = locals[:required].nil? ? true : locals[:required] %>
<% locals[:placeholder] = locals[:placeholder] || t('forms.shared.login.placeholder') %>
<%= render layout: "shared/forms/fields/layout", locals: locals do %>
<% content_for(:field) do %>
<%= form.email_field :login,
placeholder: locals[:placeholder],
class: "form-control g-py-15 g-px-15",
"data-error-class"=>"u-has-error-v1-3",
"data-success-class"=>"u-has-success-v1-2",
"data-msg" => t('forms.shared.required'),
autofocus: locals[:autofocus],
required: locals[:required] %>
<% end %>
<% end %>
And when I do this:
<%= render "shared/forms/fields/email", locals: {form: f} %>
<%= render "shared/forms/fields/login", locals: {form: f} %>
I get
Email Field
Email Field/Login Field
I found out that content_for 'appends' the block that you give it and then when I yield the whole block is returned.
The first time there is nothing in content_for(:field) and it appends to it Email Field. But the second time it does not clear its content and just appends Login Field to it.
I am thinking of adding additional complexity to layout.html.erb so just keeping it inline isn't an option.
Is there a way to tell to the layout only to yield the 'newest' value of content_for.
EDIT:
I wrote a method to flush after an yield, suggesting that the same key would be used again:
def yield_and_flush!(content_key)
view_flow.content.delete(content_key)
end
content_for has flush option to reset previous content:
<% content_for :field, flush: true do %>
new content here
<% end %>
The solution was this to write an yield_and_flush! method. I saw the solution here
def yield_and_flush!(content_key)
view_flow.content.delete(content_key)
end

Rails 4: Access all CRUD from index.html.erb

I'm trying to create only a 1 page index site.
I Want to handle creating, deleting, editing all within my 1 index. (very basic)
However, I followed the beginners for getting started:
http://guides.rubyonrails.org/getting_started.html
Example of my article controller:
def index
#articles = Article.all #Create Articles and then add the for loop inside the index.html
#article = Article.new
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
end
end
def new
#article = Article.new
end
...
private
def article_params
params.require(:article).permit(:title, :text)
end
I Use #articles to populate all articles ever added. And then #article to for CRUD. Except I can't get full control to CRUD from the index.html page.
<form role="form" class="form-inline">
<div class="form-group">
<%= form_for #article do |f| %>
<div class="form-group">
<label for="textUserInputDescription"><%= f.label :title %><br/><%= f.text_field :title %>
</label>
<label for="textUserInputDescription"><%= f.label :text %><br/><%= f.text_area :text %> </label>
<button type="submit" class="btn btn-default"><%= f.submit %></button>
</div>
<% end %>
</div>
When I click Submit, It does not add to my database.
My Question is: How do I get access to CRUD all from within the index.html?
Thanks for your time, I'm still learning Rails/CRUD/ActiveRecord and following tutorials.
I changed f.submit to:
<%= button_to "Create", new_article_path(#article[:title], #article[:text]), method: :post %>

Ruby on Rails Button too close to form

I'm new to Ruby and programming in general. I'm creating this log in page using simple form but the Create account button is to close to the confirm password form I don't know how to enter a break between these two.
Thank you!
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: 'form-horizontal'}) do |f| %>
<%= devise_error_messages! %>
<%= f.input :email, :label => 'Correo Electronico' %>
<%= f.input :password, :label => 'ContraseƱa' %>
<%= f.input :password_confirmation, :label => 'Confirmar ContraseƱa' %>
<div>
<%= f.submit "Crear cuenta", class: "btn btn-primary" %>
</div>
<% end %>
You should use a HTML class/id and put these rules in a CSS file. But there is 2 ways:
The quick & diry way:
<div style="margin-top: 15px;">
<%= f.submit "Crear cuenta", class: "btn btn-primary" %>
</div>
The proper way:
# app/assets/stylesheets/application.css.scss (or extension can be .sass)
body div.form_action_buttons {
margin-top: 15px;
}
# your view
<div class='form_action_buttons'>
<%= f.submit "Crear cuenta", class: "btn btn-primary" %>
</div>

Accessing elements between forms

I am trying to access the value of an element in a different form. More specifically I have two forms, one normal html form which submits the information, and an ajax form that updates a field in the database. I want the ajax form to take the value of an element in the normal form, but I have no idea how to accomplish that. Here is my current setup:
Message View
<%= form_for #message do |f| %>
<%= f.text_field :to %>
<%= f.text_area :body %>
<%= f.submit "Send Message" %>
<% end %>
<%= form_for :save, :url => save_message_path(), :remote => :true do |f| %>
<%= f.submit "Save" %>
<% end %>
Message Controller
def save
account.message = params[:body]
end
But the :body param is in the other form so it sets account.message to nil because the ajax form did not have a body parameter. I would like it so the ajax form can submit the value of the body element.
Since the form is edited on the client side, you'll have to write this functionality in javascript.
It is relatively straightforward to copy the value of the message body into a hidden field and submit the Ajax form. This would be most easily accomplished by adding an id your ajax form as follows:
<%= form_for :save, :url => save_messages_path(), :remote => true, :id => 'ajaxform' %>
<%= hidden_field_tag 'hidden_message' %>
Then in javascript you could do the following:
$(document).ready(function(){
$("#ajaxform").submit(function() {
$("#hidden_message").val($("#message_body").val());
return true;
});
}
You can add a hidden field body in your ajax form, and use an onsubmit event to populate it with the value of the body field from the normal form before the ajax request is sent. It would look more or less like this:
<%= form_for #message do |f| %>
<%= f.text_field :to %>
<%= f.text_area :body, :class => 'main_body_field' %>
<%= f.submit "Send Message" %>
<% end %>
<%= form_for :save, :url => save_message_path(), :remote => :true, :id => 'ajax_form' %>
<%= f.hidden_field :body, :class => 'hidden_body_field' %>
<%= f.submit "Save" %>
<% end %>
javascript (with jQuery):
$(function() {
$("ajax_form").submit(function() {
// copy body value from first form to the second one
$('.hidden_body_field').val($('.main_body_field').val());
return true;
}
}