ruby on rails rending two forms inside a page - ruby-on-rails

I have two modals on one page. When clicked on button Add Providers one modal should pop up for that. When I clicked on Add Hospital another modal should pop up. However, no matter which button I clicked on only the modal for 'Providers' showed up? No idea why.
Modal 1 is happening from the render partial provider_access_modal and the second is supposeed to happen at rendering the partial sites_access_modal
<%= render :partial => 'provider_access_modal' %> ##Modal 1
<%= render :partial => 'shared/side_menu' %>
<div id="profiles" class="container-main">
<%= render :partial => 'patients/top_bar' %>
<div class="top-space"></div>
<div class="flash">
<%- flash.each do |name, msg| -%>
<%= content_tag :div, msg, :class => "flash_#{name}" if msg.is_a?(String) %>
<%- end -%>
</div>
<div class="content-container your-sites">
<div class="header">
<div class="icon-circle"><div class="icon"><%= image_tag "my-providers-2x.png" %></div></div>
<div class="title">Your Providers</div>
<div class="button-wrapper">
<%= button_tag "Add Provider", class:"add-button", id: 'add-provider-modal' %>
<div class="push"></div>
</div><!--button-wrapper-->
</div><!--header-->
<div class="body">
<div class="no-records">
<%= image_tag "icon-no-records", class: "image" %>
<div class="text">You have no providers.</div>
</div>
</div>
</div>
<%= render :partial => 'sites_access_modal' %> ##Modal 2
<div class="content-container your-sites">
<div class="header">
<div class="icon-circle"><div class="icon"><%= image_tag "hospitalizations-icon-2x.png" %></div></div>
<div class="title">Your Hospitals</div>
<div class="button-wrapper">
<%= button_tag "Add Hospital", class:"add-button", id: 'add-site-modal' %>
<div class="push"></div>
</div><!--button-wrapper-->
</div><!--header-->
<div class="body">
<% if #active_memberships.count > 0 %>
<table>
<thead>
<tr>
<th>Hospital Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% #active_memberships.each do |membership| %>
<tr>
<td><%= membership.site.name %></td>
<td>
<%= link_to patient_remove_membership_path(id: current_user.id, membership_id: membership.id), method: :put, :data => {:confirm => 'Are you sure you want to leave this site?'}, class: "btn" do %>Leave Hospital<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<div class="no-records">
<%= image_tag "icon-no-records", class: "image" %>
<div class="text">You have no sites.</div>
</div>
<% end %>
</div>
</div>
</div>
Here is my provider-select.js code
function providerSearch(input) {
if (input.val()) {
var params = {
"provider_search": {
"query": input.val()
}
}
$.post("/providers/search", params, function(data, status) {
$(".auto-complete-modal-list .content").html(data)
if (data.length == 0) {
var notFound = $('<div>', {
'text': 'No provider found, please invite a provider below',
'class': 'item'
});
$(".auto-complete-modal-list .content").empty().append(notFound)
}
}, "html");
} else {
$(".auto-complete-modal-list .content").empty()
}
}
function providerSelection(event) {
let targetProvider = null;
if ($(event.target).is('button')) {
targetProvider = $(event.target);
}
if (targetProvider != null) {
let providerEmail = targetProvider.closest('.item').data("email")
let providerName = targetProvider.closest('.item').data("name")
$('#provider-selection .item').removeAttr('style').find('button').text("Select");
targetProvider.text("Selected")
targetProvider.closest('.item').css({
"background-color": "rgb(86, 116, 204, .8)"
})
$("#invite-label").fadeOut(function() {
$(this).text(`You are inviting ${providerName} to sign this document`).fadeIn(100);
});
$('#invite_email').val(providerEmail)
}
}
$(document).on('turbolinks:load', function() {
$("#provider-select .input-search").on("keyup", function(e) {
providerSearch($(this));
});
$("#provider-selection").on("click", function(e) {
providerSelection(e);
});
$('#invite_email').blur(function() {
let cantFindText = "Can't find your provider? Invite them via email below"
if (!$.trim(this.value).length) {
if ($('label').text() != cantFindText) {
$("#invite-label").fadeOut(function() {
$(this).text(cantFindText).fadeIn(40);
});
}
}
});
// for add provider access
$('#add-provider-modal').click(function(){
$('#modal').show()
})
});
And then here is my site-select.js code
function siteSearch(input) {
if (input.val()) {
var params = {
"sites_search": {
"query": input.val()
}
}
$.post("/sites/search", params, function(data, status) {
$(".auto-complete-modal-list .content").html(data)
if (data.length == 0) {
var notFound = $('<div>', {
'text': 'No sites found',
'class': 'item'
});
$(".auto-complete-modal-list .content").empty().append(notFound)
}
}, "html");
} else {
$(".auto-complete-modal-list .content").empty()
}
}
function siteSelection(event) {
let targetSite = null;
if ($(event.target).is('button')) {
targetSite = $(event.target);
}
if (targetSite != null) {
let siteId = targetSite.closest('.item').data("id")
$('#site-selection .item').removeAttr('style').find('button').text("Add");
targetSite.text("Added")
targetSite.closest('.item').css({
"background-color": "rgb(86, 116, 204, .8)"
})
}
}
$(document).on('turbolinks:load', function() {
$("#site-select .input-search").on("keyup", function(e) {
siteSearch($(this));
});
$("#site-selection").on("click", function(e) {
siteSelection(e);
});
$('#add-site-modal').click(function(){
$('#modal').show()
})
});

