rails nested form jquery image preview - javascript

Im using rails with jquery nested form. How to preview image that I want to upload in their own image tag. At the above picture. Everytime I add a new picture, it will be reviewed on the first image tag.
this is my html code:
<%= f.fields_for :product_images do |builder| %>
<div class="row">
<div class="col-xs-6">
<div class="form-group">
<%= f.label 'Upload Image' %>
<%= builder.file_field :image, class: 'form-control', onchange: 'readURL(this);' %>
<small class="pull-right">
<%= builder.link_to_remove "Remove this image" %>
</small>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<%= f.label 'Image: ' %> <br>
<%= image_tag builder.object.image_url(:small), id: 'img_prev' if builder.object.image_url.present? %>
</div>
</div>
</div>
<% end %>
<div class="form-group">
<%= f.link_to_add "Add image", :product_images, class: 'btn btn-success' %>
</div>
<% end %>
and my jquery script:
// image preview
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#img_prev')
.attr('src', e.target.result)
// .width(150);
.height(100);
};
reader.readAsDataURL(input.files[0]);
}
}

jQuery:
// Set image preview on selection
function readURL(input, div_id) {
div_id = "#" + div_id;
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$(div_id).attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
Rails:
<%= f.fields_for :pictures do |pic| %>
<%= pic.file_field :picture, :onChange => "readURL(this, #{pic.index})" %>
<img id="<%= pic.index %>" src="<%= image_url 'image-placeholder.png' %>">
<% end %>

Related

Assigning value to input field on nested:fieldAdded

I have an upload file field. On change of this field, I am triggering add nested field and on 'nested:fieldAdded' I am trying to assign the value to the input file field given in the new generated nested form by using the following jquery:
$(document).off('change').on('change', '#add_gallery_image, #add_place_image',function () {
if (typeof (FileReader) != "undefined") {
var reader = new FileReader();
var file = $(this)[0].files[0];
file_selector_id = $(this)[0].id;
var reader = new FileReader();
var association = ''
if (file_selector_id.includes("add_gallery_image")) {
association = 'tribute_galleries'
limit_count = GALLERY_LIMIT_JS
} else {
association = 'tribute_places'
limit_count = PLACES_LIMIT_JS
}
reader.onload = function (e) {
file_src = e.target.result;
$(".add_nested_fields[data-association='" + association + "']").click();
}
reader.readAsDataURL($(this)[0].files[0]);
// reader.readAsDataURL($(this)[0].files[0]);
}
})
$(document).on('nested:fieldAdded', function(event){
if(file_selector_id!="") {
var field = event.field;
var dateField = field.find('.add_image');
dateField[0].files = $('#' + file_selector_id)[0].files;
}
})
<div class="upload-btn position-relative">
<%= file_field_tag :image, :name => "tribute_gallery[image]", :class => "add_gallery_image image_uploader1", :id => "add_gallery_image","data-target": "#tribute_tribute_galleries_attributes_0_image-error", accept: 'image/png,image/jpeg,image/jpg', "data-id": gallery_count.present? ? gallery_count + 1 : 1, disabled: gallery_count.present? && gallery_count >= GALLERY_LIMIT %>
<a href="javascript:void(0);" class="text-transform-none f-semi theme-btn w-100 text-center theme-large-btn">
<span class="fa fa-upload mr-2 "></span> <%= I18n.t(:'tribute_setup.placeholders.upload_more') %>
</a>
</div>
<div class="row">
<div class="col-md-12 form-group">
<div class="box-sec">
<% positionCount = 0 %>
<div class="row tribute_galleries_list" >
<%= f.fields_for :tribute_galleries, wrapper: false, html: { autocomplete: "off"} do |gallery_form| %>
<% if (gallery_form.present? && gallery_form.object.id.present? && gallery_form.object.image.present?) || (gallery_form.present? && !gallery_form.object.id.present? && !gallery_form.object.image.present?) %>
<% positionCount = positionCount + 1 %>
<%#= gallery_form.object.id.present? ? 'first_gallery_div' : '' %>
<div class="col-md-3 col-sm-6 fields first_gallery_div" data-count="<%= gallery_form.object.position.present? ? gallery_form.object.position : (positionCount.present? ? positionCount : '') %>" data-id="<%= gallery_form.object.id.present? ? gallery_form.object.id : '' %>" >
<%= gallery_form.hidden_field :position, :value => gallery_form.object.position.present? ? gallery_form.object.position : (positionCount.present? ? positionCount : ''), :class => 'gallery_position' %>
<div class="photo-img-sec position-relative ">
<div class="photo-img mb-2">
<%= gallery_form.file_field :image, :class => "add_image" ,:style=>"display:none" %>
<img src="<%= gallery_form.object.image.present? ? gallery_form.object.image : "/assets/gallery-dummy.png" %>" width="247" height="162" alt="personlized memorial page online" class="view_image_tag">
<% if gallery_form.object.user_id.present? && gallery_form.object.user_id != current_user.id %>
<% if gallery_form.object.user.present? && gallery_form.object.user.user_detail.present? %>
<div class="photo-added">
<p class="small"><%= I18n.t(:'tribute_setup.placeholders.added_by') %>
<%= gallery_form.object.user.user_detail.first_name.present? ? gallery_form.object.user.user_detail.first_name : '' %> <%= gallery_form.object.user.user_detail.last_name.present? ? gallery_form.object.user.user_detail.last_name : '' %>
</p>
</div>
<% end %>
<% end %>
</div>
<div class="form-group">
<%= gallery_form.text_field :map_link, :placeholder => I18n.t(:'tribute_setup.placeholders.google_link'), :class => "theme-input form-control map_link_class" %>
</div>
<div class="form-group">
<%= gallery_form.text_field :title, :placeholder => I18n.t(:'tribute_setup.placeholders.title')+I18n.t(:'tribute_setup.placeholders.optional'), :class => "theme-input form-control name_class title_class" %>
</div>
<div class="form-group">
<%= gallery_form.text_field :description, :placeholder => I18n.t(:'tribute_setup.placeholders.description')+I18n.t(:'tribute_setup.placeholders.optional'), :class => "theme-input form-control description_class" %>
</div>
<%= gallery_form.link_to_remove "<i class='fa fa-times' aria-hidden='true'></i>".html_safe, class:"remove-btn remove_gallery_image" %>
</div>
</div>
<%= gallery_form.hidden_field :user_id, :value => gallery_form.object.user_id.present? ? gallery_form.object.user_id : current_user.id %>
<% end %>
<% end %>
</div>
<p class='add_gallery_count' data-id="<%= gallery_count %>"><%= f.link_to_add "Add", :tribute_galleries, :data => {:target => ".tribute_galleries_list"}, :style => "display:none", :class=>"add_gallery_link" %></p>
</div>
</div>
</div>
Also, the above code is working fine for chrome but in firefox, it is assigning the last uploaded file value to all the newly generated nested forms along with the current generated nested form.

Google map api javascript for address auto filling is not working (InvalidValueError: not an instance of HTMLInputElement)

I am using google map api for address auto fill in my ruby on rails app.In two forms I have used the address auto fill .But only in one form its working fine.
Working code
new.html.erb in location
<%= form_for #location,url: locations_path,html: {method: 'post'} do |f| %>
<div class="form_format">
<div class="form-group">
<div class="star">*</div>
<%= f.label :address %>
<%= f.text_field :address, class: "form-control"%>
</div>
<div class="form-group">
<div class="star">*</div>
<%= f.label :locality %>
<%= f.text_field :locality, class: "form-control",
readonly: true %>
</div>
<div class="form-group">
<%= f.label :city %>
<%= f.text_field :city, class: "form-control",readonly: true %>
</div>
<div class="form-group">
<div></div>
<%= f.label :state %>
<%= f.text_field :state, class: "form-control",
readonly: true%>
</div>
<div class="form-group">
<div class="star">*</div>
<%= f.label :country %>
<%= f.text_field :country, class: "form-control",
readonly: true %>
</div>
<div class="form-group"><center>
<%= f.submit 'Add Details', class: "btn btn-primary" %></center>
</div>
</div>
working js
var placeSearch, location_address;
var address=[];
var componentForm = {
formatted_address: 'location_address',
sublocality_level_1: 'location_locality',
locality: 'location_city',
administrative_area_level_1: 'location_state',
country: 'location_country'
};
function initAutocomplete() {
location_address = new google.maps.places.Autocomplete(
(document.getElementById('location_address')),
{types: ['geocode']});
location_address.addListener('place_changed', fillInAddress);
}
function fillInAddress() {
address=[];
var place = location_address.getPlace();
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var val = place.address_components[i]['long_name'];
document.getElementById(componentForm[addressType]).value = val;
}
}
}
function geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
var circle = new google.maps.Circle({
center: geolocation,
radius: position.coords.accuracy
});
location_address.setBounds(circle.getBounds());
});
}
}
Not Working code
edit.html.erb in doctorinfo
<%= form_for #doctorinfo,url: doctorinfo_path(#doctorinfo),html: {method: 'patch',multipart: true} do |f| %>
<div class="form_format">
<div class="form-group">
<div class="star">*</div>
<%= f.label :name %>
<%= f.text_field :name, class: "form-control"%>
</div>
<div class="form-group">
<div class="star">*</div>
<%= f.label :address %>
<%= f.text_field :address, class: "form-control"%>
</div>
<div class="form-group">
<div class="star">*</div>
<%= f.label :locality %>
<%= f.text_field :locality, class: "form-control",
readonly: true %>
</div>
<div class="form-group">
<%= f.label :city %>
<%= f.text_field :city, class: "form-control",readonly: true %>
</div>
<div class="form-group">
<div></div>
<%= f.label :state %>
<%= f.text_field :state, class: "form-control",
readonly: true%>
</div>
<div class="form-group">
<div class="star">*</div>
<%= f.label :country %>
<%= f.text_field :country, class: "form-control",
readonly: true %>
</div>
<div class="form-group">
<div class="star">*</div>
<%= f.label :specialization %>
<%= f.text_field :specialization, class: "form-control"%>
</div>
<div class="form-group">
<div class="star">*</div>
<%= f.label :time_per_slot %>
<%= f.text_field :time_per_slot, class: "form-control"%>
</div>
<div class="form-group">
<div class="star">*</div>
<%= f.label :fees %>
<%= f.text_field :fees, class: "form-control"%>
</div>
<p>
<label>Profile Picture:</label>
<% if #doctorinfo.profile?%>
<%= image_tag (#doctorinfo.profile_url), class: 'profile' %>
<% end%>
<%= f.file_field :profile %>
<%= f.hidden_field :profile_cache %>
</p>
<p>
<label>
<%= f.check_box :remove_profile %>
Remove Picture
</label>
</p>
<div class="form-group"><center>
<%= f.submit 'Update Details', class: "btn btn-primary" , name: "saving"%></center>
</div>
</div>
<% end %>
Not working js
var placeSearch, doctorinfo_address;
var address=[];
var componentForm = {
formatted_address: 'doctorinfo_address',
sublocality_level_1: 'doctorinfo_locality',
locality: 'doctorinfo_city',
administrative_area_level_1: 'doctorinfo_state',
country: 'doctorinfo_country'
};
function initAutocomplete() {
doctorinfo_address = new google.maps.places.Autocomplete(
(document.getElementById('doctorinfo_address')),
{types: ['geocode']});
doctorinfo_address.addListener('place_changed', fillInAddress);
}
function fillInAddress() {
address=[];
var place = doctorinfo_address.getPlace();
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var val = place.address_components[i]['long_name'];
document.getElementById(componentForm[addressType]).value = val;
}
}
}
function geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
var circle = new google.maps.Circle({
center: geolocation,
radius: position.coords.accuracy
});
doctorinfo_address.setBounds(circle.getBounds());
});
}
}
And when I check the console in the browser the error is
InvalidValueError: not an instance of HTMLInputElement
What am I doing wrong?Thanks in advance.
I figure out the problem .I was placing the js files in the assets/javascripts folder.So it was causing ambiguity .The problem resolved by adding the js files in its respective view.Hope it saves someone's time.

