Update only one association with simple_fields_for - ruby-on-rails

I'm wondering what is the best solution to individually update an associated record with simple_fields_for.
I have texts associated to an order. So this what I have in my view:
= f.simple_fields_for(:texts) do |ff|
.card
.card-body
.order-text
= ff.input( \
:content,
label: false,
required: false,
disabled: !#order.finalized?,
input_html: { \
class: 'form-control order-text-field',
rows: 6,
placeholder: '' })
- if #order.finalized?
br
= ff.link_to_remove( \
'Delete this text',
data: { confirm: "Do you really want to delete this text?" })
I want to add a button under each text (like the link_to_remove) to perform a specific action + update the record.
For example, under the 2nd text, I would like to edit it, then click on a button to update ONLY this record (so I have to get the params of this specific text) + perform an action.
How can I achieve this?

Related

How to use Ajax for nested form on active admin rails

Please help me out with this problem. I am new on rails
I am trying to use the ajax method to get values on the active admin nested form. But only the top of the form gets dynamic values. After changing values on the top one form on the nested form then ajax makes a request then it changes the values(i.e. update the form values).
But after adding a new buy line item then ajax makes a request but doesn't update the values on the form i.e.same values for every new buy line item.
my js code
app/assets/javascripts/buys.js
// for nested buyline items of buys resources
$('.lineItem').change(function () {
$.ajax({
url: '/admin/get_buys_buy_line_item',
type: 'GET',
dataType: "json",
data: {
product_id: $('.lineBuyProduct').val(),
buy_quantity: $(".lineBuyQuantity").val(),
buy_quantity_unit: $(".lineBuyUnit").val(),
buy_price: $(".lineBuyAmount").val(),
},
success: (data) => {
alert(data);
// if (data == null) {
// document.getElementById('lineQuantity').value = ' ';
// document.getElementById('lineAmount').value = ' ';
// }
// else {
// document.getElementsByClassName("linebuyQuantity").value = data['1'];
// document.getElementsByClassName('linebuyAmount').value = data[0];
// console.log("Dynamic select OK!")
// }
}
});
});
});
My active admin forms
f.inputs 'Line Items', class: "lineItem" do
table do
thead do
tr do
th 'S.N', class: 'form-table__col'
th 'Product', class: 'form-table__col'
th 'Quantity', class: 'form-table__col'
th 'Unit', class: 'form-table__col'
th 'Amount', class: 'form-table__col'
th 'Expiry Date', class: 'form-table__col'
th 'Destroy', class: 'form-table__col'
end
end
end
f.has_many :buy_line_items, new_record: 'Add Buy Line Item', heading: false, allow_destroy: true do |x|
x.input :sn, label: false
x.input :product, label: false, as: :select2, collection: Product.drop_down_options,
input_html: { required: true, class: 'lineBuyProduct' }
x.input :buy_quantity, label: false, input_html: { required: true, class: 'lineBuyQuantity' }
x.input :buy_quantity_unit, label: false, collection: Unit.all.pluck(:name),
input_html: { class: 'lineBuyUnit' }
x.input :buy_price, label: false,
input_html: { required: true, class: 'lineBuyAmount' }
x.input :expiry_date, as: :date_picker, input_html: { style: 'width:auto' }, label: false
end
end
Some of my screenshots of how my program behaves and what my expectations are
In this image my first selection of product on buy line iteme then on request we can see json are renderd
But in this image after selecting another product again same json data are rendered that means doesn't update with different respective product values
And there are also some problems on active admin blaze theme, after adding class on form then it changes to legend color and add item button colors to light brown
This picture is about after removing custom class name lineItem.But, after removing this class then ajax doesn't hit for that form
Might be i faced such problem due to nested form's class on active admin.While i used default class of those form from inspect then it even doesn't hit to that form for ajax request.
So, please expert team help me to slove this problem.
If you want to send the data to create a new entity(record), you need to use the http POST method: https://api.jquery.com/jquery.post/
The GET request it just retrieves an already existing entity. Probably that's why you can read some data after an ajax call, but it's not updated.
More about the differences between GET and POST methods:
When should I use GET or POST method? What's the difference between them?
If this fix doesn't work, check the rails logs.
I have never used anything related to Ruby, and I'm not completely sure if I understood your question. I'm assuming you have problems with the AJAX behavior for new items in the list. Considering that, I think your problem could be related to attaching the "change" event to the new items. I think there might be many different other ways to get the behavior you want, but I will just elaborate on your solution using JS.
From the activeAdmin's code you can see they trigger an event called "has_many_add:after" when a new item was successfully added to its parent. Considering that, I would try changing your Javascript code to:
// for nested buyline items of buys resources
$("#buy_line_items").on("has_many_add:after", function(event, fieldset, parent){
fieldset.change(function () {
$.ajax({
url: '/admin/get_buys_buy_line_item',
type: 'GET',
dataType: "json",
data: {
product_id: $(this).find('.lineBuyProduct').val(),
buy_quantity: $(this).find(".lineBuyQuantity").val(),
buy_quantity_unit: $(this).find(".lineBuyUnit").val(),
buy_price: $(this).find(".lineBuyAmount").val()
},
success: (data) => {
alert(data);
// if (data == null) {
// document.getElementById('lineQuantity').value = ' ';
// document.getElementById('lineAmount').value = ' ';
// }
// else {
// document.getElementsByClassName("linebuyQuantity").value = data['1'];
// document.getElementsByClassName('linebuyAmount').value = data[0];
// console.log("Dynamic select OK!")
// }
}
});
});
});
I'm very confident that this will work, mainly because I don't have how to try it (if you give me the generated HTML maybe it'd help me). You can try it and reach back to see if it worked or if any adjustment is required.
You might want to change your commented lines accordingly. Also about the identifier "#buy_line_items" I'm not sure if it exists in the rendered HTML so you might need to adjust that as well.

Select box doesn't show selected value

I have a select box like this, it works and is saved in the database, but after I refresh the page the selected value doesn't appear as selected. Any suggestions?
.col-md-6
%span.label.label-purple{:style => "pointer-events: none; font-size: 14px"} Country Default
= select_tag :country_default, options_for_select(Location.where(loc_type: "country").map { |country| [country.name, country.loc_code] }),
style: "margin-top: 11px;",
include_blank: "",
class: "country-default select2", data: { select: "select2"}
options_for_select has an optional second argument, which will display your selected option, if one has been selected.
...options_for_select(Location.where(loc_type: "country").map { |country|
[country.name,
country.loc_code]}, #YOURMODEL.country_default)...
Use collection_select instead of select_tag like this:
=collection_select :country, :default, Location.where(loc_type: "country"), :loc_code, :name,
{include_blank: '', selected: 'select2' },
{class: 'country-default select2', style: 'margin-top: 11px;'}
another option is using select to generate select boxes.
See the Action View Helpers Guide

Select2 rails form repopulation

I created a rails (v5) form with multiple select and collection_select elements.
Then I use Select2-rails (v4.0.3) to allow a nice selection looking like tags.
The search-options are pulled by ajax.
It works fine until one presses the submit-button with missing required fields.
Valid field-content has now been deleted from the field.
Let me give some example-code:
controller:
...
def form
if params[:form_request].nil?
#form_request = FormRequest.new
else
#form_request = FormRequest.new(params[:form_request])
end
end
def request_form
#form_request = FormRequest.new(params[:form_request])
if #form_request.valid?
render :summary
else
render :form
end
end
...
form:
...
<%= bootstrap_form_for(#form_request, url: '/form/request_form') do |f| %>
<%= f.select :field, [], {label: 'Field label'} %>
<%= f.submit "Submit form" %>
<% end %>
:field is for sure a writable field in the model (and data is set fine)
coffee-script:
Query ->
$("#form_request_from").select2({
ajax: {
url: func =(params) ->
filter = params.term
return "/data.json?filter=" + filter;
,
dataType: 'json',
processResults: processData
},
theme: 'bootstrap',
placeholder: 'Enter data here'
});
processData = (data) ->
mapdata = $.map(data, func =(obj) ->
obj.id = obj.id;
obj.text = obj.name;
return obj;
);
return { results: mapdata };
I am thinking of a lot of possibilities, but at the end I am not sure where the field-data comes from. It is inside the object, but it isn't written to the resulting HTML in any way.
And even if the id would be written as a selected option,
the select2 script would need to know how to transform that into the string to show the real data.
Any idea how to achieve that the data is still written into a field after a failing validation?
After trying out some things I found out how to do it.
At first I just changed the empty array to be the :field variable,too.
This doesn't work too well because it only remembers the ID of the value that has been entered before and like this the SELECT2-script could not find the value to that key and nothing is shown.
Then I created a new variable inside the controller in which I place the array with name and id:
field_object = ObjectsModel.find(#form_request.field.to_i)
#form_field = []
if !field_object.nil?
#form_field = [[field_object.name, field_object.id]]
end
And in the view I now use this field to show the available options:
<%= bootstrap_form_for(#form_request, url: '/form/request_form') do |f| %>
<%= f.select :field, #form_field, {label: 'Field label'} %>
<%= f.submit "Submit form" %>
<% end %>
This works perfectly fine for me without the need to touch the SELECT2-script.
The possible values are still fetched by AJAX but already filled out fields will persist upon redirect to another action.

Multiple selected data doesn't appear

I use select2 for multiple select. My problem is, I can select multiple value from json data and I can save this data in related model columns. But when I want to update this model, the selected data doesn't appear.
some part of my json data:
{
- categories:[
- {
id:7,
name:"Eğitim Bilimleri Enstitüsü"
},
- {
id: 8,
name: "Eğitim Yönetim Teftişi ve Planlaması 1. Yarıyıl"
},
...
]
}
I have a Moodle class(it is not inheritance from ActiveRecord, just a class and it has some functions which return json data). I am wondering whether it is right approach.
in the content of my form:
<%= simple_form_for(#period) do |f| %>
...
<%= f.input :moodle_connect_ids, collection: Moodle.categories.map {|p| [ p['name'], p['id'] ] }, input_html: {multiple: true} %>
...
<% end %>
I explicitly set moodle_connect_ids to be an array in my controller:
params.require(:period).permit(..., :moodle_connect_ids => [])
in the content of my .js file:
$("#period_moodle_connect_ids").select2({
placeholder: "Moodle Dönem Bağlantılarını Seçiniz",
multiple: true,
allowClear: true
});
When I select to multiple values and save my model, the column's value looks like this:
> Period.last
=> #<Period:0x007fcf53a4d830
id: 25,
...
moodle_connect_ids: "[\"\", \"85\", \"120\"]"
...
Am I on the wrong way? Have you any suggestion?
I've figured out how to do this issue.
I've added selected option in the f.input:
selected: #period.moodle_connect_ids? ? JSON.parse(#period.moodle_connect_ids).map(&:to_i) : []
the input's last state:
<%= f.input :moodle_connect_ids, collection: Moodle.categories.map {|p| [ p['name'], p['id'] ] }, input_html: {multiple: true}, selected: #period.moodle_connect_ids? ? #period.moodle_connect_ids.map(&:to_i) : [] %>

rails 4 simple form include_blank still sending empty attributes

I have the following form setup:
= simple_form_for(#job, url: job_payment_path, html: { id: 'payment-processor-form' }) do |j|
div[class='row']
div[class='col-md-12']
div[class='panel panel-default']
div[class='panel-heading']
h3[class='panel-title']
|Total Cost
div[class='panel-body']
h2[class='job-cost' data-initial = "#{job_base_price}"]
= number_to_currency(job_base_price)
div[class='panel-heading']
h3[class='panel-title']
|Have a coupon?
div[class='panel-body']
div[class='row-inline']
div[class='row-block row-block-one']
= j.simple_fields_for :coupon_attributes, #job.coupon do |c|
= c.input_field :code, maxlength: 50, id: 'coupon-code', class: 'form-control', data: { 'initial' => 0 }, include_blank: false
div[class='row-block']
button[type='button' class='btn btn-primary' id='coupon-verify' ]
|Verify
p[class='help-hint']
= t('simple_form.hints.coupon.code')
div[class='row']
div[class='col-md-12']
= j.button :button, type: 'button', class: 'btn-primary text-uppercase', id: 'purchase-job' do
= job_posting_button_step_label
When this form submits, I am seeing the following attributes:
This is not right.
I would expect the coupon code to be nil, not "".
Am I missing something here?
I see two things:
first:
:include_blank is an option for select fields, it skips the generation of a blank option tag at the beginning. code is an input field. If you want to force an input value, try required: true.
second:
form values are sent to the server as application/x-www-form-urlencoded. Empty imput fields are sent as i.e. job[coupon_attributes][code]=. There is no distinction between an empty string and no value.
The convention in Rails is to interpret all input values as string (and typecast later when assigning values to models). So an empty value is always returned as ''.

Resources