Lightweight and powerful data binding.

Overview

Rivets.js

Rivets.js is a lightweight data binding and templating system that facilitates building data-driven views. It is agnostic about every aspect of a front-end MV(C|VM|P) stack, making it easy to introduce it into your current workflow or to use it as part of your own custom front-end stack comprised of other libraries.

Usage

<section id="auction">
  <h3>{ auction.product.name }</h3>
  <p>Current bid: { auction.currentBid | money }</p>

  <aside rv-if="auction.timeLeft | lt 120">
    Hurry up! There is { auction.timeLeft | time } left.
  </aside>
</section>
rivets.bind($('#auction'), {auction: auction})

Getting Started and Documentation

Documentation is available on the homepage. Learn by reading the Guide and refer to the Binder Reference to see what binders are available to you out-of-the-box.

Building and Testing

First install any development dependencies.

$ npm install

Building

Rivets.js uses gulp as its build tool. Run the following task to compile + minify the source into dist/.

$ gulp build

Testing

Rivets.js uses mocha as its testing framework, alongside should for expectations and sinon for spies, stubs and mocks. Run the following to run the full test suite.

$ npm test

Contributing

Bug Reporting

  1. Ensure the bug can be reproduced on the latest master.
  2. Open an issue on GitHub and include an isolated JSFiddle demonstration of the bug. The more information you provide, the easier it will be to validate and fix.

Pull Requests

  1. Fork the repository and create a topic branch.
  2. Make sure not to commit any changes under dist/ as they will surely cause conflicts for others later. Files under dist/ are only committed when a new build is released.
  3. Include tests that cover any changes or additions that you've made.
  4. Push your topic branch to your fork and submit a pull request. Include details about the changes as well as a reference to related issue(s).
