Rails: Submit html table content in form to controller - javascript

I have some trouble with an rails formular.
I have a form to create "projects".
Project form
<%= bootstrap_form_for(#project) do |f| %>
...
<div class="container-fluid">
<%= f.static_control label:"Vordefinierte Aufgaben" do %>
<div class="actions form-group nopadding">
<div class="center-block">
<%=link_to "", data: {toggle:"modal", target:".newTask-modal"} , class: "btn btn-success center-block btn-sidebar-ok", id: "singlebutton" do%>
<i> <span class="glyphicon glyphicon-plus pull-left btn-sidebar-icon"></span>Neue Aufgabe hinzufügen </i>
<% end %>
</div>
</div>
<div class="task-table">
<%=render 'tasks/table'%>
</div>
<% end %>
</div>
...
<!-- task Modal to create a new task -->
<%=render 'tasks/newTaskModal' %>
<% end %>
<!-- Button -->
<div class="actions form-group">
<div class="center-block">
<%= button_tag( type: 'submit', class: "btn btn-success center-block btn-sidebar-ok", id: "singlebutton") do%>
<i> <span class="glyphicon glyphicon-ok pull-left"></span>Projekt anlegen </i>
<% end %>
</div>
</div>
Within this form a have a table which shows created tasks and a button to open an bootstrap modal. This modal contains a new form to create a task.
Task Form within modal
<%= bootstrap_form_tag() do |f| %>
<div class="col-sm-8">
<%= f.text_field :task_title, label: "Titel", placeholder: "Betreff", icon: "pencil",wrapper: { class: 'icon-addon addon-md'} %>
</div>
<div class="col-sm-4">
<%= f.number_field :task_in_min, label: "Arbeitszeit in Min", placeholder: "Bsp.: 25", icon: "time", wrapper: { class: 'icon-addon addon-md'}%>
</div>
<div class="col-sm-12">
<%= f.text_area :task_description, label: "Beschreibung*", placeholder: "Aufgabenbeschreibung", icon: "pencil", rows: 10, wrapper: { class: 'icon-addon addon-md'}%>
</div>
<%= button_tag( type: 'button', id:"taskSubmit", class: "btn btn-success center-block btn-sidebar-ok") do %>
<i > <span class="glyphicon glyphicon-ok pull-left btn-sidebar-icon"></span> Speichern </i>
<% end %>
<% end %>
If I click to "taskSubmit" a javascript put this task (title, description, min) into the table within the project form. JS create a new table row with the task content.
Javascript
//take data from task form and at a new task element to the task table in project form
$(function TaskSubmitFunction(){
$('#taskSubmit').click(function(){
var task_title = $('#task_title').val();
var task_description = $('#task_description').val();
var task_in_min = $('#task_in_min').val();
//Remove spaces from title
var id = task_title.replace(/ /g,'');
$('#taskTable tr:last').after('<tr id="task_'+id+'"> <td>'+task_title+'</td> <td>'+task_description+'</td><td>'+task_in_min+'</td><td> <span class="pull-right"><span data-toggle="tooltip" data-placement="right" data-original-title="Löschen"><button class="btn btn-sm btn-danger btn-colored delete-position" id="'+id+'"name="button" type="button" task="'+task_title+'"><i><span class="glyphicon glyphicon-remove"/></i></button></span></span></td></tr>');
$('#taskTable').after('<input type="hidden" id="1" name="1" value="'+task_title+'" />');
$('#task_title').val('');
$('#task_description').val('');
$('#task_in_min').val('');
//initialize task delete
$(function TaskDeleteFunction(){
$('#'+id).click(function(){
var task_title = $(this).attr('task');
if (confirm("Soll die Aufgabe wirklich gelöscht werden?")) {
$('#'+id).remove();
}
return false;
});
});
});
});
What I want to do now is to submit these table elements to the project controller to create the project and all necessary tasks activeRecords. Is this possible?
How can I do this? Maybe create a hidden field for every table element which will be submit to the project form? But every table element consists of three values... how can I do this?
Do you have any idea?
best regards

Why not just use three hidden fields (one for each value)? Straightforward and they will be easy to access in the params hash.

Related

How do I autofocus to text input field in modal? Rails 7, Bootstrap 5

I have a search button in the top navbar. When the user clicks, a modal opens with a text input field. I want the keyboard focus to be automatically inside the text input field when the modal opens.
Here is the search modal code:
<div class="modal" id="searchModal" tabindex="1" aria-labelledby="searchModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="searchModalLabel">Search parks</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<%= search_form_for #q, url: :parks do |f| %>
<%= f.hidden_field :has_entrance_fee_eq %>
<%= f.hidden_field :region_eq %>
<div class="form-group">
<%= f.text_field :name_en_or_name_he_or_description_en_or_description_he_cont,
autofocus: true,
placeholder: "Search for a park (English or Hebrew)",
class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit 'Search parks', name: "", class: "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
</div>
</div>
I've already tried simply adding autofocus: true in the rails form, but it doesn't work:
<div class="form-group">
<%= f.text_field :name_en_or_name_he_or_description_en_or_description_he_cont,
autofocus: true,
placeholder: "Search for a park (English or Hebrew)",
class: "form-control" %>
</div>
The Bootstrap documentation says:
Due to how HTML5 defines its semantics, the autofocus HTML attribute has no effect in Bootstrap modals. To achieve the same effect, use some custom JavaScript:
var myModal = document.getElementById('myModal')
var myInput = document.getElementById('myInput')
myModal.addEventListener('shown.bs.modal', function () {
myInput.focus()
})
But I'm not really familiar with Javascript so not sure where/how to use this code, if this is indeed the right direction... In general I'm new to coding so any help would be much appreciated, the more specific the better!
Update:
I tried adding the following code to the search modal but it didn't work:
<script>
// Get the modal and the input element
var myModal = document.getElementById('searchModal')
var myInput = document.querySelector('input')
// Add a listener for the shown.bs.modal event on the modal
myModal.addEventListener('shown.bs.modal', function() {
// When the modal is shown, focus the input element
myInput.focus()
})
</script>

Searching by hitting enter

Right now i have a search field and right next to it a submit search button.
But want to delete the button so that the user can just hit enter. What do i need to change ?
<%= form_tag search_path, method: :get do %>
<div class="row">
<div class="col-md-5">
<%= text_field_tag :search, params[:search], placeholder: "z.B. New York", class: "suchfeld", id: "autolocation" %>
</div>
<div class="row">
<div class="col-md-2">
<%= submit_tag "Search", class: "btn btn-normal btn-block" %>
</div>
</div>
</div>
<br/><br/>
<% end %>
Can be done using jquery or javascript
1 -> Provide a unique id to form and input field which will be submitted on hit enter
<%= form_tag(search_path, method: :get, id: 'search_form') do %>
<div class="row">
<div class="col-md-5">
<%= text_field_tag :search, params[:search], placeholder: "z.B. New York", class: "suchfeld", id: "autolocation" %>
</div>
</div>
<br/><br/>
<% end %>
2 -> Using jQuery check if enter button is pressed, then submit this form
<script>
$(document).ready(function() {
$('#autolocation').keydown(function(event) {
// enter has keyCode = 13
if (event.keyCode == 13) {
$('#search_form')submit(); // submit the form
return false;
}
});
});
</script>
You can simple hide the button using css. {display: none}. But don't delete the button. (If you are using boostrap try adding d-none class to the submit button.) This will submit your form with enter key.

uncaught TypeError: ajaxForm is not a function in rails version 5?

I am trying to submit the modal form using ajaxForm and display the response in modal itself. But, I am getting uncaught type error (...).ajaxForm is not a function.
Basically I want to create a modal form for lesson creation form and have to submit , my app consists of both API controller and front end controller.
api!
param_group :lesson
description 'creates a lesson'
example "
{
'id': 12,
'title': 'MUDRAS',
'active_video_id': 3,
'description': 'Description of the lesson',
'points': null,
'is_public': '1',
'videos': [
{
'video': {
'id': 1,
'video': {
'url': '/uploads/video/video/1/250-authentication-from-scratch.mp4'
},
'title': null,
'storage_type': 'Lesson',
'storage_id': 12
}
},
]
}"
def create
#lesson = Lesson.new(lesson_params)
#lesson.creator = current_user
if #lesson.save
render json: {
success: true,
message: "Lesson created Successfully"
}
else
render json: { success: false, message: "Could not Create : #{#lesson.errors.full_messages.join(', ')}" }
end
end
def new
#lesson = Lesson.new
end
The above code is my API controller.The below codes are my Front end controller and lesson related forms.
def create
#lesson = Lesson.new(lesson_params)
if #lesson.save
render json: {
success: true,
message: "Lesson Created Successfully"
}
else
render json: {
success: false,
message: "Lesson Creation Failed"
}
end
end
I need to display the "New Lesson" button in Lesson Index page.
lessons/index.html.erb
<% unless current_user.student? %>
<div class="container-fluid">
<div class="col-md-3 col-sm-3 text-left">
<div id="newLesson" class="lesson-category btn-danger" lesson_url="<%= new_lesson_path %>">
<i class="fa fa-plus"></i> ADD LESSON
</div>
</div>
</div>
<div class="hidden" id="newLessonForm">
<% #lesson = Lesson.new ; #lesson.videos = [Video.new] %>
<%= render "lessons/form" %>
</div>
<% end %>
<%= render "shared/primary_modal" %>
<div class="container-fluid">
<div class="col-md-3 col-sm-3 text-left">
<h2 class="main-tab tab-active">LESSONS</h2>
</div>
<div class="col-md-9">
<div class="col-md-12 text-right">
<h2 class="main-tab tab-inactive"><a id="responsesLink" class="blacko" href="#"><%= "MY" if current_user.student? %> RESPONSES</a></h2>
</div>
</div>
<div class="col-md-12"><hr/></div>
<!-- Lessons of this course Go here -->
<div class="col-md-3">
<% #lessons.each do |lesson| %>
<div id="lesson_<%= lesson.id %>" class="pill video-view lesson-load" data-lesson-id="<%= lesson.id %>" data-src="<%= lesson.active_video_url %>"><%= lesson.title %></div>
<% end %>
<!-- <div class="pill pill-inactive">Something</div> -->
</div>
<!-- Lesson Content goes here -->
<div class="col-md-9">
<div class="row">
<div class="col-md-12">
<%= render "shared/video_player" %>
</div>
</div>
<div id="lessonContent">
</div>
</div>
</div>
<script>
$("#newLesson").click(function(){
var lesson_path = $(this).attr("lesson_url");
$.get(
lesson_path,
function(content){
$("#primaryModalContent").html(content);
$("#format").val('js');
$("#primaryModal").modal("show");
}
);
});
</script>
My lesson creation form is given as a partial.
<div class="col-md-12">
<%= simple_form_for #lesson, html: {class: "newLessonform"} do |f| %>
<%= f.input :title, label: "Lesson Title", required: false %>
<%= f.input :description, required: false, as: :text %>
<%= f.input :points, required: false, as: :integer %>
<%= f.input :is_public, label: 'Check to Make this lesson public', as: :boolean %>
<div class="col-md-12">
<% unless #lesson.new_record? or #lesson.active_video_url.blank? %>
<h4> Currently Linked Video </h4>
<video src="<%= #lesson.active_video_url %>" style="width: 400px;"></video>
<% end %>
<hr/>
</div>
<h4>Add <%= #lesson.videos.blank? ? "a" : "another" %> Video</h4>
<% #lesson.videos = [Video.new(title: "")] if #lesson.videos.blank? %>
<%= f.simple_fields_for :videos do |g| %>
<%= g.input :title, label: "Video title" %>
<%= g.input :video, as: :file, lebel: "Select Video" %>
<% end %>
<center><%= f.submit class: "lesson-category btn-danger" %></center>
<% end %>
</div>
<script type="text/javascript">
$(".newLessonform").ajaxForm(function(data) {
$("#primaryModalContent").html(data.message);
});
</script>
In the above script , I have given ajaxForm. The modal form for this is given below.
<div class="modal fade" id="primaryModal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" , data-dismiss="modal">×</button>
<h1 class="modal-title" id="modalTitle"></h1>
</div>
<div class="row modal-body" id="primaryModalContent">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
The error in chrome console , was uncaught error:(...)$.ajaxForm is not a function.
I am stuck in this for about a week. Could any one give me a solution.
Thanks in advance.
The best way to use an AJAX form in rails is to use rails_ujs.
First you have to tell rails_ujs that you want an AJAX action on your form :
<%= simple_form_for #lesson, html: {class: "newLessonform"}, remote: true do |f| %>
Then add a new file in your views, this view will be rendered after a successfull create action initiated by an AJAX action : views/lessons/create.js.erb
Inside you can put you js code, this code will be executed on the same page as the AJAX form. This is just a view and you can use variables from the controller.
$("#primaryModalContent").html("<%= #message %>")
Finally, you need to update your controller to handle AJAX action :
def create
#lesson = Lesson.new(lesson_params)
if #lesson.save
#success = true
#message = "Lesson Created Successfully"
else
#success = false,
#message = "Lesson Creation Failed"
end
respond_to do |format|
format.js
end
end
Here you can find some documentation about Rails UJS :
http://guides.rubyonrails.org/working_with_javascript_in_rails.html#remote-elements
https://blog.codeship.com/unobtrusive-javascript-via-ajax-rails/

Gif for Load more not displaying with Ajax and jQuery in my Rails app

I have followed this tutorial: Rails - load more results using jquery ajax but not sure where I am making a mistake or if something in the tutorial is wrong.
EDIT:
When i click "Load More": the ajax loader gif does not appear and the next 3 categories do not appear below the current 3 categories (with articles belonging to the category).
When i click "Load More": the ajax loader gif does appear and the next 3 categories do get rendered. However, they are overlaying over the current categories instead of being added below the current categories.
categories/index.html.erb
<div class = "container">
<%= render #categories %>
</div>
<div class="load-more-container">
<%= image_tag "ajax-loader.gif", style: "display:none;", class: "loading-gif" %>
<%= link_to "Load More", categories_path, class: "load-more" %>
</div>
<script>
$('.carousel').carousel({
interval: false
});
</script>
_category.html.erb
<div class="category" data-id="<%= category.id %>">
<h3 class= "padding-bottom-20"><%= link_to category.name, category_path(category) %></h3>
<% div_id = "carousel_slider_#{category.id}" -%>
<div id="<%= div_id -%>", class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
<div class="item active">
<div class="carousel-content">
<%= render 'article', obj: category.articles.order("impressions_count DESC").limit(3) %>
</div>
</div>
<div class="item">
<div class="carousel-content">
<%= render 'article', obj: category.articles.order("impressions_count DESC").limit(3).offset(4) %>
</div>
</div>
</div>
<a class="left carousel-control" href="#<%= div_id -%>" + "#{category.name}" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
<a class="right carousel-control" href="#<%= div_id -%>" + "#{category.name}" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
</div>
</div>
Categories controller
class CategoriesController < ApplicationController
before_action :authenticate_user!
def index
if params[:id]
#categories = Category.order('created_at DESC').where('id < ?', params[:id]).limit(3)
else
#categories = Category.order('created_at DESC').limit(3)
end
respond_to do |format|
format.html
format.js
end
end
end
assets/javascripts/category.js
$(document).ready(function () {
$('a.load-more').click(function (e) {
e.preventDefault();
$('.load-more').hide();
$('.loading-gif').show();
var last_id = $('.category').last().attr('data-id');
$.ajax({
type: "GET",
url: $(this).attr('href'),
data: {
id: last_id
},
dataType: "script",
success: function () {
$('.loading-gif').hide();
$('.load-more').show();
}
});
});
});
categories/index.js.erb
$('.container').append('<%= escape_javascript(render(:partial => #categories)) %>')
Change index.html.erb to
<div id="category">
<%= render #categories %>
</div>
index.js.erb
$('#category').append('<%= escape_javascript(render(partial: #categories)) %>')

Rails AJAX / Spinner not working properly

My spinner show but only from the second search occurence on...
When I search for a stock the first time nothing appears. Here's my repo: https://github.com/Ardzii/finance-tracker and the heroku: https://finance-tracker-ardzii.herokuapp.com/
And, so that you don't have to look the repo:
Here's the view: _lookup.html.erb (partial)
<div id="stock-lookup">
<h3>Search for stocks</h3>
<%= form_tag search_stocks_path, remote: true, method: :get, id: 'stock-lookup-form', spinner: true do %>
<div class="form-group row no-padding text-center col-md-12">
<div class="col-md-10">
<%= text_field_tag :stock, params[:stock], placeholder: "Stock ticker symbol", autofocus: true, class: 'form-control search-box input-lg' %>
</div>
<div class="col-md-2">
<%= button_tag(type: :submit, class: "btn btn-lg btn-success") do %>
<i class="glyphicon glyphicon-search"></i> Look up a stock
<% end %>
</div>
</div>
<%= render 'common/spinner' %>
<div id='stock-lookup-results'></div>
<% end %>
</div>
The spinner partial: _spinner.html.erb
<div id="spinner" class="row col-md-12 text-center spinner" style="display: none;">
<i class="glyphicon glyphicon-refresh glyphicon-spin"></i> Processing...
</div>
My Javascript file: search.js.erb
var init_stock_lookup;
init_stock_lookup = function(){
$('#stock-lookup-form').on('ajax:before', function(event, data, status){
show_spinner();
});
$('#stock-lookup-form').on('ajax:complete', function(event, data, status){
hide_spinner();
});
$('#stock-lookup-form').on('ajax:success', function(event, data, status){
$('#stock-lookup-results').html("<%= j render 'stock', {stock: #stock} %>");
init_stock_lookup();
});
}
$(document).ready(function() {
init_stock_lookup();
})
The view it renders: _stock.html.erb
<div class="well results-block">
<% if stock.present? %>
<strong>Symbol:</strong> <%= stock.ticker %>
<strong>Name:</strong> <%= stock.name %>
<strong>Price:</strong> <%= stock.price %>
<% else %>
<i>Stock not found</i>
<% end %>
</div>
My application.js file:
var hide_spinner = function (){
$("#spinner").hide();
}
var show_spinner = function (){
$("#spinner").show();
}
I'm not sure the problem was stated really clearly, so I will restate it here:
The spinner works only after a first search. On the first lookup, I have no spinner being displayed...
Thanks in advance and as usual for your help!

Categories

Resources