In both of your JavaScript snippets I can see the line
$('#modal').show();
There is:
$('#add-provider-modal').click(function(){
$('#modal').show()
})
and
$('#add-site-modal').click(function(){
$('#modal').show()
})
So when you click your Add Provider Modal or Add Site Model buttons, the same model, with the id "modal", will show.
In the code you have supplied I can't find an element with the ID of "modal" so it must lie within your partials that you have not provided. I would recommend changing the partials to give them different IDs for the different modals and then updating your click handlers to open the correct one at the correct time.

Related

Enable button only if at-least one CheckBox is checked using Stimulus JS

i am using Rails 7 and in one of my forms i have multiple check-boxes. how can make the submit button disabled until at-least one Checkbox is checked?
This may not be the best solution because I am a newbie - but it works :)
Let me know if you solved this problem somehow differently.
#show.html.erb
<%= form_with(url: your_path) do |f| %>
<div data-controller="disable">
<div>
<%= f.check_box :test, { checked: false, data: { action: "change->disable#next" } } %>
</div>
<div>
<%= f.check_box :test2, { checked: false, data: { action: "change->disable#next" } } %>
</div>
<div class="mb-10">
<%= f.submit "Submit!", class:
"w-full
rounded-md
bordder-primary
py-3
px-5
bg-primary
text-base text-white
cursor-pointer
hover:bg-opacity-90
transition", id: 'submit'
%>
</div>
</div>
<% end %>
And:
#app/javascript/controllers/disable_controller.js
import { Controller } from "#hotwired/stimulus"
export default class extends Controller {
connect() {
document.getElementById('submit').disabled = true;
}
next(event) {
var x = (document.getElementById("test").checked);
var y = (document.getElementById("test2").checked);
if (x == true || y == true) {
document.getElementById('submit').disabled = false;
}
}
}

Generating dropdown values based on value of another dropdown in rails

So basically, what I'm trying to do is show the value of status dropdown as [initial, started completed] when bug_type dropdown's value is bug, otherwise status dropdown should show [initial, started, resolved]
<div class="col">
<div class="form-group">
<%= form.select :bug_type, options_for_select([['Bug', 'bug'], ['Feature', 'feature']]) %> <br>
</div>
</div>
<div class="col">
<div class="form-group">
<% if #bug.bug_type == 'bug'%>
<%= form.select :status, options_for_select([['Initial', 'initial'], ['Started', 'started'], ['Completed', 'completed']]) %> <br>
<% else %>
<%= form.select :status, options_for_select([['Initial', 'initial'], ['Started', 'started'], ['Resolved', 'resolved']]) %> <br>
<% end %>
</div>
</div>
So far, I tried doing this but it doesn't work.
Also, I've used enums for bug_type and status. Please help me, if there's another approach to deal with this.
there are two ways for your requirement. One is client side you can change the dropdown value or you can send one server side request and render your required options.
For client side you can do like this:
<div class="col">
<div class="form-group">
<%= form.select :bug_type, options_for_select([["Bug", "bug"], ["Feature", "feature"]]) %>
</div>
</div>
<div class="col">
<div class="form-group">
<% if #bug.bug_type == "bug" %>
<%= form.select :status, options_for_select([["Initial", "initial"], ["Started", "started"], ["Completed", "completed"]]) %>
<% else %>
<%= form.select :status, options_for_select([["Initial", "initial"], ["Started", "started"], ["Resolved", "resolved"]]) %>
<% end %>
</div>
</div>
<script>
// Please change selector accoding to your DOM.
// This is bug type select dropdown
$('#bug_type_select').change(function() {
var selectedValue = $('#bug_type option:selected').val();
var bugOptions = {
'initial': 'Initial',
'started': 'Started',
'completed': 'Completed'
}
var featureOptions = {
'initial': 'Initial',
'started': 'Started',
'resolved': 'Resolved'
}
// Please change selector accoding to your DOM.
// This is status select dropdown
var $mySelect = $('#mySelect');
$mySelect.empty();
if (selectedValue === 'bug') {
$.each(bugOptions, function(key, value) {
var $option = $('<option/>', {
value: key,
text: value
});
$mySelect.append($option);
});
} else {
$.each(featureOptions, function(key, value) {
var $option = $('<option/>', {
value: key,
text: value
});
$mySelect.append($option);
});
}
});
</script>

