I'm very new to Rails and I need to dynamically add/remove input fields on a "form_for" in Rails. I am using these inputs to alter a user's profile.
Here's the snippet I want to turn dynamic:
<%= f.label :languages, "Languages" %>
<%= f.text_field :languages, class: "shortInput", value: #parsed_json_user['user']['languages']%> <br />
I have seen many tutorials using nested attributes (I'm not even exactly sure about what those are) and such but I will not be using models. As you can see, I just want an object with a multitude of values (e.g. array) since I'll be using an API to update the "User" model.
I need something like:
Languages:
English remove
add new
Should I be using fields_for? Or somehow use JS or JQuery? Any help would be appreciated.
I searched everywhere for a similar question and haven't found any but if you actually know of or find one, pointing me in the right direction would be wonderful!
Thanks in advance
#languages = User's Languages
f.collection_select :user_languages[], #languages, :id, :name , {hide_label: true, :selected => #languages.first.id} , {:style => "width: 120px",:required => true}
Update: For single form, no nesting - one option is to hack together your own jquery. I had used a different site for my testing, but this Jquery example was the one I found easier. I removed the stuff about a counter for max fields ... it goes in the /app/assests/javascript/.js ...
$(document).ready(function() {
$(".add_field_button").click(function(e){ //on add input button click
e.preventDefault();
$('.input_fields_wrap').append('<div><input type="text" name="mytext[]"/>Remove</div>'); //add input box
}
});
$(".input_fields_wrap").on("click",".remove_field", function(e){ //user click on remove text
e.preventDefault(); $(this).parent('div').remove();
})
});
And the html code ...
<div class="input_fields_wrap">
<button class="add_field_button">Add More Fields</button>
<div><input type="text" name="mytext[]"></div>
</div>
If you're not having luck yet - Cocoon Gem or railscast 197/198 will do what you need with jquery which is dynamic. Ignore the parts about nesting and just take what you need from it.
Also, I'm still poking around in turbolinks which had an update recently...you might be able to find an answer there...probably not exactly what you would want...
From what I can tell is that is rely's on two paths you write in rails, that are then built upon via the jquery that acts on (add/delete) :before or :after the link_to_add_association or link_to_remove_association in order to add/hide fields from view on the dom & then the update button actually pushes the whole mess to through activeRecord into the database.
Related
I am using Django forms to apply some basic html feature such as data mask and input pattern. Below is the code on the forms.py for one of the input fields.
'contact_person' : forms.TextInput(
attrs={'class':'form-control capitalize','pattern':'[a-zA-Z]*'}),
or data mask
'primary_phone_no' : forms.TextInput(
attrs={'class':'form-control','data-mask':"000 000 000"}),
Once I make the changes and see the changes on the browser, inspect element and locate that field, I can clearly see the changes had been applied on the HTML but when I put the input I see no changes has taken place. Means nor of the feature such as datamask or pattern is happening.
Its a very strange thing I am facing. Did someone came across this and is there something am I missing?
Thank you
It might be related to the order of where you set the widget settings. This works:
class MyForm(forms.Form):
contact_person = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control capitalize',
'pattern': '[a-zA-Z]*'
}))
primary_phone_no = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control',
'data-mask': '000 000 000'
}))
I was wondering if it possible to change the class of an image tag gotten from summernote.
Currently I am using summernote with rails4 and have implemented it the following way:
in creation of a new project
<%= form_for(#project, :html => { :multipart => true }) do |f| %>
<%= f.text_area :description, id:"summernote" %>
<script type="text/javascript">
$(document).ready(function() {
$('#summernote').summernote();
});
</script>
and when I show it
<%= #project.description.html_safe %>
If I insert an image like this it works but i would like to know two things:
1: Where does this image get stored? If I look at the source code generate it is just data:image/jpeg;base64,/9j/4S/(Bunch of random letters)
2:I would like give a class to all tags generated for images uploaded with summernote (and possibly save them using paperclip if possible)
Thanks for the help!
The "f.text_area" in your code will hold everything you enter in the summernote box entry. Once you submit the entry all images will be converted to base64 and stored directly in your database end server.
To apply your own tags on the images click on the "Code View" button found in summernote editing toolbar and locate your image code then manually place an opening <div class= "your-class"> before the image code and another closing <div> tag after your image code.
I am new in Rails and i've searched around the web and books but I couldnt find how to make custom forms when working with rails..
what happens is that I am used to write my own HTML tags and I confortable with that. I dont like to use libs like JSF (from JAVA) that writes html components for me and I dont want that rails write it for me, except for simple tags like
text_field(:post, :title, :size => 20)
# => <input type="text" id="post_title" name="post[title]" size="20" value="#{#post.title}" />
so.. how can I do that.. for example: I would like to write by myself
<input type="text" class="myclass" data="mydata" name="how-to-get-the-attribute-name-with-rails" value="how-to-get-value-with-rails" />
how can I do that?
If you want more control over the html you are creating, you can also use a content_tag
content_tag :input, "label_name", class: "myclass", data: "mydata", name: "how-to-get-the-attribute-name-with-rails", value: "how-to-get-value-with-rails"
You can supplement any html element tag for :input. So if you want a div instead, use :div etc...
As you have written above, The name of any form field in rails is in the following format
name = 'post[name]' i.e. model_name[attribute_name]
So your params hash will contain :post => {:name => value} which allows you to use mass-assignment. But if you want to get some extra parameters from the form you can directly include them in the form and give them any name as you want. It will be available in your params hash.
You can get value easily using value = <%= #object.attribute_name. %>
I am not sure if you wanted to know this or something else. Let me know if you need more help.
You can simply write html inside a Rails form, so
<input type="text" class="myclass" data="mydata" name="how-to-get-the-attribute-name-with-rails" value="how-to-get-value-with-rails" />
is perfectly valid, but note that you should use the names and id's in correct way to automatically bind them to your back end controller.
After all, what text_field(:post, :title, :size => 20) does is it convert the parameters to pure HTML (we call them helper methods in Rails).
Read here for formhelper options (using helpers will keep your code clean).
When using the FormHelper->create(...), the HTML that gets rendered looks like this:
<form action="/blogs/add" method="post" accept-charset="utf-8">
<div style="display:none;">
<input type="hidden" name="_method" value="POST">
</div>
<!-- omitted: form inputs -->
</form>
Why is that div with the display:none; style there? How do I make it not show up?
UPDATE: Just to be clear, I'm wondering why both the div AND the hidden input inside the div show up. They don't seem to be necessary, and therefore I don't want them to be there.
For anyone coming to this recently, there is a simple solution to this now that doesn't involve a custom helper. Using the FormHelper templates, the block of code in question is generated by the 'hiddenBlock' template. (See the full list of default templates here: https://api.cakephp.org/3.2/class-Cake.View.Helper.FormHelper.html#%24_defaultConfig).
So, to amend the example given in CakePHP's documentation to match this case and remove the wrapping <div> around the hidden <input> for _method (assuming HTML5):
// In your View class
$this->loadHelper( 'Form' , [ 'templates' => 'app_form' ] );
// in config/app_form.php
return [
'hiddenBlock' => '{{ content }}'
];
I was confronted with this problem because I recently implemented a Content Security Policy that doesn't allow inline styling, and I thought I should share my working solution.
The div is there to be valid HTML.
Non-block-level elements (such as <input>) are not valid directly inside <form> tags until HTML5. Source
Edit: To answer your question, you can't easily get rid of it. It's hard-coded into FormHelper::create(), you'd have to override that method in a custom helper. Why is it bothering you anyways?
This link might help you.
Whenever you use FormHelper->create() method ,A hidden input field is generated to override the default HTTP method. You can also change it by passing type option. Kindly ask if it not worked for you.
Try:
echo $this->Form->create('User', array(
'inputDefaults' => array(
'div' => false
)
));
The divs won't be created on any input of the form.
use hiddenField => false property
I have a Ruby on Rails application that I'm writing where a user has the option to edit an invoice. They need to be able to reassign the order of the rows. Right now I have an index column in the db which is used as the default sort mechanism. I just exposed that and allowed the user to edit it.
This is not very elegant. I'd like the user to be able to drag and drop table rows. I've used Scriptaculous and Prototype a bit and am familiar with them. I've done drag and drop lists, but haven't done table rows quite like this. Anyone have any suggestions for not only reordering but capturing the reorder efficiently?
Also, the user can dynamically create a new row in JS right now, so that row has to be reorderable as well.
Bonus points if it can be done with RJS instead of direct JavaScript.
I've used the Yahoo User Interface library to do this before:
http://developer.yahoo.com/yui/dragdrop/
MooTools sortables are actually better than script.aculo.us because they are dynamic; MooTools allows the addition/removal of items to the list. When a new item is added to a script.aculo.us sortable, you have to destroy/recreate the sortable to make the new item sortable. There'll be a lot overhead in doing so if the list has many elements. I had to switch from script.aculo.us to the more lightweight MooTools just because of this limitation and ended up being extremely happy with that decision.
The MooTools way of making a newly added item sortable is just:
sortables.addItems(node);
Okay, I did some more scouring and figured out something that seems to mostly be working.
edit.html.erb:
...
<table id="invoices">
<thead>
<tr>
<th>Id</th>
<th>Description</th>
</tr>
</thead>
<tbody id="line_items">
<%= render :partial => 'invoice_line_item', :collection => #invoice.invoice_line_items.sort %>
</tbody>
</table>
<%= sortable_element('line_items', {:url => {:action => :update_index}, :tag => :tr, :constraint => :vertical}) -%>
...
app/controllers/invoices.rb
...
def update_index
params["line_items"].each_with_index do |id, index|
InvoiceLineItem.update(id, :index => index)
end
render :nothing => true
end
...
The important part is :tag => :tr in "sortable_element" and params["line_items"] -- this gives the new list of ids and is triggered on the drop.
Detriments: Makes the AJAX call on drop, I think I'd prefer to store the order and update when the user hits "save". Untested on IE.
I like jQuery http://docs.jquery.com/UI/Sortables
$("#myList").sortable({});
You will need to write some code to persist it but it isn't that tough.
The Yahoo interface was easier than I expected, had something snazzy working in less than four hours.
Scriptaculous sortables seems like the way to go since it's built in.
http://github.com/madrobby/scriptaculous/wikis/sortable
With Prototype and Scriptaculous :
Sortable.create('yourTable', {
tag: 'tr',
handles: $$('a.move'),
onUpdate: function() {
console.log('onUpdate');
}
});