Ruby On Rails & bootstrap_form - dropdown in f.text_field - ruby-on-rails

I want to have dropdown at text_field in Ruby on Rails form.
I wrote the code like that:
<div class="dropdown">
<%= f.text_field :title, class: "dropdown-toggle", data: {toggle:"dropdown"} %>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
# some dropdown items
</ul>
</div>
My code doesn't work and I get an error...
Uncaught TypeError: Cannot read property 'setAttribute' of null
In my investigation, the problem seems ....
<div class="dropdown"
<div class="form-group">
<input class="form-control dropdown-toggle" data-toggle="dropdown" type="text">
</div>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
# some dropdown items
</ul>
</div>
Since I'm using bootstrap form, f.text_field is automatically wrapped by "form-group".
I don't need this wrapper in order to make dropdown work well.
So, the following code will work, but I don't know how to realize it by using f.text_field in bootstrap form.
<div class="dropdown"
<input class="form-control dropdown-toggle" data-toggle="dropdown" type="text">
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
# some dropdown items
</ul>
</div>
Please tell me how to coexist "f.text_field", "form-group", and bootstrap dropdown.

I found a solution at offical document (https://github.com/bootstrap-ruby/bootstrap_form)
You may want to define your own form group div around a field. To do so, add the option wrapper: false to the input field. For example:
f.form_group :user do
f.email_field :email, wrapper: false
end

Related

How to capture a search term from a form and pass it to a method in Rails app

I am learning rails online and have got as far as creating a simple site with some products in a products table with fields:
id
name
price
description
I have gone to the getbootstrap site and started pinching the code from this example -
https://getbootstrap.com/docs/4.0/examples/jumbotron/
This page has a nice search box in the navbar at the top right. I now have it in my simple site and the container HTML currently looks like this:
<div class="container" >
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">My Shop</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="/">Products</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</div>
</nav>
</div>
My problem is that all of the tutorials I see are creating simple forms using ERB to implement some sort of search functionality. like so:
<% form_tag projects_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
While I want to utilise this nicely rendered HTML form instead.
I don't know how to capture the search term and pass it to a method from my form. The ERB example uses the params hash to store the search term.
What I would like to implement is -
1 - Capture the name of a product entered in the search box
2 - Pass that string to a method in my model that queries the DB for first matching name
3 - gets the record id and uses it to redirect to the Show page with the id to display the item
I have found that setting the form action to "/" causes a click on the submit button to jump to the index method in my controller. From there I am sure I could utilise the model to query the underlying DB but I cannot seem to pass across the search term.
I do have a params hash at that point but it just seems to have a "controller" and an "action" member. Is there an attribute I can set that would add the value to this hash?
Thanks in advance
Brad
You must set an action to the form and a name to the field
<form class="form-inline my-2 my-lg-0" action="/search" method="get">
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search", name: "search>
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
Then define the method in a controller.
StaticPagesController
def search
#search_term = params[:search]
end
And define your route in routes.rb
match '/search', to: 'static_pages#search', via: 'get'

How do I implement bootstrap dropdown in rails with categories

I'm wanting to implement Bootstrap's dropdowns in my rails project similar to the code below provided on Bootstrap's website:
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
Dropdown
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
<li role="separator" class="divider"></li>
<li>Separated link</li>
</ul>
</div>
I currently have a section in the project where I can add new/edit categories for use in the main form. The code I currently have for an unformatted select/dropdown is:
<%= f.select :category_id, Category.all.map { |category| [ category.name, category.id ] }, class: "form-control" %>
Which doesn't seem to apply any bootstrap formatting, I've tried changing the code around a bit to be:
<%= f.select :category_id, options_for_select([Category.all.map { |category| [ category.name, category.id ] }]), {}, class: "form-control" %>
This gives the dropdown box a bootstrap style box, but the dropdowns under the default selection don't have any formatting similar to Bootstrap's example. One of my categories is just called Pages, but the text inside the selectbox in the code above just shows ["pages", 1] where 1 is the ID.
Any help with this would be greatly appreciated :)
i think correct syntax is like below
= f.select :category_id, options_for_select(Category.collect {|c| [c.name, c.id]}), { :include_blank => "Please select category"}, {:class => "form-control"}

