This app was created with "create-sprout-app"

Here are examples for some of Sprout app features:

Dynamic text content

The app was built using the debug option --allowAppScopeAccess
allowing you to access the global State object of the app via the console
To see reactivity in action:

Open the console.
Type: const state = sproutApps.sprout_demo_app.getGlobalState()
state variable now contains the global state object.
Type: state.dynamicText = "Hello dynamic text!". Click enter, and watch how the text above automagically change.

This input field is bound to the 'dynamicText' state value. Start writing text in it, to see the dynamic text above changes accordingly:


// html
<div is="reactive-div" _text="dynamicText">
    <counter-button></counter-button>
</div>
<input id="dynamicInput" is="reactive-input" _bind="value:dynamicText" />

// counter-button template.html
<button is="reactive-button" ref="btn-counter">Increase Counter</button>

// counter-button runtime.js
export default {
    events: {
        "btn-counter": function(event, host, global) {
            global.counter++;
        }
    }
}

// Global index.js
const initState = {
    counter: 0,
    set_dynamicText: [function() { 
        return `This text is dynamic! \n It is bound to the 'dynamicText' State property.
        It can even use template strings, referencing another State value in them,
        like this counter: \n ${this.counter} \n`;
    }, ["counter"], true],
    list: [
        { key: 0 },
        { key: 2 },
        { key: 3 },

    ],
    isHidden: true,
}
this.setGlobalState(initState);
            

Mapping State Arrays to Lists of Custom Components

The following div has a "_map" command that maps an array of State objects to <list-item> custom components:


// html
<div is="reactive-div" _map="list:list-item"></div>

// global index.js
const initState = {
    counter: 0,
    set_dynamicText: [function() { 
        return `This text is dynamic! \n It is bound to the 'dynamicText' State property.
        It can even use template strings, referencing another State value in them,
        like this counter: \n ${this.counter} \n`;
    }, ["counter"], true],
    list: [
        { key: 0 },
        { key: 2 },
        { key: 3 },

    ],
    isHidden: true,
}
this.setGlobalState(initState);
            

State Attributes

There is a hidden div here, with its hidden attribute bound to an isHidden State value. Click the button to toggle that state.


//html 
<div is="reactive-div" hidden="$isHidden">This was hidden!</div>
<show-hide></show-hide>

// show-hide template.html
<button is="reactive-button" ref="show-hide-btn">
    <span is="reactive-span" hidden="$!isHidden">Show</span>
    <span is="reactive-span" hidden="$isHidden">Hide</span>
    </button>

// show-hide runtime.js
export default {
    events: {
        "show-hide-btn": function(event, host, global) {
            global.isHidden = global.isHidden ? false : true
        }
    }
}
            

Conditional Rendering, Custom Properties

Conditional rendering allows you to render elements according to a state conditions

There is a <conditional-render> element here, with conditions related to the value of the same counter from above.

Try to increase or decrease the counter, see what happens when it becomes 10, see what happens when it's higher than 10

The two buttons below are instances of the same component, customizable by a type property

The counter value is:

// html
<counter-button type="increase"></counter-button>
<counter-button type="decrease"></counter-button>
<conditional-demo></conditional-demo>

// conditional-demo: template.html
<div class="framed">
    <conditional-render _condition="counter">
        <div _if="<10">This is only shown if the counter is smaller than 10</div>
        <div _if="10">This is only shown if the counter is exactly equal to 10</div>
        <div _if=">10">This is only shown if the counter is higher than 10</div>
        <div>This is always shown</div>
    </conditional-render>
</div>