How do I do a jQuery toggleClass in Volt?

149 views Asked by At

I'm playing around with Volt and currently trying to do a simple toggleClass for a sidebar in my Volt app (with no luck). Here is a code sample.

app/main/views/main.html

<:Title>
  {{ view main_path, "title", {controller_group: 'main'} }}

<:Body>

  <div id="wrapper">
    <div id="sidebar-wrapper">
      <ul class="sidebar-nav">
        <li><a href="#">blah</a></li>
        <li><a href="#">blah</a></li>
        <li><a href="#">blah</a></li>
        ...
      </ul>
    </div>

    <div id="page-content-wrapper">
      <div class="container-fluid">
        <div class="btn btn-default sidebar-toggler">Toggle Sidebar</div>
        <:volt:notices />
        {{ view main_path, 'body', {controller_group: 'main'} }}
      </div>
    </div>
  </div>

app/main/assets/js/sidebar.js

$(document).ready(function() {
  $(".sidebar-toggler").click(function(e) {
    e.preventDefault();
    $("#wrapper").toggleClass("toggled");
  });
});

When clicking on div.sidebar-toggler a toggled class should be added to div#wrapper ... It doesn't, there maybe another way to do this with Volt.

The code above is not working. What's the good Volt way to do this ?

1

There are 1 answers

0
Ryan On BEST ANSWER

In volt, you would typically make the toggle state a "reactive accessors" on the controller, then use bindings to update the class state. Since controllers are the context for bindings, we can check the state of the reactive_accessor in an if binding.

in the controller:

module Main
  class MainController < Volt::ModelController
    reactive_accessor :toggled

    def toggle_sidebar
      self.toggled = !toggled
    end
    ....

in the view:

...
<div class="btn btn-default sidebar-toggler {{ if toggled }}toggled{{ end }}" e-click="toggle_sidebar">Toggle Sidebar</div>
...

When we call the self.toggled = method, it changes the state and reactively updates any bindings using that data. The e-click calls the toggle_sidebar method on the controller. The common Volt way to do something simple like this is to put the if directly into the view. We could also put it into a method that returns a string and bind to that.

def toggled_class
  toggled ? 'toggled' : ''
end

....

<div class="btn btn-default sidebar-toggler {{ toggled_class }}" e-click="toggle_sidebar">Toggle Sidebar</div>

Hopefully that helps, I can clarify more if you need.