Defining Default Style

Normally you define styles globally in your application. But some components may require some styling (e.g. particular layout) that is specific for their operation.

Reactor (Sciter internal code in fact) offers simple way to define component styles using styleset class property in the form ["stylesetname", "file.css"]

Let's redefine our Clock class that we used earlier :

include "sciter:reactor.tis";

class Clock: Reactor.Component 
{
  const styleset = ["clock", $url(clock.css)]; // style set declaration

  this var data = { time: new Date() }; // setting initial state 

  function attached() { // a.k.a. React::componentDidMount
    this.timer(1s, function() {
      this.update { time:new Date() };
      return true; // to keep the timer ticking
    });
  }

  function render() {
    return
     <clock>
      <div.greeting>Hello, world!</div>
      <div>It is {this.data.time.toLocaleString(#time)} now.</div>
     </clock>;
  } 
}

Where $url() is a stringizer function that resolves its textual argument to absolute URL using this script file loaction as a base.

And here is a content of clock.css file: 

@set clock 
{
  :root {
    display: block;
    flow:vertical;
  }
  span.time { 
    display:inline-block; 
    white-space:nowrap; 
  }
}

Check sample: {sdk}/samples/+reactor/doc-samples/styles-events/clock.htm

As you see it defines independent set of CSS rules that define content (and only content) of our clock component and its internals.

General consideration: if component is designed to be used in many applications then its default style set should include only rules needed for layout and those are critical for operation. Each application will add its own styling on top of these default styles.  

Note that style sets in Sciter are not polluting global list of style rules and so are very effective - reduce time needed for style resolution of DOM elements. 

Event Handling in Components

In contrast with ReactJS Sciter does not require any special constructs for handling events - we can use normal (for the Sciter) event handling definitions in classes.

Sample of small component that encapsulates search block enclosing <input> and <button> in one entity:   

class Search : Reactor.Component {

  this var elInput;

  function render() {
    return <search>
        <input|text @(this.elInput) />
        <button.do/>
    </search>;
  }

  event click $(button.do) { 
    this.postEvent("do-search", this.elInput.value ); 
  }
  event change $(input) { 
    this.showSuggestionsFor( this.elInput.value ); 
  }

  property value(v) 
  {
     get return this.elInput.value;
     set this.elInput.value = v;
  }
}

In this example we are handling two events: click on the button and change of the input. Nothing is really new here.

HTML Resident Mounting Points

Reactor Components are executable entities even if they look as HTML.

Normally in ReactJS you see JSX code only inside <script> sections and JS code files. Example that we saw before already:

function App() {
  return
    <main>
       <Welcome name="Ivan" />
       <Welcome name="Olga" />
       <Welcome name="Andrew" />
    </main>;
}

$(main).merge( <App /> );

While this works in general it may look non-natural or inconvenient to someone. 

Alternatively Sciter offers special <reactor> HTML element as a mounting point:

<body>
   <p>Test of &lt;Tabs> component.</p>
      
   <reactor(Tabs) src="tabs.tis">
     <tab(first) label="First tab">First tab content</tab>
     <tab(second) label="Second tab">Second tab content</tab>
     <tab(third) label="Third tab" src="tab-content.htm"></tab>
   </reactor>

</body>

The <reactor> element expects two attributes:

Please note that, while it looks like HTML, content between <reactor> and </reactor> is parsed by script rules (SSX in this case). Essentially you may think as the whole <reactor> section is just <script> element:

<body>
   <p>Test of &lt;Tabs> component.</p>
      
   <script type="text/tiscript+ssx" component="Tabs" src="tabs.tis">
     <tab(first) label="First tab">First tab content</tab>
     <tab(second) label="Second tab">Second tab content</tab>
     <tab(third) label="Third tab" src="tab-content.htm"></tab>
   </script>

</body>

The only major difference of the <reactor>: it is a placeholder element - as soon as component gets instantiated it replaces the <reactor> DOM element. Therefore final DOM after <reactor>'s execution will look like:

<body>
   <p>Test of &lt;Tabs> component.</p>
      
   <tabs>
     <tab(first) label="First tab">First tab content</tab>
     <tab(second) label="Second tab">Second tab content</tab>
     <tab(third) label="Third tab" src="tab-content.htm"></tab>
   </tabs>

</body>

Check sample at {sdk}/samples/+reactor/components/tabs/test.htm