How to load rails form partials with jquery and submit as one form

In an attempt to make my rails html more readable I extracted several parts of it into partials. I then use jquery to render the partials. The issue is that now the form has come all "unhooked" so to speak, meaning when I attempt to submit the form it acts as though the partials don't exist. I suspect I am not understanding quite how forms work, because it seems like in other answers related to this the form builder isn't even addressed.
This SO question seems related to what I want to do but I think I'm too inexperienced to grasp it properly
The code I have thus far goes as follows:
/assets/javascripts/work_order.js
$(document).ready(function(){
$('.best_in_place').best_in_place();
$('#work_order_dueDate').datepicker();
$.datepicker.setDefaults({ dateFormat: 'dd-mm-yy'});
var selection_made = false
$('#work_order_project_type_id').change(function(){
if (!selection_made){
selection_made = true
var selection = $(this).find('option:selected').text();
if (selection == "Variable Data Mailing"){
$.get('/presort_informations/new');
$.get('/printing_instructions/new');
}
else if (selection == "Mailing"){
$.get('/presort_informations/new');
}
else if (selection == "Print Job"){
$.get('/printing_instructions/new');
}
}
});
});
and then
/views/work_orders/_form.html.erb
<%= form_for(#workorder) do |f| %>
<% if #workorder.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#workorder.errors.count, "error") %> prohibited this workorder from being saved:</h2>
<ul>
<% #workorder.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<fieldset class="general-info">
<legend>General</legend>
<div class="col-md-12">
<div class="col-md-3">
<div class="form-group">
<%= f.label :Job_Title, class: "control-label" %>
<%= f.text_field :title, class:"form-control" %>
</div>
<div class="form-group">
<%= f.label :Project_Type, class: "control-label" %>
<%= f.collection_select(:project_type_id, ProjectType.all, :id, :name, {:prompt => true}, {:class => "form-control"}) %>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<%= f.label :Rep, class: "control-label" %>
<%= f.text_field :rep, class:"form-control" %>
</div>
<div class="form-group">
<%= f.label :Labels, class: "control-label" %>
<%= f.collection_select(:labels_id, Labels.all, :id, :name, {:prompt => true}, {:class => "form-control"}) %>
</div>
</div>
<div class="col-md-3">
<div class= "form-group">
<%= f.label :Due_Date, class: "control-label" %>
<%= f.text_field :dueDate, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :Project_Description, class: "control-label" %>
<%= f.text_area :projectDescription, class: "form-control" %>
</div>
</div>
</div>
</fieldset>
<fieldset class="presort-information">
</fieldset>
<div class="col-md-6 printing">
</div>
<fieldset class="production-details">
<legend>Production</legend>
<%= f.fields_for :production_details, ProductionDetails.new do |ff| %>
<%end%>
</fieldset>
<%= f.hidden_field(:number, :value => #workorder.number) %>
<%= f.hidden_field(:client_id, :value => #workorder.client_id) %>
<%= f.submit(class: "btn btn-default") %>
<% end %>
and as an example of one of the partials:
/app/views/presort_informations/new.js.erb
$('.presort-information').append( '<%= j render("presort_informations/form") %>' );
/app/views/presort_informations/_form.html.erb
<legend>Mailing</legend>
<%= fields_for :presort_information, PresortInformation.new do |ff| %>
.
.
.
<% end %>
I'm not really sure how to tie this all together so that I can load the partials based on the select box, but then submit them all as one form.
Edit:
I found this SO question which deals with the same issue, but I suspect that because I am rendering the partial after the page has been loaded I no longer have access to the form builder variable.
$('.presort-information').append( '<%= j render("presort_informations/form", f: f) %>' );
gives an undefined variable error when it's called. I'm still not sure how to bridge this gap between jquery and rails.
Turns out it was a relatively (if new conceptually to me) easy fix
First, load each DOM partial in along with hidden sections.
<%= form_for(#workorder) do |f| %>
<% if #workorder.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#workorder.errors.count, "error") %> prohibited this workorder from being saved:</h2>
<ul>
<% #workorder.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<fieldset id="general-info-partial">
<%=render("genInfo", f: f)%>
</fieldset>
<fieldset id="presort-information-partial">
<%=render("presort_informations/form", f: f)%>
</fieldset>
<div class="col-md-6">
<fieldset id="printing-information-partial">
<%=render("printing_instructions/form", f: f)%>
</fieldset>
</div>
<fieldset id="production-details-partial">
<%=render("production_details/form", f: f) %>
</fieldset>
<%= f.hidden_field(:number, :value => #workorder.number) %>
<%= f.hidden_field(:client_id, :value => #workorder.client_id) %>
<input type="submit" value="Submit" class="btn btn-default">
<% end %>
<div id="hidden-general-info" class="hidden"></div>
<div id="hidden-presort-information" class="hidden"></div>
<div id="hidden-printing-information" class="hidden"></div>
Then the Javascript to move things in and out of the form:
$(document).ready(function(){
$('.best_in_place').best_in_place();
$('#work_order_dueDate').datepicker();
$.datepicker.setDefaults({ dateFormat: 'dd-mm-yy'});
var presortFields = $('#presort-information-partial');
var printingFields = $('#printing-information-partial');
var presortHidden = $('#hidden-presort-information');
var printingHidden = $('#hidden-printing-information');
presortHidden.html(presortFields.html());
presortFields.html('');
printingHidden.html(printingFields.html());
printingFields.html('');
$('#work_order_project_type_id').change(function(){
var selection = $(this).find('option:selected').text();
if (selection == "Variable Data Mailing"){
if (printingFields.html() == '' && presortFields.html() == ''){
printingFields.html(printingHidden.html()).hide().slideDown();
presortFields.html(presortHidden.html()).hide().slideDown();
}
else if(printingFields.html() == '' && !(presortFields.html() == '')){
printingFields.html(printingHidden.html()).hide().slideDown();
}
else if(!(printingFields.html() == '') && presortFields.html() == ''){
presortFields.html(presortHidden.html()).hide().slideDown();
}
}
else if (selection == "Mailing"){
if(!(printingFields.html() == '')){
printingFields.slideUp();
printingFields.html('');
presortFields.html(presortHidden.html()).hide().slideDown();
}else{
presortFields.html(presortHidden.html()).hide().slideDown();
}
}
else if (selection == "Print Job"){
printingFields.html(printingHidden.html()).hide().slideDown();
presortFields.slideUp();
presortFields.html('');
}
});
Basically, the idea was to load everything in as if I was going to use it all, and then just move the partials into a hidden section of the DOM, and then use JS to put them back in when the user makes a selection

Rails combined two form fields into one

How do I combined the day and time into a "start_time" variable (and "end_time") before submitting? JS?
<%= form_for #task do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="time_selectors">
<%= f.label :start_time %>
<%= f.text_field :start_time, :class => 'datepicker' %>
<select class="form-control time_dropdown" id="start_hour">
<option>Select Date</option>
</select>
<div class="clear_both"></div>
<%= f.label :end_time %>
<%= f.text_field :end_time, :class => 'datepicker' %>
<select class="form-control time_dropdown" id="end_hour">
<option>Select Date</option>
</select>
</div>
<div class="clear_both"></div>
</div>
<div class="clear_both"></div>
<%= f.submit "Create Task", class: "btn btn-large btn-primary" %>
</div>
<% end %>
I have them combined in my Task model, and I'd prefer to leave them combined if I can.
My JS right now doesn't work. What am I missing?
$('#new-task').submit ()->
valuesToSubmit = $(this).serialize
console.log('test')
console.log(valuesToSubmit)
return false
$('button').click ()->
console.log ('test2')
What about something like this?
$('form').on 'submit', (event) ->
event.preventDefault()
start_time = ''
start_time += $(#).find('input[name=start_day]').val()
start_time += '_'
start_time += $(#).find('input[name=start_hour]').val()
$('<input/>', {type: 'hidden', name: 'start_time', value: start_time}).appendTo($(#))
#submit()
(*The CoffeeScript version hasn't been tested - use the working Fiddle as your guide.)
Fiddle

how to include the javascript into dropdown list in ruby on rails?

I have a javascript file for the cascading dropdown boxes loading from different models. But I dont know how to include into the dropdown list.
Form:
<% content_for :javascript do %>
var master_surveys = <%=
Condition::MasterSurvey.all.map {|ms| {id: ms.Master_Survey_Code, to_s: ms[:Master_Survey_Name]}}.to_json.html_safe
%>
var elements = <%= elements = Hash.new { |hash, code| hash[code] = [] }
Condition::Element.all.each {|e| elements[e.Master_Survey_Code] << {id: e.Element_Code, to_s: e.Element} }.to_json.html_safe
%>
var sub_elements = <%= sub_elements = Hash.new { |hash, code| hash[code] = [] }
Condition::SubElement.all.each {|s| sub_elements[s.Element_Code] << {id: s.Sub_Element_Code, to_s: s.Sub_Element} }.to_json.html_safe
%>
var materials = <%=
materials = Hash.new { |hash, code| hash[code] = [] }
Condition::RenewSchedule.all.each {|rs| materials[rs.Sub_Element_Code] << {id: rs.Material_Code, to_s: rs.Material} }.to_json.html_safe
%>
$(document).ready(function(){
$('select#enr_rds_surv_rdsap_xref_master_survey').chainedTo('select#enr_rds_surv_rdsap_xref_Element_Code');
});
<% end %>
<%= form_for(#enr_rds_surv_rdsap_xref) do |f| %>
<% if #enr_rds_surv_rdsap_xref.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#enr_rds_surv_rdsap_xref.errors.count, "error") %>:</h2>
<ul>
<% #enr_rds_surv_rdsap_xref.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :Master_Survey %><br/>
<%= f.select :master_survey, Condition::MasterSurvey.all.map{|e| [e.Master_Survey_Code]}, { :prompt => 'Please Select' } %>
</div>
<div class="field">
<%= f.label :Element_Code %><br/>
<%= f.select :Element_Code, Condition::Element.all.map{|e| [e.Element, e.Element_Code]}, { :prompt => 'Please Select' } %>
</div>
<div class="field">
<%= f.label :Sub_Element_Code %><br/>
<%= f.select :Sub_Element_Code, Condition::SubElement.all.map{|e| [e.Sub_Element, e.Sub_Element_Code]}, { :prompt => 'Please Select' } %>
</div>
<div class="field">
<%= f.label :Material_Code %><br/>
<%= f.select :Material_Code, Condition::RenewSchedule.all.map{|e| [e.Material]}, { :prompt => 'Please Select' } %>
</div>
<div class="actions">
<%= f.submit 'Save'%>
</div>
<% end %>
So, The above javascript file collect the data from the parent. In the form, I created a dropdown list statically loaded the data from the database. I want to include the javascript to loaded automatically into the dropdown list dynamically.
Thanks in advance!!!!
I usually do it by Ajax and partials(or page, up to you.), not nice but might be help?
Bind change even on your parent selects. like
$("#parent_select").change(function(){
$.ajax({
url: '/parents/'+$(this).val()+'/childs/',
complete: function(data){
$('#children_select').html(data);
}
})
});
And in your child controller render a partial(or page) with only contents of options of selected children. like:
<%children.each do |child|%>
<option value='<%=child.id%>'><%=child.name%></option>
<%end%>

Categories