jComponent / 06. Scopes
Updated: 21. July 2020
Author: Peter Širka

06. Scopes

Professional Support Chat with contributors

Scopes can simplify paths in HTML declaration. In other words: scopes can reduce paths in all nested components.

Quick navigation:

How does it work?

  • first you need to implement an element with data-scope attribute
  • data-scope can contain path or can be empty
<!-- WITHOUT SCOPE -->
<div>
    <div data---="textbox__users.form.firstname">Name</div>
    <div data---="textbox__users.form.age">Age</div>    
</div>

<!-- WITH SCOPE -->
<div data-scope="users.form">
    <div data---="textbox__?.firstname">Name</div>
    <div data---="textbox__?.age">Age</div>    
</div>

New scopes in +v17

+v17 improves scopes like data-bind. So if you use data-scope attribute then you need to use ? (question mark) in each component where you want to use scope. ? will be replaced for a scope path. Otherwise will be path independent in the component. We recommend to use this declaration.

<div data-scope="users.form">
    <div data---="textbox__?.firstname">Name</div>
    <div data---="textbox__?.age">Age</div>    
</div>

New declaration

<div data-scope="PATH__OPTIONS__DEFAULT_VALUE">

</div>

EXAMPLE:

<div data-scope="users.form__init:users_form_init__{}">
    - method "users_form_init" will be evaluated if the scope will be initialized
    - {} will be a default value for "users.form"
</div>

