# Formulas

A Formula property computes its value from the page's other properties. The formula is a small JavaScript function in the collection's code. You don't need the rest of the plugin API to write one.

## Add a formula

1. In **Collection Settings...**, add a property of type **Formula**. Call it Total.
2. Add the inputs it needs, say Number properties Hours and Rate.
3. Choose **Edit formula in Code Editor** on the Formula property.
4. Register the calculation in `onLoad()`:

```javascript
class Plugin extends CollectionPlugin {
    onLoad() {
        this.properties.formula("Total", ({record}) => {
            const hours = record.number("Hours");
            const rate = record.number("Rate");
            if (hours == null || rate == null) return null;
            return hours * rate;
        });
    }
}
```

Preview, check a page with values, one without, and one with zero, then save. If the collection already has code, add the `formula` call to its existing `onLoad()` instead of replacing the class.

## Writing them

Return `null` when there is no sensible answer, so an empty input stays empty instead of becoming zero. Formulas run every time a row is drawn, so keep them quick: read the properties you need and return a value, without network requests or writes.

Readers: `record.number()`, `record.text()`, `record.choice()`, `record.users()`, `record.linkedRecord()` and `record.linkedRecords()`. A choice comes back as its id; `PluginProperty.choiceLabel()` gives the label.

## Two more examples

A progress percentage from two numbers:

```javascript
this.properties.formula("Progress", ({record}) => {
    const done = record.number("Completed");
    const planned = record.number("Planned");
    if (done == null || planned == null || planned <= 0) return null;
    return Math.round(100 * done / planned);
});
```

The number of linked projects, from a multi-value Page Link, which is how you build a rollup:

```javascript
this.properties.formula("Project count", ({record}) => {
    return record.linkedRecords("Projects").length;
});
```

For custom rendering, sorting and views, continue with [Collection plugins](../plugins/collection-plugins.md).
