Declarative API Reference
The Declarative API lets you link HTML elements to NExS app cells using CSS classes and data attributes—no JavaScript required.
Overview
Add specific class names and a data-nexs-cell-addr attribute to HTML elements to create automatic two-way binding with your NExS app cells.
Input Elements
Class: nexs__input
Links an input element to an editable cell. Changes flow both directions:
- User edits the HTML input → value sent to NExS cell
- NExS cell changes → HTML input updates
Supported Input Types
Text Input
<input type="text"
class="nexs__input"
data-nexs-cell-addr="B5">
Checkbox
<input type="checkbox"
class="nexs__input"
data-nexs-cell-addr="C3">
- Checked = sends
1to cell - Unchecked = sends
0to cell
Radio Buttons
<input type="radio" name="plan" class="nexs__input"
data-nexs-cell-addr="B8" value="Basic"> Basic
<input type="radio" name="plan" class="nexs__input"
data-nexs-cell-addr="B8" value="Premium"> Premium
<input type="radio" name="plan" class="nexs__input"
data-nexs-cell-addr="B8" value="Enterprise"> Enterprise
All radio buttons in a group share the same data-nexs-cell-addr. The selected button’s value is sent to the cell.
Select (Dropdown)
<select class="nexs__input" data-nexs-cell-addr="D2">
<option value="Option A">Option A</option>
<option value="Option B">Option B</option>
<option value="Option C">Option C</option>
</select>
The selected option’s value is sent to the cell.
Output Elements
Class: nexs__output_formatted
Displays the cell’s formatted value (as shown in Excel).
<span class="nexs__output_formatted"
data-nexs-cell-addr="B10"></span>
If cell B10 contains 1234.56 formatted as currency, displays: $1,234.56
Class: nexs__output_raw
Displays the cell’s raw value (unformatted).
<span class="nexs__output_raw"
data-nexs-cell-addr="B10"></span>
If cell B10 contains 1234.56 formatted as currency, displays: 1234.56
Comparison
| Cell Value | Format | nexs__output_formatted |
nexs__output_raw |
|---|---|---|---|
| 1234.56 | Currency | $1,234.56 | 1234.56 |
| 0.15 | Percentage | 15% | 0.15 |
| 44927 | Date | 1/15/2023 | 44927 |
| Hello | Text | Hello | Hello |
The _raw and _formatted classes only differ for numeric values. Text cells display the same in both.
View Selector
Class: nexs__viewselect
Creates a dropdown that switches between views.
<select class="nexs__viewselect"></select>
The dropdown automatically populates with your app’s view names.
Multiple Apps
For pages with multiple embedded apps, specify which app:
<!-- View selector for second app (index 1) -->
<select class="nexs__viewselect" data-nexs-app="1"></select>
<!-- View selector for app named "My App" -->
<select class="nexs__viewselect" data-nexs-app="My App"></select>
Cell Address Syntax
The data-nexs-cell-addr attribute uses the extended cell reference syntax: [appRef]viewRef!cellRef
Components
| Component | Description | Examples |
|---|---|---|
appRef |
App name or index | [My App], [0], [1] |
viewRef |
View name or index | Dashboard, 0, 1 |
cellRef |
Cell address or name | B7, Input_1 |
Default Values
- If
appRefis omitted, defaults to first app ([0]) - If
viewRefis omitted, defaults to first view (0)
Examples
| Address | Meaning |
|---|---|
B5 |
Cell B5 on first view of first app |
Dashboard!B5 |
Cell B5 on “Dashboard” view of first app |
[My App]Dashboard!B5 |
Cell B5 on “Dashboard” view of “My App” |
[1]B5 |
Cell B5 on first view of second app |
[0]2!B5 |
Cell B5 on third view of first app |
Input_1 |
Named cell “Input_1” on first view of first app |
[My App]Settings!Config |
Named cell “Config” on “Settings” view of “My App” |
Complete Example
This mortgage calculator is a custom page built entirely with the Declarative API. It runs against a published NExS app built from a mortgage analysis spreadsheet. Download the spreadsheet to see how it works, or open the Mortgage Calculator app in a new window to compare it with the original spreadsheet view.
The spreadsheet’s inputs are in Sheet1!C7:C19, and its NExS.app worksheet makes them editable:
| A | B | C | |
|---|---|---|---|
| 1 | app | Mortgage Calculator | |
| 2 | view | Sheet1!B2:K23 | |
| 3 | name | Main | |
| 4 | input | C7:C10 | |
| 5 | input | C15:C19 | |
| 6 | end |
The custom page binds to these cells:
| Cell | Contents | Bound to |
|---|---|---|
| C7 | Mortgage term (years) | Radio buttons, one shared cell |
| C8 | Rate | Text input |
| C9 | Purchase price | Text input |
| C10 | Down payment | Text input |
| C15 | Additional principal (monthly) | Text input |
| C16 | Marginal tax bracket | Select |
| C17 | Annual appreciation | Text input |
| C18 | Insurance (annual) | Text input |
| C19 | Property tax rate | Text input |
| C11, C12 | Loan amount, monthly payment | nexs__output_formatted |
| F17:K17 | Cash out, tax savings, net cost, loan balance, property value, and equity after 10 years | nexs__output_formatted |
On their own, nexs__input text inputs show the cell’s raw value, so the rate would appear as 0.04 and the purchase price as 500000. A short nexsappupdated listener replaces them with the cell’s formatted text (4.000%, $500,000) after every update. It skips the input the user is typing in. Formatted values are safe to send back, because text inputs accept the same entries as the spreadsheet cell. Type rates with a percent sign (6.5%), because a plain 6.5 would be read as 650%.
Try It
Mortgage Calculator
After 10 Years
The Code
<!DOCTYPE html>
<html lang="en">
<head>
<title>Mortgage Calculator</title>
<style>
.calculator {
font-family: Arial, sans-serif;
max-width: 560px;
margin: 20px auto;
padding: 24px;
border: 1px solid #ddd;
border-radius: 8px;
}
.fields {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0 16px;
}
.field {
margin-bottom: 15px;
}
.field-label {
display: block;
font-weight: bold;
margin-bottom: 5px;
}
.field input[type="text"], .field select {
width: 100%;
padding: 8px;
font-size: 16px;
box-sizing: border-box;
}
.radio-row {
display: flex;
gap: 16px;
padding: 8px 0;
}
.result {
background: #f0f8ff;
padding: 15px;
border-radius: 4px;
text-align: center;
}
.result .amount {
font-size: 32px;
font-weight: bold;
color: #2a7;
}
.summary {
margin-top: 15px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px 16px;
}
.summary h4 {
grid-column: 1 / -1;
margin: 0;
}
.summary div {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #eee;
}
</style>
</head>
<body>
<div class="calculator">
<h2>Mortgage Calculator</h2>
<div class="fields">
<!-- Text inputs -->
<div class="field">
<label class="field-label" for="price">Purchase Price</label>
<input type="text" id="price"
class="nexs__input"
data-nexs-cell-addr="C9"
placeholder="$500,000">
</div>
<div class="field">
<label class="field-label" for="down">Down Payment</label>
<input type="text" id="down"
class="nexs__input"
data-nexs-cell-addr="C10"
placeholder="$200,000">
</div>
<div class="field">
<label class="field-label" for="rate">Interest Rate (e.g. 6.5%)</label>
<input type="text" id="rate"
class="nexs__input"
data-nexs-cell-addr="C8"
placeholder="6.5%">
</div>
<div class="field">
<label class="field-label" for="extra">Extra Principal / Month</label>
<input type="text" id="extra"
class="nexs__input"
data-nexs-cell-addr="C15"
placeholder="$0">
</div>
<!-- Radio buttons: all share cell C7, and the selected value is sent -->
<div class="field">
<span class="field-label">Loan Term (years)</span>
<div class="radio-row">
<label>
<input type="radio" name="term" class="nexs__input"
data-nexs-cell-addr="C7" value="15"> 15
</label>
<label>
<input type="radio" name="term" class="nexs__input"
data-nexs-cell-addr="C7" value="20"> 20
</label>
<label>
<input type="radio" name="term" class="nexs__input"
data-nexs-cell-addr="C7" value="30" checked> 30
</label>
</div>
</div>
<!-- Select: the option's value is sent, its text is what users see -->
<div class="field">
<label class="field-label" for="tax">Tax Bracket</label>
<select id="tax" class="nexs__input" data-nexs-cell-addr="C16">
<option value="0.1">10%</option>
<option value="0.12">12%</option>
<option value="0.22">22%</option>
<option value="0.24" selected>24%</option>
<option value="0.32">32%</option>
<option value="0.35">35%</option>
<option value="0.37">37%</option>
</select>
</div>
<div class="field">
<label class="field-label" for="appreciation">Annual Appreciation</label>
<input type="text" id="appreciation"
class="nexs__input"
data-nexs-cell-addr="C17"
placeholder="3%">
</div>
<div class="field">
<label class="field-label" for="insurance">Insurance / Year</label>
<input type="text" id="insurance"
class="nexs__input"
data-nexs-cell-addr="C18"
placeholder="$5,000">
</div>
<div class="field">
<label class="field-label" for="proptax">Property Tax Rate</label>
<input type="text" id="proptax"
class="nexs__input"
data-nexs-cell-addr="C19"
placeholder="0.5%">
</div>
</div>
<!-- Outputs -->
<div class="result">
<div>Monthly Payment</div>
<div class="amount">
<span class="nexs__output_formatted" data-nexs-cell-addr="C12"></span>
</div>
<div>on a loan of
<span class="nexs__output_formatted" data-nexs-cell-addr="C11"></span>
</div>
</div>
<div class="summary">
<h4>After 10 Years</h4>
<div>Cash out
<span class="nexs__output_formatted" data-nexs-cell-addr="F17"></span></div>
<div>Tax savings
<span class="nexs__output_formatted" data-nexs-cell-addr="G17"></span></div>
<div>Net cost
<span class="nexs__output_formatted" data-nexs-cell-addr="H17"></span></div>
<div>Loan balance
<span class="nexs__output_formatted" data-nexs-cell-addr="I17"></span></div>
<div>Property value
<span class="nexs__output_formatted" data-nexs-cell-addr="J17"></span></div>
<div>Equity
<span class="nexs__output_formatted" data-nexs-cell-addr="K17"></span></div>
</div>
</div>
<!-- NExS app (handles calculations), hidden so only the custom UI shows -->
<div style="display:none;">
<!-- Replace this UUID with your own app's ID if building from scratch -->
<script class="nexs"
src="https://static.nexs.com/js/nexs_embed.js"
data-nexs-app-url="https://platform.nexs.com/app/ec7dcdee-dcea-4032-94ba-16782c9a1036">
</script>
</div>
<script>
// Text inputs receive the cell's raw value (0.04, 500000). After each
// update, show the formatted text instead (4.000%, $500,000), except
// in the input the user is currently editing.
document.addEventListener('nexsappupdated', () => {
document.querySelectorAll('input[type="text"].nexs__input').forEach(input => {
if (input !== document.activeElement) {
input.value = NEXS.cell(input.dataset.nexsCellAddr).text.trim();
}
});
});
</script>
</body>
</html>
Every input and output is wired up by its class and data-nexs-cell-addr alone. The only JavaScript is the optional listener that formats the text inputs.
Tips
Hiding the NExS App
If you’re building a fully custom UI and don’t want the spreadsheet view visible, you can hide the embed container with CSS:
<div style="display:none;">
<script class="nexs"
src="https://static.nexs.com/js/nexs_embed.js"
data-nexs-app-url="https://platform.nexs.com/app/YOUR-APP-ID">
</script>
</div>
The Declarative API elements will still work even when the app view is hidden.
Combining with JavaScript
The Declarative API works alongside the JavaScript API. Use declarative binding for simple cases and JavaScript for complex logic:
<input type="text" class="nexs__input" data-nexs-cell-addr="B5">
<script>
document.addEventListener("nexsappupdated", function() {
// React to changes with JavaScript
const value = NEXS.cell("B10").data;
if (value > 1000) {
alert("High value detected!");
}
});
</script>
Multiple Apps
When embedding multiple apps, always specify the app reference:
<!-- Inputs for first app -->
<input class="nexs__input" data-nexs-cell-addr="[0]B5">
<!-- Inputs for second app -->
<input class="nexs__input" data-nexs-cell-addr="[1]B5">
<!-- View selector for second app -->
<select class="nexs__viewselect" data-nexs-app="1"></select>
Related
- JavaScript API — Programmatic control
- Events Reference — React to app changes
- Embedding Basics — Getting started guide
