Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/opal/vienna

Client-side MVC framework for Opal
https://github.com/opal/vienna

Last synced: 30 days ago
JSON representation

Client-side MVC framework for Opal

Lists

README

        

### ⚠️ ALERT

**The project is no longer actively developed and looking for new maintainers.**

---

# Vienna: Client side MVC framework for Opal

[![Build Status](https://travis-ci.org/opal/vienna.svg?branch=master)](https://travis-ci.org/opal/vienna)

Until a better README is out (shame on us) you can take a look at
the [Opal implementation](https://github.com/opal/opal-todos)
of [TodoMVC](http://todomvc.com).

## Installation

Add vienna to your ```Gemfile``` with a reference to the Github source.

Note: The vienna hosted on rubygems.org is a different project.

```ruby
gem 'opal-vienna'
```

If you're compiling opal in a static application, make sure to require bundler first.

```ruby
require 'bundler'
Bundler.require
```

## Model

Client side models.

```ruby
class Book < Vienna::Model
attributes :title, :author
end

book = Book.new(title: 'My awesome book', author: 'Bob')
book.title = 'Bob: A story of awesome'
```

### Attributes

Attributes can be defined on subclasses using `attributes`. This simply defines
a getter/setter method using `attr_accessor`. You can override either method as
expected:

```ruby
class Book < Vienna::Model
attributes :title, :release_date

# If date is a string, then we need to parse it
def release_date=(date)
date = Date.parse(date) if String === date
@release_date = date
end
end

book = Book.new(:release_date => '2013-1-10')
book.release_date
# => #
```

## Views

`Vienna::View` is a simple wrapper class around a dom element representing a
view of some model (or models). A view's `element` is dynamically created when
first accessed. `View.element` can be used to specify a dom selector to find
the view in the dom.

Assuming the given html:

```html


Hi

```

We can create our view like so:

```ruby
class MyView < Vienna::View
element '#foo'
end

MyView.new.element
# => #]>
```

A real, existing, element can also be passed into the class method:

```ruby
class MyView < Vienna::View
# Instances of this view will have the document as an element
element Document
end
```

Views can have parents. If a child view is created, then the dom selector is
only searched inside the parents element.

### Customizing elements

A `View` will render as a div tag, by default, with no classes (unless an
element selector is defined). Both these can be overriden inside your view
subclass.

```ruby
class NavigationView < Vienna::View
def tag_name
:ul
end

def class_name
"navbar navbar-blue"
end
end
```

### Rendering views

Views have a placeholder `render` method, that doesnt do anything by default.
This is the place to put rendering logic.

```ruby
class MyView < Vienna::View
def render
element.html = 'Welcome to my rubyicious page'
end
end

view = MyView.new
view.render

view.element
# => '

Welcome to my rubyicious page
'
```

### Listening for events

When an element is created, defined events can be added to it. When a view is
destroyed, these event handlers are then removed.

```ruby
class ButtonView < Vienna::View
on :click do |evt|
puts "clicked on button"
end

def tag_name
:button
end
end
```

For complex views, you can provide an optional css selector to scope the events:

```ruby
class NavigationView < Vienna::View
on :click, 'ul.navbar li' do |evt|
puts "clicked: #{evt.target}"
end

on :mouseover, 'ul.navbar li.selected', :handle_mouseover

def handle_mouseover(evt)
# ...
end
end
```

As you can see, you can specify a method to handle events instead of a block.

### Customizing element creation

You can also override `create_element` if you wish to have any custom element
creation behaviour.

For example, a subview that is created from a parent element

```ruby
class NavigationView < Vienna::View
def initialize(parent, selector)
@parent, @selector = parent, selector
end

def create_element
@parent.find(@selector)
end
end
```

Assuming we have the html:

```html





```

We can use the navigation view like this:

```ruby
@header = Element.find '#header'
nav_view = NavigationView.new @header, '.navigation'

nav_view.element
# => [