Microframework for building and organizing Rails front-ends via Webpacker ✨
Ralix provides barebones and utilities to help enhance your current Rails views. It integrates well with Turbolinks and Rails-UJS.
Ralix consists basically in 2 concepts, Controllers
and Components
:
-
Controllers
: Controllers are meant to be mounted under a route path, they are like page-specific (scoped) JavaScript. -
Components
: Components are like widgets you will have in several pages: modals, tooltips, notifications, etc. Components can be also auto-mounted on each DOM load, you just need to pass them to theRalixApp
instance.
On the other hand, Ralix also provides some helpers and utilities to facilitate most common operations like: selectors, manipulations, events, etc. Check it out here.
To install Ralix in your application, add the ralix
npm package to your JavaScript bundle.
Using npm
:
> npm install ralix
Using Yarn
:
> yarn add ralix
Structure:
├── components
│ ├── modal.js
│ ├── geolocation.js
│ ├── flash_messages.js
│ ├── forms.js
├── controllers
│ ├── users.js
│ ├── dashboard.js
│ ├── bookings.js
│ └── app.js
├── packs
│ └── application.js
└── app.js
// Dependencies
import Rails from '@rails/ujs'
import Turbolinks from 'turbolinks'
import { RalixApp } from 'ralix'
// Controllers
import AppCtrl from 'controllers/app'
import DashboardCtrl from 'controllers/dashboard'
import BookingsCtrl from 'controllers/bookings'
import UsersCtrl from 'controllers/users'
// Components with auto-start on each DOM load event (turbolinks:load or DOMContentLoaded)
import Forms from 'components/forms'
import FlashMessages from 'components/flash_messages'
const App = new RalixApp({
rails_ujs: Rails,
routes: {
'/dashboard': DashboardCtrl,
'/bookings': BookingsCtrl,
'/users': UsersCtrl,
'/.*': AppCtrl
},
components: [
Forms,
FlashMessages
]
})
Rails.start()
Turbolinks.start()
App.start()
import Modal from 'components/modal'
export default class AppCtrl {
back() {
window.history.back()
}
toggleMenu() {
toggleClass('#menu', 'hidden')
}
openModal(url, options) {
const modal = new Modal(url, options)
modal.show()
}
}
import AppCtrl from './app'
export default class UsersCtrl extends AppCtrl {
constructor() {
super()
}
back() {
visit('/dashboard')
}
search() {
hide('.search-result')
show('.spinner')
setTimeout(() => {
submit('.search-form')
}, 300)
}
}
<a href="#" onclick="back()">Back</a>
<div id="menu">...</div>
...
<a href="#" onclick="toggleMenu()">Toggle Menu</a>
<a href="#" onclick="openModal('/modals/help')">Help me!</a>
...
<input type="text" name="query" onkeyup="search()" />
...
<div onclick="visit('/sign-up')">...</div>
export default class FlashMessages {
constructor() {
const flashMessages = findAll('.js-close-alert')
flashMessages.forEach(message => {
message.addEventListener('click', () => {
addClass(message.parentElement, 'hidden')
})
})
}
}
- find(query)
- findAll(query)
- show(query)
- hide(query)
- addClass(query, classList)
- removeClass(query, classList)
- toggleClass(query, classList)
- attr(query, attribute, value)
- data(query, attribute, value)
- insertHTML(query, html, position)
- serialize(query)
- submit(query)
- reload()
- visit(url)
- currentUrl()
- getParam(param)
- setParam(param, value, { url, update })
- setUrl(state, method, data)
- currentElement()
- currentEvent()