Previously, when there was a reactive object in the prototype chain of a different object, it would get notified of the first write to a property that existed on the reactive object but did not yet exist on the other object, despite the value of that property not actually getting written to the reactive and hence the value not getting changed. This was caused by the fact that we assumed that Reflect.set would set the value on the target, when in fact, the value is set on the object that underlies the `receiver`. When a reactive object is part of the prototype chain, the first write on a key triggers the set trap but the receiver is not the reactive object, and so Reflect.set doesn't modify the target, but adds the new key to the object that's lower in the prototype chain. This commit fixes that by actually reading the value from the target instead of assuming that it was changed by Reflect.set This commit also removes the special symbols SKIP and TARGET, as there is no reliable way to check whether these keys are present on the object itself or on its prototype chain, which can cause issue when trying to create reactive objects from objects with other reactive objects in their prototype chain, or to create reactive objects from objects with non-reactive objects in their prototype chain. To solve this problem, we simply use a WeakMap that maps reactives to their targets, and a WeakSet that contains all skipped objects.
🦉 Owl Framework 🦉
Class based components with hooks, reactive state and concurrent mode
Try it online! you can experiment with the Owl framework in an online playground.
Project Overview
The Odoo Web Library (Owl) is a smallish (~<20kb gzipped) UI framework built by Odoo for its products. Owl is a modern framework, written in Typescript, taking the best ideas from React and Vue in a simple and consistent way. Owl's main features are:
- a declarative component system,
- a fine grained reactivity system similar to Vue,
- hooks
- fragments
- asynchronous rendering
Owl components are defined with ES6 classes and xml templates, uses an underlying virtual DOM, integrates beautifully with hooks, and the rendering is asynchronous.
Quick links:
- documentation,
- changelog (from Owl 1.x to 2.x),
- playground
Example
Here is a short example to illustrate interactive components:
const { Component, useState, mount, xml } = owl;
class Counter extends Component {
static template = xml`
<button t-on-click="() => state.value = state.value + props.increment">
Click Me! [<t t-esc="state.value"/>]
</button>`;
state = useState({ value: 0 });
}
class Root extends Component {
static template = xml`
<span>Hello Owl</span>
<Counter increment="2"/>`;
static components = { Counter };
}
mount(Root, document.body);
Note that the counter component is made reactive with the useState hook.
Also, all examples here uses the xml helper to define inline templates.
But this is not mandatory, many applications will load templates separately.
More interesting examples can be found on the playground application.
Documentation
Learning Owl
Are you new to Owl? This is the place to start!
Reference
- Overview
- App
- Component
- Component Lifecycle
- Concurrency Model
- Dev mode
- Dynamic sub components
- Environment
- Error Handling
- Event Handling
- Form Input Bindings
- Fragments
- Hooks
- Loading Templates
- Mounting a component
- Portal
- Precompiling templates
- Props
- Props Validation
- Reactivity
- Rendering SVG
- Refs
- Slots
- Sub components
- Sub templates
- Templates (Qweb)
- Translations
- Utils
Other Topics
- Notes On Owl Architecture
- Comparison with React/Vue
- Why did Odoo build Owl?
- Changelog (from owl 1.x to 2.x)
- Notes on compiled templates
Installing Owl
Owl is available on npm and can be installed with the following command:
npm install @odoo/owl
If you want to use a simple <script> tag, the last release can be downloaded here: