Turn HAML buttons into radio buttons - ruby-on-rails

I have some ruby and HAML code that works by showing two buttons on the screen. I want to change these to radio buttons. This is the code that currently shows two buttons:
.row
.col-md-6
.input-group
= render #audience, opportunity: :opportunity
What gets rendered out looks like this:
<div class="row">
<div class="col-md-6">
<a class="btn btn-lg btn-block btn-default audience-tab active" data-value="consumer" data-remote="true" href="/opportunities/229/edit?audience=consumer">Consumer</a>
</div>
<div class="col-md-6">
<a class="btn btn-lg btn-block btn-default audience-tab " data-value="business" data-remote="true" href="/opportunities/229/edit?audience=business">Business</a>
</div>
</div>
I don't need that href= stuff. Not sure why that is there. But what I want to get rendered out is two radio buttons that say "Consumer" and "Business" with a label that says "Audience Type". Something like this should work:
Audience Type:
<input type="radio" name="audience" value="consumer"> Consumer
<input type="radio" name="audience" value="business"> Business

As I see you use Bootstrap, so HAML code should look like:
%p Audience Type:
.radio
%label
%input{name: "audience", type: "radio", value: "consumer"}
Consumer
.radio
%label
%input{name: "audience", type: "radio", value: "business"}
Business
If #audience is a instance of Audience class you must place HAML code into app/views/audiences/_audience.haml template.

Related

Ruby On Rails & bootstrap_form - dropdown in f.text_field

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

rails button_to type="button"

Basically, what I am trying to get dropdown button from rails button_to, this is done via ajax, when someone clicks on that button, it shows rendered cart <ul> tag via ajax render.
bootstrap:
<button class="btn btn-primary dropdown-toggle" type = "button" data-toggle="dropdown"><span class="glyphicon glyphicon-shopping-cart"></span> <span class="badge"><%="#{#cart.line_items_count}" %></span></button>
rails button_to:
%= button_to navbar_cart_path, {remote :true, method: :get, :class => 'btn btn-primary dropdown-toggle', data_toggle: "dropdown"} do %>
<span class="glyphicon glyphicon-shopping-cart"></span>
<span class="badge" id="cart-badge-id"><%="#{#cart.line_items_count}" %></span>
<% end %>
This generates similar button tags, except when looking at html source code, bootstrap button has attribute type="button", but rails generates type="submit"
bootstrap:
<button class="btn btn-primary dropdown-toggle" type = "button" data-toggle="dropdown"><span class="glyphicon glyphicon-shopping-cart"></span> <span class="badge">5</span></button>
rails:
<form class="button_to" method="get" action="/navbar_cart data-remote="true">
<button class="btn btn-primary dropdown-toggle" data_toggle="dropdown" type="submit">
<span class="glyphicon glyphicon-shopping-cart"></span>
<span class="badge" id="cart-badge-id">5</span>
</button></form>
Another great question if whether or not it is even possible to even make a dropdown menu this way.
If you just want a drop down you could use select_tag('attr', options_for_select()) to get your drop down and then do something like this to kick off any ajax stuff you want to do:
$('#my_select_dropdown').change(function(){
//do stuff here
});
EDIT: Here is a link to look at select_tag docs in case you want more details: http://apidock.com/rails/ActionView/Helpers/FormTagHelper/select_tag
Just override the type attribute in the html_options argument of the method which is the same hash you are passing the class name for your element:
<%= button_to navbar_carth_path, {remote: true, method: :get}, {"class": "btn btn-primary dropdown-toggle", "data-toggle": "dropdown", "type": "button"} do %>
I think yo were also adding the html options within the same hash as the options hash which are not the same, the options hash (the first) are options for the rails helper per se, the second hash corresponds to attribute values that you want to apply to the rendered element:
button_to(name = nil, options = nil, html_options = nil, &block)
Check the signature of the method here.
Update You were also passing the remote :true parameter wrong, you have a space between the remote word and the actual value so it parses as a symbol, it should be: remote: true. On the other hand, I advice to enclose all html options of helpers (like data-toggle) between quotes and not only its values so that you can use hyphens instead of dashes (bootstrap option is data-toggle AFAIK, not data_toggle
So it seems like when using rails button_to and adding data: attributes doesnt overwrite type="button", so I tryed experimanting and came up with this.
<%= link_to navbar_cart_path, { method: :get, remote: true, class: "btn btn-primary dropdown-toggle", "id": "cart-button", "type": "button", "data-toggle": "dropdown" } do %>
<span class="glyphicon glyphicon-shopping-cart"></span>
<span class="badge" ><%="#{#cart.line_items_count}" %></span>
<% end %>
This generates HTML code:
a class="btn btn-primary dropdown-toggle" id="cart-button" type="button" data-toggle="dropdown" data-remote="true" data-method="get" href="/navbar_cart">
<span class="glyphicon glyphicon-shopping-cart"></span>
<span class="badge" >5</span>
Where I can then use AJAX GET to render #cart partial in dropdown tags

Bootstrap button group and form_for

In my Rails app I'd like to use a Bootstrap button group. There is a single field, and each button represents a different state .. ie like radio buttons.
Even better if I can do it with simple_form but can't find a solution by Googling.
<%= simple_form_for #user_word, url: user_words_path, remote: true, wrapper: :inline_form, html: { class: 'form-inline' } do |f| %>
<div class="row">
<div class="col-sm-12">
<div id="selector" class="btn-group btn-group-sm" >
<button class="btn level-unknown" id='unknown' type="button">Unknown</button>
<button class="btn level-low" id='low' type="button">Low</button>
<button class="btn level-medium active" id='medium' type="button">Medium</button>
<button class="btn level-high" id='high' type="button">High</button>
<button class="btn level-known" id='known' type="button">Known</button>
</div>
</div>
</div>
<% end %>
Not sure exactly what you're asking. If your issue is that the active class is not switching to your clicked button, it's because you need javascript to do so.
$('#selector button').on('click',
function(e){
var $obj=$(e.target);
$('#selector .active').removeClass('active'); //remove active class from buttons
$obj.addClass('active'); //add active class to clicked button
});
See a working example here https://jsfiddle.net/DTcHh/14519/
Edit:
I just learned that this functionality is built in to the bootstrap javascript library. Your markup just needs to be modified to match this syntax
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary active">
<input type="radio" name="options" id="option1" autocomplete="off" checked> Radio 1 (preselected)
</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="option2" autocomplete="off"> Radio 2
</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="option3" autocomplete="off"> Radio 3
</label>
</div>
See example at http://getbootstrap.com/javascript/#buttons-checkbox-radio

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 %>)

Make all input fields on the same line

Im trying to use css to make all the fields for my form display on one line. It's part of the header nav on my page so it is important that it shows on one line instead of multiple lines.
Here's my header code at the moment.
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-target=".nav-collapse" data-toggle="collapse">
<span class="i-bar"></span>
<span class="i-bar"></span>
<span class="i-bar"></span>
</a>
<a class="brand" href="/">Bandini</a>
<div class="container nav-collapse">
<ul class="nav">
<li><%= link_to "Clients", "/clients" %></li>
<li><%= link_to "Jobs", "/jobs" %></li>
</ul>
<ul class="user_nav">
<%= render :partial => "sessions/manager" %>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
The <%= render :partial => "sessions/manager" %> part points to a partial which displayes another partial depending on the users login state.
If they are logged out, then it displays the login form and if they are logged in then it shows th currrent users email adress and a signout link.
Here's my login form.
<%= simple_form_for("user", :url => user_session_path, :html => {:id => "sign_in", :class => 'form-inline' }, :remote => true, :format => :json) do |f| %>
<%= f.input :email, :placeholder => 'Email' %>
<%= f.input :password, :placeholder => 'Password' %>
<%= f.submit 'Login' %>
<%= link_to "Forgot your password?", new_password_path('user') %>
<% end %>
The form utilizes ajax and the simple_form gem for all the markup.
Ive tried playing around in Googles element tools and adding display: inline; to all of my input fields but no such luck.
Can anyone assist or point me in the right direction?
Edit: HTML generated..
<ul class="user_nav">
<form accept-charset="UTF-8" action="/users/sign_in" class="simple_form form-inline" data-remote="true" id="sign_in" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="fN0oKIlpnhS0WLZpKQafln+182IT1ONVuDP0eRtT8fg=" /></div>
<div class="control-group email required"><label class="email required control-label" for="user_email"><abbr title="required">*</abbr> Email</label><div class="controls"><input class="string email required" id="user_email" name="user[email]" placeholder="Email" size="50" type="email" /></div></div>
<div class="control-group password required"><label class="password required control-label" for="user_password"><abbr title="required">*</abbr> Password</label><div class="controls"><input class="password required" id="user_password" name="user[password]" placeholder="Password" size="50" type="password" /></div></div>
<input name="commit" type="submit" value="Login" />
Forgot your password?
</form>
</ul>
The reason display: inline; on your inputs is not working is because simple_form by default wraps a div tag around every input. There are two ways to fix this problem:
Create a custom wrapper for simple_form
https://github.com/plataformatec/simple_form#the-wrappers-api
Set both your inputs and the surrounding div to be inline-block:
.user_nav div, .user_nav input, .user_nav input[type="submit"] {
display: inline-block;
}
While the .user_nav input css style theoretically should not be necessary, it helps to specify it just in case there is some other CSS rule somewhere setting inputs to block. If you're sure that inputs are behaving normally, then you should be able to remove the second part of the CSS definition above.
By what documentation says http://twitter.github.com/bootstrap/components.html#navbar
Just add navbar-form class to your form and pull-left or pull-right
Also you should place it inside a li tag since you are placing it inside a ul

Resources