Giter Club home page Giter Club logo

snabberb's Introduction

Snabberb

Snabberb is a simple Ruby view framework built on Opal and Snabbdom.

You can write reactive views in plain Ruby that compile to efficient Javascript.

Inline Example

require 'opal'
require 'snabberb'

class TextBox < Snabberb::Component
  needs :text
  needs :selected, default: false, store: true

  def render
    onclick = lambda do
      store(:selected, !@selected)
    end

    style = {
      cursor: 'pointer',
      border: 'solid 1px rgba(0,0,0,0.2)',
    }

    style['background-color'] = 'lightblue' if @selected

    h(:div, { style: style, on: { click: onclick } }, [
      h(:div, @text)
    ])
  end
end


# Assuming you have a DOM element with ID=app
TextBox.attach('app', text: 'hello world')

# Or you can get the HTML string for isomorphic applications
TextBox.html(text: 'hello world')

Examples

Rack App

Roda App with HTML Prerendering

18xx Board Game Engine

Usage

Creating DOM Elements With h

Subclass Snabberb::Component and override #render to build divs using #h.

Render should only return one root element.

#h takes either a DOM symbol (:div, :span, :a, ...) or another Snabberb::Component class.

...
class DomExample < Snabberb::Component
  def render
    h(:div)
  end
end

class ComponentExample < Snabberb::Component
  def render
    h(OtherComponent)
  end
end

Like Snabbdom, #h with DOM elements can take props which take the form of a dict.

...
class PropsExample < Snabberb::Component
  def render
    h(:div, { style: { display: 'inline-block' }, class: { selected: true } })
  end
end

Components do not take props, instead they take needs which are dependent arguments.

...
class PassingNeedsExample < Snabberb::Component
  def render
    h(ChildComponent, need1: 1, need2: 2)
  end
end

#h can also be nested with a child or multiple children.

...
class NestedExample < Snabberb::Component
  def render
    h(:div, [
      h(ChildComponent, need1: 1, need2: 2),
      h(:div, { style: { width: '100px' } }, [
        h(:div, 'hello'),
      ])
    ])
  end
end

Needs

Components can define needs which allow parent components to pass down arguments. They can also be stateful which allows changes to propogate easily throughout the application.

Needs are by default required. They can be set with default values. Needs are accesible with instance variables that are automatically set.

...
class NeedsExample < Snabberb::Component
  needs :name
  needs :value, default: 0, store: true

  def render
    onclick = lambda do
      store(:value, @value + 1)
    end

    h(:div, [
      h(:div, @name),
      h(:div, { on: { click: onclick} }, @value),
    ])
  end
end

When simple state changes must be tracked, a need can define store: true. This will use the stored value of this key which is set on the root node. The precedence of need values is stored > passed needs > default value.

Needs can be set with #store which will trigger a view update. Snabberb uses Snabbdom to update the DOM, so only the differences in the DOM are changed.

Prerendering

You can prerender your HTML by calling

Snabberb.prerender_script('LayoutClass', 'ApplicationClass', 'application_id', javascript_include_tags: '', **needs)

A detailed example can be found in the Roda example.

Generating HTML from a File

You can generate HTML from a component with a file.

Snabberb.html_script('path/to/my_component.rb', **needs)

This reads in the ruby file at the path and generates javascript that calls html on the CamelCased version of the file name.

Installation

Add this line to your application's Gemfile:

gem 'snabberb'

And then execute:

$ bundle

Or install it yourself as:

$ gem install snabberb

Development

bundle install
bundle exec rake

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/tobymao/snabberb.

License

The gem is available as open source under the terms of the MIT License.

snabberb's People

Contributors

dependabot[bot] avatar michaeljb avatar tobymao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

snabberb's Issues

Get following error when use with opal, opal-opal-sprockets.

Hi, i am a newbie to Opal.

I am developing a Roda web app, and Opal seem like works!

because you can see a hello output on browser console (i output it from opal)

But, when i try to following inline example in readme, get following error.

image

Could you please help on this? thank you.

Following is my source code for reproduce.

https://github.com/zw963/marketbet_crawler/blob/test_snabberb/assets/js/app.rb

I use roda-sprockets plugin like this:

plugin :sprockets, precompile: %w(app.rb app.scss),
    root: Dir.pwd,
    public_path: 'public/',
    opal: true,
    debug: ENV['RACK_ENV'] != 'production'

Typo in sample code

In your example of nested children, your last close parenthesis is an open parenthesis instead.

This appears in the code below this text:

"#h can also be nested with a child or multiple children.#

[BUG] Event handlers not working properly

The problem I have is with handling click events and passing a value to it. in snabbdom things are pretty straightforward

function clickHandler(number) {
  console.log("button " + number + " was clicked!");
}
h("div", [
  h("a", { on: { click: [clickHandler, 1] } }),
]);

and this the code I write in opal

click_handler = -> (_, el) do
  p "button" + Native(el).data.on.click[1] + " was clicked!")
end

h(:div, [
  h(:a, {on: click: [click_handler, 1]} )
])

As you can see, you have to go through the element to get to the value, which makes the code not really nice

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.