Rails 3: Make token inputs sortable

I am using token inputs in a text field and would like to also make these tokens sortable (JQuery UI). I am using Ryan Bates screencast to get started however I am unsure how to apply content_for to my code. Here is what I have...
<fieldset id="presenters">
<p>
<%= event_form.label :presenter_tokens, "Presenters" %>
<%= event_form.text_field :presenter_tokens, "data-pre" => #event.presenter_tokens_tokeninput.to_json %>
</p>
</fieldset>
Here is the HTML I get...
<fieldset id="presenters">
<p>
<label for="event_presenter_tokens">Presenters</label>
<ul class="token-input-list-facebook">
<li class="token-input-token-facebook">
<p>Mark</p>
<span class="token-input-delete-token-facebook">×</span>
</li>
<li class="token-input-token-facebook">
<p>Laurie</p>
<span class="token-input-delete-token-facebook">×</span>
</li>
<li class="token-input-input-token-facebook">
</ul>
<input data-pre="[{"id":131,"name":"Mark"},{"id":1311,"name":"Laurie"}]" id="event_presenter_tokens" name="event[presenter_tokens]" size="30" type="text" value="131,1311" style="display: none;"/>
I ended up solving this problem by using https://github.com/swanandp/acts_as_list

How to compare AngularJS value to ruby on rails variable value

I am using Firebase in a pretty simple chat application. One of the features i'm working on now is the ability to update messages in the chat room, but only if you were the original author. For the editing i have an icon that, when clicked, will do some javascript to hide the message div and display a previously hidden div that has the update form in it. But i only want this to be available if you were the author of the message. Here's what the code looks like:
<li class="message phm pvm pull-left" ng-repeat="(msgId,msg) in room.messages">
<div class="message-current" data-message-id="{{msgId}}">
<span class="message-author pull-left">{{msg.author}}</span>
<span class="message-body pull-left pls">{{msg.body}}</span>
<span class="message-timestamp pull-right prs">
{{msg.timestamp | date:'MMM d, yyyy h:mm a'}}
<a class="message-update-link" href="#" ng-click="showMessageUpdate(msgId)"><span class="glyphicon glyphicon-pencil"></span></a>
</span>
</div>
<div class="message-update hidden" data-message-id="{{msgId}}">
<form class="form-inline" ng-submit="updateMessage(roomId, msgId, '<%= current_user.full_name %>')">
<textarea class="form-control update-message" ng-model="msg.body" ng-trim="false">{{msg.body}}</textarea>
<input class="button button-large button-primary" type="submit" value="Update">
</form>
</div>
</li>
Right now, i can only get it to have updatable message for ALL message or no messages. Basically, the part i am stuck on is the check of whether or not the angularjs value of {{msg.author}} is equal to the rails value of <%= current_user.id %>. Any thoughts on how this can be achieved? Thanks for any help!
SOLVED:
Thanks to Jiten for the step in the right direction. I'm new to learning AngularJS and it's pretty complex. Sometimes you just need to know where to start.
I ended up using a combination of the ngIf directive and the angular.equals function. In my rails view i used ng-if="isAuthor(msg.author, '<%= current_user.full_name %>')" on anything i wanted available to authors of that message only. This will evaluate the response of isAuthor() and only render to the dom if it evaluates to true. The code above now looks like this:
<li class="message phm pvm pull-left" ng-repeat="(msgId,msg) in room.messages">
<div class="message-current" data-message-id="{{msgId}}">
<span class="message-author pull-left">{{msg.author}}</span>
<span class="message-body pull-left pls">{{msg.body}}</span>
<span class="message-timestamp pull-right prs">
{{msg.timestamp | date:'MMM d, yyyy h:mm a'}}
<a ng-if="isAuthor(msg.author, '<%= current_user.full_name %>')" class="message-update-link" href="#" ng-click="showMessageUpdate(msgId)"><span class="glyphicon glyphicon-pencil"></span></a>
</span>
</div>
<div ng-if="isAuthor(msg.author, '<%= current_user.full_name %>')" class="message-update hidden" data-message-id="{{msgId}}">
<form class="form-inline" ng-submit="updateMessage(roomId, msgId, '<%= current_user.full_name %>')">
<textarea class="form-control update-message" ng-model="msg.body" ng-trim="false">{{msg.body}}</textarea>
<input class="button button-large button-primary" type="submit" value="Update">
</form>
</div>
</li>
Here is what isAuthor() looks like in my AngularJS controller:
$scope.isAuthor = function(msgAuthor, currentUser) {
return angular.equals(msgAuthor, currentUser);
}
Pretty simple really!
To compare two objects you can use:
angular.equals({{msg.authorId}}, <%= current_user.full_name %>)