Comments
  • The People Deserve A New Rivets Release!

    The People Deserve A New Rivets Release!

    Hi All,

    @Leeds-eBooks and I have spoken, we want to start the conversation about a new release. @Leeds-eBooks and I are the most recently added core contributors and we seem to be the only active 2 right now (he more than I). Rivets has had a TON of new activity lately this is great and very healthy! In order to keep everyone interested and willing to help, we we must push things forward even in the absence of the original developer @mikeric.

    In the coming days we will revisit all (currently 37) open pull requests. When this is done I will report back to this thread and we can all give our arguments for or against moving forward with the accepted PR's representing the new feature set.

    Anyone following rivets with decent opensource experience please chime in. We need your help to ensure we dont mess things up and upset people.

    If anyone knows @mikeric can you personally reach out to him and ask him to give some of us access to publish to NPM. (we cannot publish new version to NPM without it.)

    opened by Duder-onomy 36
  • Conditional Logic

    Conditional Logic

    It's me again :)

    I'm new to data binding but i've been checking out knockout as well.

    is it possible to do conditional logic with rivets?

    something like this

    <div class="post">
        <div data-if="post.type = foo">
            <h2>Foo</h2>
            <span>foo stuff</span>
        </div>
        <div data-if="post.type = bar">
            <h2>Bar</h2>
            <span>bar stuff</span>
        </div>
    </div>
    
    opened by wayneashleyberry 22
  • Some bugs have been fixed. Time for a 0.9.2?

    Some bugs have been fixed. Time for a 0.9.2?

    Hi

    There has been several bad issues detected. Some are fixed with PR.

    Issues

    • [x] #644
    • [x] #650
    • [x] #649
    • [x] #658

    Doc update

    • [x] Details on computed properties (#658)
    • [x] Download link update

    @Leeds-eBooks @Duder-onomy Is it time for a 0.9.2?

    opened by jccazeaux 19
  • Rivets function auto-execution in expressions

    Rivets function auto-execution in expressions

    In this issue, I would like to discuss the auto-execution of functions in Rivets expressions

    { model.myFunction }
    

    If myFunction is a function, Rivets will execute it and send the result in the template.

    I think we should turn off this feature. It would allow us to manually call the function with parameters. This would be a powerfull feature for a very small cost. The manual execution would be handled by a formatter like

    { model.myFunction | call model.param1 'param2' }
    

    For backward compatibility reasons we could have a parameter in Rivets configuration

    rivets.configure({autoExecuteFunctions: true});
    

    I know it's less user friendly than a JS expression. But it's in the rivets template syntax and would totally benefit of the existing databinding mecanism without any additional work. I like rivets expression syntax, because it's very easy to learn but very powerful.

    opened by jccazeaux 19
  • Memory leak in 0.7.1

    Memory leak in 0.7.1

    Hi

    I've done the upgrade from 0.6.9 to 0.7.1. Since i noticed some memory leak. The objects seem to be retained after unbind. I made a jsfiddle with a very basic bind/unbind. In the model i put a very big String (~5MB) so we can clearly see the allocations and deallocations.

    example with 0.6.9 : http://jsfiddle.net/jccazeaux/v6x47k6k/

    In the chrome profiler we can see that the objects are correctly freed: image

    Same code with 0.7.1 : http://jsfiddle.net/jccazeaux/v6x47k6k/2/

    In the chrome profile we see that the objects are retained. The memory is growing. 071

    To test it, just start the "Record heap allocation" profiling type and click alternatively on "bind" and "unbind".

    opened by jccazeaux 19
  • how to pass input parameter into function through rv-on-xxx

    how to pass input parameter into function through rv-on-xxx

    Hi All,

    I'd like to pass something to function through rv-on-blur rv-on-blur="item.dd('1')"

    But it fails, how to do, anyone can teach me?

    Thanks Eric Xin

    opened by ericxin1982 18
  • Ability to invoke function inside rivets expressions

    Ability to invoke function inside rivets expressions

    It's not very hard to implement ability to pass arguments (and watch them) into function in rivets expression. So that, all the methods will have more clear api

    <div rv-show="canShow(todo)" rv-each-todo="todos"></div>
    
    <a rv-click="selectTab(tab)">Tab 1</a>
    
    <h1>{ formatDate(todo.createdAt, 'hh:mm') }</h1>
    

    Basically we need to add one more if inside TypeParser which will compile and return function. We can restrict this so the implementation won't be very complicated. For example, it's possible to pass only primitives and keypaths. That means we can't pass function invokation as a result. So this is not valid:

    { formatDate(todo.getDate(), 'hh:mm') }
    

    However I believe even this case can be handled using recursive.

    @blikblum, @Leeds-eBooks, @jccazeaux do you think this something useful or overcomplicated?

    opened by stalniy 18
  • Binding issues with jQuery plugins

    Binding issues with jQuery plugins

    I'm having a little issue figuring out the best way to hook Rivets up to a jQuery plugin. What I initially tried was making sure that the jQuery plugin announced updates by triggering off an event.

    The problem is, I end up with a bit of circular logic, because the plugin announces and update, Rivets updates the model, which then fires off the "routine" binder, which then manually updates the plugins value, which fires off my trigger again.

    What I'm running into is if I can set() on the model directly, things work as I expect. However, if I manually use the jQuery plugin to select my value, I end up getting my callback selections to fire off twice.

    Any suggestions?

    opened by dswitzer 18
  • Interfaces

    Interfaces

    As a follow-up to #92, I think the keypath access notations (. and :) should not be hardcoded into Rivets.js core, it's confusing to beginners what these are for, and "why" you actually need to define an adapter. Instead they should be exposed as interfaces that you can add and overwrite however you like, but not required to start using Rivets.js.

    By default, Rivets.js would ship with a single interface for the . notation to observe properties on POJSOs using ES5 natives. This interface will work on all ES5-compliant browsers (IE9+, FF4+, SF5+, CH7+ and OP12+).

    If you're targeting non-ES5 browsers, you can overwrite the default interface to work with an evented model library of your choice that has the legacy browser support you need.

    You can add as many interfaces as you like and assign whatever separator you want to them. For example, you can keep . for subscribing to plain objects, add : or @ for subscribing to Backbone.js model attributes or even # for subscribing to validation errors if you want.

    The API for defining an interface would be similar as for defining the adapter in < 0.6.0.

    rivets.interfaces[":"] = {
      observe: function(keypath, callback) {
        this.on("change:" + keypath, callback)
      },
      unobserve: function(keypath, callback) {
        this.off("change:" + keypath, callback)
      }
      get: function(keypath) {
        return this.get(keypath)
      },
      set: function(keypath, value) {
        this.set(keypath, value)
      }
    }
    

    There would be no more : notation by default. If you want similar functionality as the adapter bypass, you can just implement an interface for it (leave out the observe and unobserve functions and define a simple get and set).

    rivets.interfaces[":"] = {
      get: function(keypath) {
        return this[keypath]
      },
      set: function(keypath, value) {
        this[keypath] = value
      }
    }
    

    To sum things up, there would now be 3 main concepts for tuning Rivets.js to your application.

    • Interfaces: Defines how Rivets.js observes and interacts with the model / keypath.
    • Binders: Defines how Rivets.js affects the DOM and/or model when properties change.
    • Formatters: Defines how Rivets.js affects incoming values before it goes through the binder and/or back to the model.

    All of which are accessible in the universal syntax for binding declarations:

    data-[prefix]-[binder]="[model][interface][keypath] < [dependencies] | [formatters]"
    
    opened by mikeric 18
  • Delayed value on inputs

    Delayed value on inputs

    It would be nice if you could specify when you want 'value' to be updated (keyup, keydown, keypress, etc.) to make everything look a bit snappier. Right now you need to lose focus/press enter before it will publish using data-value. I tried to accomplish this with an extension but modifying value within the context of the function has no effect. This might be a different issue but it would be nice to have control over changing the value from within an extension via some convenience functions.

    What I want to do (rough example):

    rivets.register 'keyup', (el, val) ->
      el.addEventListener 'keyup', (e) -> 
        val += String.fromCharCode e.which
    
    opened by yocontra 18
  • feat(components): make

    feat(components): make "template" method being optional.

    Features for components:

    • made "template" method being optional
    • added ability to return DOM node/fragment from "template" method
    • added tests for component binding

    CC: @Leeds-eBooks, @mikeric, @ansman

    opened by stalniy 17
  • Get Callback when component args change

    Get Callback when component args change

    Hello, not really an issue but more a question/feature request. Is there any way that i can trigger a callback function on a rivets components viewModel anytime the arguments to the component change? I have a plugin that needs some manual setup/configuration within the view. I would like to trigger the functions that do this from within the component every time the arguments change. I was thinking something along the lines of the following:

    rivets.components['session-chooser'] = { template: function() { return SessionChooser.prototype.HTML; }, initialize: function(el,attr) { let viewModel = new SessionChooser(el,attr);
    this.observers.event.callback <- point this at a function on the viewModel somehow or add another observer to do so.. return viewModel; } }

    opened by GtrPksRnt4eatin 0
  • Cart quantity error

    Cart quantity error

    Hello! In 8/10 cases, when adding the quantity of products, for example, 4 pieces - after going to Cart, there is not 4, but 1 piece. And you have to manually put the right amount in Cart. As if rivets or ajax scripts are not immediately loaded or maybe something else. What could it be? We need your help.

    opened by pavelzolotin 0
  • Separate scopes / do not pollute global

    Separate scopes / do not pollute global "rivets" configuration

    This may just be something I am not seeing, but is there a way of creating different scopes that do not share the same "rivets" object?

    I.e. I do not see a way of having 2 separate views with different formatters bound to them, as they are all registered on the same "rivets" object,

    E.g. rivets.formatters.gt = (a,b) => a > b; becomes available in all bindings/views, as far as I can tell?

    I want isolated views that are not "polluted" with formatters and other options set on other views, as there could be configurations sourced from separate parties on the same page.

    E.g. if I could do let scope1 = new rivets(); scoped.formatters.gt = ...

    Is this not possible?

    Maybe if this was possible to configure on the rivets.bind(el, data, ...local config...) ?

    In Handlebars you can do: template({ ..data.. }, { helpers: { gt: (a,b) => a > b })

    opened by sp00x 0
  • rv- breaks if we add to document

    rv- breaks if we add to document

    I have a function that adds stylesheets to the head. After this function is called, all rv- attribute bindings break (such as rv-html, rv-data-*, etc). Regular bindings seem to continue to work ({ data.whatever }). Thoughts? Is there anyway to "reload" these attribute bindings?

    The attribute bindings are on a component that's rendered insite an rv-each, which may be the problem.

    opened by stickboyc 1
  • How to bind the change event of input using lastest rivets

    How to bind the change event of input using lastest rivets

    Consider an example:

    <div>
    <input type="text" id="number_1"/> x <input type="text" id="number_1"/> = <span id="total"></span>
    </div>
    

    When #number_1 textfield is filled in 5 and #number_2 textfield is filled in 2,then #total span will be show 10 automatically. How to do this by rivets (0.9.6),Please display all the code,thanks very much.

    opened by rfrkk 0
Owner
Michael Richards
Michael Richards
Lightweight MVC library for building JavaScript applications

Spine Spine is a lightweight MVC library for building JavaScript web applications. Spine gives you structure and then gets out of your way, allowing y

Spine JS Project 3.6k Jan 4, 2023
Simple, lightweight, persistent two-way databinding

way.js Simple, lightweight, persistent, framework-agnostic two-way databinding Javascript library. With no to little JS code to write. And no dependen

gwendall 2.9k Dec 30, 2022
JavaScript UI library for data-driven web applications

Road to 2.0 The master branch has new, in-progress version of w2ui. You might want to consider 1.5 branch that is stable and supports older browsers.

Vitali Malinouski 2.4k Jan 3, 2023
🌟 DataFormsJS 🌟 A minimal JavaScript Framework and standalone React and Web Components for rapid development of high quality websites and single page applications.

?? Welcome to DataFormsJS! Thanks for visiting! ?? ?? ?? ?? ?? ?? 中文 (简体) 欢迎来到 DataFormsJS Español Bienvenido a DataFormsJS Português (do Brasil) Bem

DataFormsJS 156 Dec 8, 2022
An HTML5/CSS3 framework used at SAPO for fast and efficient website design and prototyping

Welcome to Ink Ink is an interface kit for quick development of web interfaces, simple to use and expand on. It uses a combination of HTML, CSS and Ja

SAPO 1.9k Dec 15, 2022
A framework for real-time applications and REST APIs with JavaScript and TypeScript

A framework for real-time applications and REST APIs with JavaScript and TypeScript Feathers is a lightweight web-framework for creating real-time app

Feathers 14.2k Dec 28, 2022
Functional, simple and customizable UI buttons for react native. Also contains loading functionality and automatically changes color for dual tone buttons. TypeScript support.

React Native UI Buttons ✨ Installation If you want to use icons make sure you have react-native-vector-icons installed in your project. npm install --

Hussain Pettiwala 6 Dec 5, 2022
Give your JS App some Backbone with Models, Views, Collections, and Events

____ __ __ /\ _`\ /\ \ /\ \ __ \ \ \ \ \ __ ___\ \ \/'\\ \ \_

Jeremy Ashkenas 28k Dec 27, 2022
NativeScript empowers you to access native api's from JavaScript directly. Angular, Vue, Svelte, React and you name it compatible.

NativeScript empowers you to access native APIs from JavaScript directly. The framework currently provides iOS and Android runtimes for rich mobile de

NativeScript 22k Jan 4, 2023
Simple and elegant component-based UI library

Simple and elegant component-based UI library Custom components • Concise syntax • Simple API • Tiny Size Riot brings custom components to all modern

Riot.js 14.7k Jan 4, 2023
MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers

Derby The Derby MVC framework makes it easy to write realtime, collaborative applications that run in both Node.js and browsers. Derby includes a powe

DerbyJS 4.7k Dec 31, 2022
The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web.

Bootstrap Sleek, intuitive, and powerful front-end framework for faster and easier web development. Explore Bootstrap docs » Report bug · Request feat

Bootstrap 161.1k Jan 4, 2023
Spaced-repetition: for coders and scientists.

Memcode Flashcards: for coders, mathematicians, and physicists. Open-source, free for all. Made with love ?? Links Site ❤️ : www.memcode.com Patreon:

Evgenia Karunus 231 Dec 30, 2022
A JavaScript implementation of SOM, a minimal Smalltalk for teaching and research.

ohm-som A JavaScript implementation of SOM, a minimal Smalltalk for teaching and research. Just a hobby, won't be big and professional like TruffleSOM

Patrick Dubroy 16 Jun 25, 2021
An open-source, self-hosted, low-code framework to build internal tools, web apps, admin panels, BI dashboards, workflows, and CRUD apps with YAML or JSON.

An open-source, self-hosted, low-code framework to build internal tools, web apps, admin panels, BI dashboards, workflows, and CRUD apps with YAML or JSON.

Lowdefy 2k Jan 4, 2023
Supabase client initialization and encapsulation in fastify framework

fastify-supabase Supabase client initialization and encapsulation in fastify framework. Install Install the package with: npm i fastify-supabase --sav

null 19 Aug 2, 2022
Brail is a framework built on NextJS for developing email templates in React, and returning HTML that is compatible with major email clients.

Brail is a framework built on NextJS for developing email templates in React, and returning HTML that is compatible with major email clients. It aims to seperate the concerns of generating the emails and delivering them.

null 121 Jan 2, 2023
A data-binding function for the DOM.

Alert: this library is now deprecated. s2 is its successor. It implements what simulacra does in a better way (using Proxy), and more. Simulacra.js Si

郑达里 541 Nov 18, 2022
A tiny, SSR-safe directive for binding random data to an element.

1️⃣ vue-bind-once A tiny, SSR-safe directive for binding random data to an element. A tiny, SSR-safe directive for binding random data to an element.

Daniel Roe 113 Jan 8, 2023