find method is not waiting for elements that will appear from a json file

Currently, i have this test:
spec/features/cardx/cardx_spec.rb
it 'can edit cardx with the form' do
product = FactoryGirl.create(:product)
store = FactoryGirl.create(:store)
click_link(class: 'link-record-edit')
page.find(class: 'record-form')
fill_in 'field-start-date', with: Date.tomorrow.to_s
page.find(id: 'cardx-edit-form').fill_in 'field-end-date', with: (Date.tomorrow + 7).to_s
page.find(id: 'cardx-edit-form').select(product.name, from: { id: 'field-product' })
page.find(id: 'cardx-edit-form').select(store.name, from: { id: 'field-store' })
page.find(id: 'cardx-edit-form').click_button(t('button.save'))
changed = Cardx.find(#cardx.id)
result = changed.start_date == Date.tomorrow && changed.end_date == (Date.tomorrow + 7) && changed.product.name == product.name && changed.store.name == store.name
expect(result).to eq(true)
end
This test is supposed to check if i can submit a form, but this form is being rendered and added to the DOM via an AJAX request that happens when i click on a link in the page. This render is coming via a JSON file.
When I'm using the browser normally as a user, everything works, but when i run this test (even when i set max_timeout with ridiculous values like 50 seconds), it immediately fails saying that it cannot find 'record-form' element. Isn't find supposed to wait until max_timeout runs out?
What apparently happens in my test is that it isn't trying to load and render the JSON file with the form code. Is there a solution to this problem?
EDIT: Code I have so far
javascript that loads form
$(document).on('click', '.link-record-edit', function(e) {
//diferentiate between multiple searches on page
setRecord(this);
//set selected id
record[record_type].selected_id = $(this).attr('data-id');
//mark selected row
markSelectedRow();
if(record_type !== "default") {
//if in tab, open modal
$(record[record_type].form_placeholder).modal();
}
//get ID for edition
(loadForm || console.error)(e);
e.preventDefault();
});
function loadForm(ev, callback) {
//validate
if (typeof record[record_type].path_edit === 'undefined') {
return console.error("No definition for 'record[record_type].path_edit' on your page's js");
}
target = [];
_event = null;
if(typeof event === 'undefined' || event === null) {
_event = ev;
} else {
_event = event;
}
if(_event.srcElement !== undefined && _event.srcElement.className !== undefined) {
target = _event.srcElement.className.split(" ");
} else if(_event.target !== undefined && _event.target.className !== undefined) {
target = _event.target.className.split(" ");
}
//show form block
$form_placeholder = "";
if(record_type === "default") {
//is nome cases, with tabs, preselect first tab
$('[role="tabpanel"] a:first').tab('show');
//if selected in default list, empty tab placeholders
$('.tab-pane [data-placeholder="true"]').html('');
//add sidebar form
$('.width-switcher').filter(':visible').removeClass('col-sm-12').addClass('col-sm-6');
$('.width-switcher:hidden').fadeIn('fast');
$form_placeholder = record[record_type].form_placeholder;
} else if(target.indexOf("link-record-edit") > -1 || target.indexOf("link-record-new") > -1) {
$form_placeholder = record[record_type].form_placeholder + ' .modal-content';
}
//last case cenario
if(record[record_type].inline_placeholder != null && $($form_placeholder).length == 0) {
$form_placeholder = record[record_type].form_placeholder;
}
loadSpinner($form_placeholder);
//enable/disable tabs
if(record[record_type].selected_id > 0 && record_type === "default") {
$(".nav-tabs").show();
} else if(record_type === "default") {
$(".nav-tabs").hide();
}
// Remove temporary buttons from hooks
$('.temporary').remove();
// pass var to form of view/edit mode
$edit_mode = $('.editor-mode.active').length;
//get form data and place it on placeholder
$.ajax({
url: record[record_type].path_edit.replace(':id', record[record_type].selected_id),
type: "GET",
dataType: "html",
data: { parent_id: record[record_type].parent_id, edit_mode: $edit_mode },
success: function(result) {
//add form
$($form_placeholder).fadeOut(100, function() {
$(this).html(result).fadeIn(400, function() {
//as it fades in, set title and prettify form objects
//change title
setFormTitle();
//refresh scripts for forms
formPluginRegresh();
//new html on page, redistribute record types attributes
distributeRecordAttributes();
removeSpinner();
//callback if anyone waits
if(callback != null) { callback(); }
});
});
},
error: function(jqXHR, textStatus, errorThrown) {
showMessage('error', $.parseJSON(jqXHR.responseText));
}
});
}
function update_inline_combos() {
//case inline, update dropdownlist
if($(record[record_type].form_placeholder).parents('.overflow').length > 0) {
//check existance of drops
drops = $('.input-group[data-record="'+record_type+'"]').find('> select');
//fill in new data
$.ajax({
url: record[record_type].path_list_drop,
type: "GET",
dataType: "html",
success: function(result) {
$.each(drops, function(index, value) {
//element's id
$id = $(value).attr('id');
//add new data with :id, :name
setBoot('#'+$id, result);
});
},
error: function(jqXHR, textStatus, errorThrown) {
showMessage('error', $.parseJSON(jqXHR.responseText));
}
});
}
}
HTML I have
index.html
<div class="col-sm-6 col-xs-12 width-switcher not-visible">
<div class="box-container">
<div class="box-header">
<span class="title" id="edit-cardx-title"> </span>
<!-- Split button -->
<button class="btn btn-xs btn-default pull-right close-width-switcher" type="button">
<i class="fa fa-close"></i>
</button>
</div>
<div class="box-content no-padding">
<div id="placeholder-form-cardx">
<!-- FORM PLACEHOLDER -->
</div>
</div>
</div>
</div>
_form.etml (partial that will be put on placeholder)
<%= render partial: 'partials/form_objects/form_title', format: :erb, locals: { optional: true } %>
<%= simple_form_for(#cardx, remote: true,
url: url_for(action: 'update_or_create', controller: 'cardxes', format: 'json'),
html: { method: 'post', id: 'cardx-edit-form' },
authenticity_token: true) do |f| %>
<%= f.error_notification %>
<%= f.hidden_field :id %>
<div class="form-inputs form-group">
<div class="col-lg-2 col-md-3 col-sm-4 control-label">
<%=t("label.start_date")%>
</div>
<div class="col-lg-10 col-md-9 col-sm-8">
<%= f.input :start_date, as: :string,
input_html: {class: "date-picker day-datepicker", id: "field-start-date"},
label: false, required: true, class: "form-control" %>
</div>
</div>
<div class="form-inputs form-group">
<div class="col-lg-2 col-md-3 col-sm-4 control-label">
<%=t("label.end_date")%>
</div>
<div class="col-lg-10 col-md-9 col-sm-8">
<%= f.input :end_date, as: :string,
input_html: {class: "date-picker day-datepicker", id: "field-end-date"},
label: false, required: true, class: "form-control" %>
</div>
</div>
<!--
<div class="form-inputs form-group">
<div class="col-lg-2 col-md-3 col-sm-4 control-label">
<%#=t("label.end_date")%>
</div>
<div class="col-lg-10 col-md-9 col-sm-8">
<%= f.collection_select :store_id,
Store.to_collection.list, :id, :name,
{ include_blank: t("form.choose") },
{ class: "required" } %>
</div>
</div>
-->
<div class="form-inputs form-group">
<div class="col-lg-2 col-md-3 col-sm-4 control-label">
<%=t("label.store.one")%>
</div>
<div class="col-lg-10 col-md-9 col-sm-8">
<%= f.collection_select :store_id,
Store.to_collection.list, :id, :name,
{ include_blank: t("form.choose") },
{ class: "required selectpicker", id: "field-store" } %>
</div>
</div>
<div class="form-inputs form-group">
<div class="col-lg-2 col-md-3 col-sm-4 control-label">
<%=t("label.product.one")%>
</div>
<div class="col-lg-10 col-md-9 col-sm-8">
<%= f.collection_select :product_id,
Product.to_collection.list, :id, :name,
{ include_blank: t("form.choose"), required_field: true },
{ class: "selectpicker required", id: "field-product" } %>
</div>
</div>
<script>
$(function() {
$('.selectpicker').selectpicker({
liveSearch: true,
liveSearchNormalize: true,
size: 6,
width: '100%',
dropupAuto: true,
actionsBox: false
});
});
</script>
<%= render partial: "partials/form_objects/form_actions",
format: :erb,
locals: { f: f, record: #cardx } %>
<% end %>
Thank you in advance
EDIT:
I'm using this test (for simplicity) to detect whether the form is loaded and i get ' Unable to find css "#cardx-edit-form" '
it 'show edit form when a cardex record is clicked' do
page.find('.link-record-edit', match: :first).click
page.find('#cardx-edit-form', wait: 50)
expect(page).to have_selector('#cardx-edit-form')
end
The fact that your test isn't tagged with js: true metadata, and that no waiting behavior is happening points to the probability that you're using the rack_test driver for this test. The rack_test driver doesn't support JS and hence doesn't do any waiting either (since without JS support there are no asynchronous actions to wait for). You should be able to confirm that from the stacktrace of your error which will probably reference files with 'capybara/rack_test' in their name. See - https://github.com/teamcapybara/capybara#drivers and https://github.com/teamcapybara/capybara#using-capybara-with-rspec

Rails 5 - show block on check box

In my rails view (am new to rails), I want to show a div when a check box is set to true.
How should I do that?
I thought of using
<%= check_box_tag 'advancedtagging', false %> Tag details
combined with:
<% if advancedtagging = '1' %>
<div class="row">
<%= render 'tags/advanced', :object => #annotation %>
</div>
<% end -%>
This is my view:
<div class="row">
<div class="col-md-4">
<div data-spy="affix">
<%= link_to 'Close', annotation_path(#annotation), :class => "btn btn-link" %>
<%= link_to 'List' , annotations_path, :class => "btn btn-link" %>
<%= check_box_tag 'advancedtagging', false %> Tag details
<%= render 'tags/form', :object => #annotation %>
<br>
<div class="panel panel-default" id="annotationResults">
<%= render 'tags/tag_list', :object => #annotation %>
</div>
</div>
</div>
<div class="col-md-8" id="file">
<%= content_tag :iframe, nil, src: pdf_annotation_path(#annotation), width: "100%", height: "875px", frameBorder: "0" %>
</div>
</div>
<% if advancedtagging = '1' %>
<div class="row">
<%= render 'tags/advanced', :object => #annotation %>
</div>
<% end -%>
Put an id to your div and your checkbox
<div id="mydiv" class="row">
<%= render 'tags/advanced', :object => #annotation %>
</div>
Using Jquery
$(function() {
$('#mycheckbox').click(function(event){
event.preventDefault();
$('div#mydiv').toggle();
});
});
Add your CSS file div.hidden { display: none; }
Using pure js
Add in some js file for example application.js or other you want
$(function() {
var mycheckbox = document.getElementById('mycheckbox');
var mydiv = document.getElementById('mydiv');
var toggleDiv = function(){
if(mycheckbox.checked) {
mydiv.style['display'] = 'block';
} else {
mydiv.style['display'] = 'none';
}
}
mycheckbox.onclick = toggleDiv;
toggleDiv();
});

Ruby on rails checkbox (when clicked to div, enable checkbox)

I want checkbox to be clicked when div.tel_show is clicked
<script type="text/javascript">
$("div.tel_show").on("click",function(event) {
var target = $(event.target);
if (target.is('input:checkbox')) return;
var checkbox = $(this).find("input[type='checkbox']");
if( !checkbox.prop("checked") ){
checkbox.prop("checked",true);
} else {
checkbox.prop("checked",false);
}
});
</script>
I think I need to change var checkbox = $(this).find("input[type='checkbox']");
what should I write instead of input[type='checkbox']
<div class="row">
<div id="media-contents" class="col-lg-12">
<% if #media_contents.empty? %>
<h2 id="no-media">Dosya Bulunamadı</h2>
<% else %>
<% #media_contents.each do |media| %>
<div class="col-lg-4 tel_show">
<div class="thumbnail">
<%= image_tag media.file_name.url %>
<div class="caption">
<p>
<%= check_box_tag "media_contents[]", media.id %>
</p>
</div>
</div>
</div>
<% end %>
<% end %>
</div>
</div>
Thanks in advance.
Try this:
$("div").live("click",function(event)
{
var target = $(event.target);
if (target.is('input:checkbox')) return;
var checkbox = $(this).find("input[type='checkbox']");
if( checkbox.attr("checked") == "" ){
checkbox.attr("checked","true");
} else {
checkbox.attr("checked","");
}
});
Give your checkbox a class or an id, then use e.g. $('#checkbox_id') to find it.
Input type selectors should not have '' around the type, e.g. should be "input[type=checkbox]" instead of "input[type='checkbox']".

Resources