Now.js Framework Documentation

Now.js Framework Documentation

Scope Isolation - Data Context Separation

EN 12 Feb 2026 04:01

Scope Isolation - Data Context Separation

Overview

To prevent conflicts when multiple systems try to process the same data-* directives, Now.js uses a Scope Isolation system.

Problem Solved

When multiple systems work with data-attr, data-text, etc. simultaneously:

<!-- ❌ Problem: Both AppConfigManager and FormManager try to process data-attr="value:company" -->
<form data-load-api="/api/user/profile">
  <input name="company" data-attr="value:company">
  <!-- AppConfigManager: company = "Global Company" from config API -->
  <!-- FormManager: company = "User Company" from user profile API -->
  <!-- Result: Unpredictable value, depends on which system runs last -->
</form>

Solution: Automatic Scope Isolation

1. AppConfigManager Skips Elements in Isolated Scopes

AppConfigManager will NOT process data-* directives inside:

[data-component="api"] - ApiComponent

<div data-component="api" data-api-url="/api/products">
  <span data-text="name">Product Name</span>
  <!-- AppConfigManager won't touch this element -->
  <!-- ApiComponent manages it -->
</div>

form[data-load-api] - FormManager with API Loading

<form data-load-api="/api/user/profile">
  <input name="company" data-attr="value:company">
  <!-- AppConfigManager won't touch this element -->
  <!-- FormManager manages it -->
</form>

[data-load-api] - Any Container with API Loading

<div data-load-api="/api/dashboard/stats">
  <span data-text="totalUsers">Loading...</span>
  <!-- AppConfigManager won't touch this element -->
  <!-- Container manages its own data loading -->
</div>

2. AppConfigManager Only Processes Global Elements

<!-- ✅ AppConfigManager WILL process these -->
<header>
  <span data-text="company">My Company</span>
  <img data-attr="src:logo" alt="Logo">
</header>

<footer>
  <p data-text="copyright"></p>
  <span data-text="version"></span>
</footer>

Usage Guidelines

1. Global Configuration Data (AppConfigManager)

Use for data shared across the entire application:

<nav>
  <div class="brand">
    <img data-attr="src:logo" alt="Logo">
    <span data-text="company">Company Name</span>
  </div>
</nav>

<footer>
  <p data-text="copyright">© 2024 Company</p>
</footer>
// API: /api/config
{
  "company": "My Company Ltd.",
  "logo": "/images/logo.png",
  "copyright": "© 2024 My Company Ltd.",
  "variables": {
    "--color-primary": "#29336b"
  }
}

2. Form-Specific Data (FormManager)

Use for form-specific data:

<form data-load-api="/api/user/profile">
  <input type="text" name="name" data-attr="value:name">
  <input type="email" name="email" data-attr="value:email">
  <select name="company_id" data-attr="value:company_id">
    <!-- Options loaded from data-options-api -->
  </select>
</form>
// API: /api/user/profile
{
  "data": {
    "name": "John Doe",
    "email": "john@example.com",
    "company_id": "123"
  }
}

3. Component-Specific Data (ApiComponent)

Use for components that load their own data:

<div data-component="api" data-api-url="/api/products">
  <div data-for="item in items">
    <h3 data-text="item.name">Product</h3>
    <p data-text="item.price">Price</p>
  </div>
</div>

Best Practices

✅ Correct

<!-- Global config uses AppConfigManager -->
<header>
  <span data-text="siteName">Site Name</span>
</header>

<!-- Form data uses FormManager -->
<form data-load-api="/api/user/profile">
  <input name="username" data-attr="value:username">
</form>

❌ Avoid

<!-- Don't use the same name in global and form scope -->
<header>
  <span data-text="name">Global Name</span>
</header>

<form data-load-api="/api/user">
  <input name="name" data-attr="value:name">
  <!-- Confusing: which API does "name" come from? -->
</form>

Debug Mode

Enable debug to see which elements are skipped:

Now.config.debug = true;

Console will show:

[AppConfigManager] Skipped 5 elements in isolated scopes: [input, input, select, ...]

Checking Scope

Use helper method to check if an element is in isolated scope:

const element = document.querySelector('input[name="company"]');
const isIsolated = AppConfigManager.isInIsolatedScope(element);

console.log(isIsolated);
// true = inside form[data-load-api] or [data-component="api"]
// false = AppConfigManager will process

Summary

Scope Attribute Managed By Use Case
Global None AppConfigManager Data shared across the app
Form form[data-load-api] FormManager Form-specific data
Component [data-component="api"] ApiComponent Component that loads its own data
Container [data-load-api] Custom Container that loads its own data

Principle: Each scope manages its own data without interfering with others