Options:

  • init:path.to.method evaluates a method when the scope is initialized
  • class:class_name toggles class for the element
  • isolated:true can enable isolated scope (a parent scope path won't be inherited)

Disallow scopes for selected components

IMPORTANT: <= v16 jComponent supports data-jc-noscope="true" attribute which can disallow scope for the component. In +v17 is this attribute deprecated.

<div data-jc-scope="users.form">

    <div data---="textbox__firstname">Name</div>
    <!-- path will be: users.form.firstname -->

    <div data---="textbox__age">Age</div>    
    <!-- path will be: users.form.age -->

    <!-- DISALLOW SCOPE -->
    <div data---="textbox__users.search" data-jc-noscope="true"></div>
    <!-- path will be: users.search -->
    
</div>

Isolated scopes with ! exclamation mark

Independent scopes can rewrite current scope. Independence is enabled by adding exclamation mark ! into the scope path data-scope="!products.form" or you can use option like this data-scope="products.form__isolated:true".

<div data-scope="users.form">

    <div data---="textbox__?.name">Name</div>
    <!-- path will be: users.form.name -->
    
    <!-- Isolated scope -->
    <div data-scope="products.form__isolated:true">
        <div data---="textbox__?.name">Name</div>
        <!-- path will be: products.form.name -->
    </div>

    <!-- Inherited scope -->
    <div data-scope="products.form">
        <div data---="textbox__?.name">Name</div>
        <!-- path will be: users.form.products.form.name -->
    </div>
    
</div>

Anonymous scope with ? question mark

Anonymous scopes are very good option for creating reusable independent web parts, e.g. Contact form, Subscriber form, etc..

  • jComponent generates random path for this scope
  • path will have more than 15 chars
  • path will be stored in window object
  • example: jmhjxgietazasfazfqxqb
<div data-scope="?">

    <div data---="textbox__?.name">Name</div>
    <!-- path will be: random_path.name -->

</div>

<!-- EXAMPLE -->

<div data-scope="?">

    <div data---="textbox__?.name">Name</div>
    <!-- path will be: aoyhdvlmloorhzomzm.name -->

</div>

<div data-scope="?">

    <div data---="textbox__?.name">Name</div>
    <!-- path will be: xsngbvdllnidnaownly.name -->

</div>

How can I obtain anonymous path?

<div data-scope="?__init:scopeinit">
    ...
</div>

<script>
    function scopeinit(path, el) {
    // path {String}
    // el {jQuery Element}

    var scope = el.scope();
    // or
    var scope = this; 

    // scope === Scope object
}
</script>

Scope object

Properties:

path;
// returns {String}
// A scope path

config;
// +v17
// returns {Object}
// A parsed configuration

elements;
// returns {Array of DOM elements}
// All scopes (parent -> children)

isolated;
// returns {Boolean}
// Determines isolated scope

element;
// returns {jQuery element}
// A scope element

Methods:

scope.FIND();
// alias to global method: FIND() but this method finds components in the scope element only

scope.SETTER();
// alias to global method: SETTER() but this method works for components in the scope element only

scope.reset([path], [delay]);
// @path {String} Optional, it's additional path to scope path
// @delay {Number} Optional
// This method performs RESET() for the scope path
// +v18: path can contain "?" which will be replaced with a scope path

scope.default([path], [delay]);
// @path {String} Optional, it's additional path to scope path
// @delay {Number} Optional
// This method performs DEFAULT() for the scope path
// +v18: path can contain "?" which will be replaced with a scope path

scope.set(path, value, [delay], [reset]);
// @path {String} It's additional path to scope path
// @value {Object}
// @delay {Number} Optional
// @reset {Boolean} Optional, performs reset
// This method performs SET() for the scope path
// +v18: path can contain "?" which will be replaced with a scope path

scope.push(path, value, [delay], [reset]);
// @path {String} It's additional path to scope path
// @value {Object}
// @delay {Number} Optional
// @reset {Boolean} Optional, performs reset
// This method performs PUSH() for the scope path
// +v18: path can contain "?" which will be replaced with a scope path

scope.update(path, [delay], [reset]);
// @path {String} It's additional path to scope path
// @delay {Number} Optional
// @reset {Boolean} Optional, performs reset
// This method performs UPDATE() for the scope path
// +v18: path can contain "?" which will be replaced with a scope path

scope.get(path);
// @path {String} It's additional path to scope path
// returns {Object}
// This method performs GET() for the scope path
// +v18: path can contain "?" which will be replaced with a scope path

scope.can([flags]);
// @flags {Array String} Selector flags
// returns {Boolean}
// This method performs CAN() for the scope path
// +v18: path can contain "?" which will be replaced with a scope path

scope.errors([flags], [highlight]);
// @flags {Array String} Selector flags
// @highlight {Boolean} Highlight invalid components
// returns {Array jComponents}
// This method performs ERRORS() for the scope path
// +v18: path can contain "?" which will be replaced with a scope path

// SELECTOR FLAGS:
// @hidden - jComponent finds all hidden components
// @visible - jComponent finds all visible components
// @disabled - jComponent finds all components which have disabled inputs
// @enabled - jComponent finds all components which have enabled inputs

Special usage with ? question mark

Scopes supports one more thing. If the component path will contain ? question mark in the path then the scope replaces this ? mark with the current scope path.

<div data-scope="users">

    <div data---="textbox__address.?.street">Street</div>
    <!-- path will be: address.users.street -->

</div>

Skip parent scopes

+v17 this behaviour is targeted for special cases. You can skip parent scopes in the form ?COUNT_OF_SKIP, the example below describes more:

<div data-scope="level1">
    <div data-scope="level2">
        <div data-scope="level3">
            
            <div data-bind="?.name"></div>
            <!-- Path will be decoded as: level1.level2.level3.name -->

            <div data-bind="?1.name"></div>
            <!-- Path will be decoded as: level1.level2.name -->

            <div data-bind="?2.name"></div>
            <!-- Path will be decoded as: level1.name -->

        </div>
    </div>

</div>

Good to know

  • IMPORTANT: scope must contain some jComponent
  • scopes need to be declared in HTML directly
  • scopes can have nested scopes
  • jComponent contains a list of used scopes in component.scope property
  • scope DOM element contains the whole path stored in element.$scopedata property
  • obtaining scope with help of jQuery: $('selector').scope() returns a scope instance