wysihtlm5 form submit and validation

I'm having trouble implementing the wysihtlm5 editor using the wysihtml5-rails gem: https://github.com/NARKOZ/wysihtml5-rails
First of all, my html tags are not saved to the database. Then if the form submit fails, the text_area is only filled with plain text. How can i make sure, the html tags are sent to the server in the right way?
In the debug output i can see that the description is arriving in the controller without html tags:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fW5FMxr/sgNkLUowLT2E0UfIXtFbXvkOubPYM0GJm0I=", "description"=>"sdfgsdfg"}, "_wysihtml5_mode"=>"1"}
application.js:
//= require wysihtml5
//= require parser_rules/advanced
In my view:
<%= form_for #auction do |f| %>
<div class="control-group">
<label class="control-label" for="auction_days">Beschreibung</label>
<div class="controls">
<div id="wysihtml5-toolbar" style="display: none;">
<div class="btn-group">
<a data-wysihtml5-command="bold" title="CTRL+B" class="btn"><i class="icon-bold"></i></a>
<a data-wysihtml5-command="italic" title="CTRL+I" class="btn"><i class="icon-italic"></i></a>
<a data-wysihtml5-command="underline" title="CTRL+U" class="btn"><i class="icon-underline"></i></a>
</div>
<div class="btn-group">
<a data-wysihtml5-command="formatBlock" data-wysihtml5-command-value="h1" class="btn">H1</a>
<a data-wysihtml5-command="formatBlock" data-wysihtml5-command-value="h2" class="btn">H2</a>
</div>
<div class="btn-group">
<a data-wysihtml5-command="insertUnorderedList" class="btn"><i class="icon-list-ul"></i></a>
<a data-wysihtml5-command="insertOrderedList" class="btn"><i class="icon-list-ol"></i></a>
</div>
<a data-wysihtml5-command="createLink" class="btn"><i class="icon-link"></i> Link</a>
<!--<a data-wysihtml5-action="change_view">switch to html view</a>-->
<br /><br />
<div data-wysihtml5-dialog="createLink" style="display: none;" class="alert alert-info input-xxlarge">
<label><strong>Link einfügen:</strong></label>
<input type="text" data-wysihtml5-dialog-field="href" value="http://" class="span3">
<a data-wysihtml5-dialog-action="save" class="btn">OK</a> <a data-wysihtml5-dialog-action="cancel" class="btn">Abbrechen</a>
</div>
</div>
<%= f.text_area :description, :id => 'wysihtml5-textarea', :label=>false, :class=>"input-xxlarge", :placeholder => "Beschreibung hier einfügen ..." %>
<script>
var editor = new wysihtml5.Editor("wysihtml5-textarea", {
toolbar: "wysihtml5-toolbar",
parserRules: "wysihtml5ParserRules"
});
</script>
</div>
<%= button_tag(type: 'submit', class: "btn btn-success") do %>
<i class="icon-ok icon-white"></i> Send
<% end %>
<% end %>
is the editor load properly? try inspect element in browser for the case when validation fail ,is because what you re saving is plain text, so it will just display plain text for you as well.
I saw there is a html view tag in the demo, maybe you try check whether it can be changed to html text or not.
Additionally:
I personally recommend the plain 1 without gem.
https://github.com/mindmup/bootstrap-wysiwyg
or ckeditor or tinymce :D

Resources