habame v1.0.41
Habame
Habame is a frontend javascript framework to build user interface
Create a component
const App = Habame.createComponent('App', function() {
    // Define your component states, actions, event and others here
}, `<div>Welcome to Habame</div>`);Render a component
const root = Habame.createRoot(document.getElementById('app'));
root.render(App);
// or
root.render('App'); Create an action and call it
const App = Habame.createComponent('App', function({ Actions }) {
    Actions.callMeWithEvent = function($event) {
        alert('Hello '+ $event.target.getAttribute('name') +'!');
    };
    Actions.callMeWithValue = function(name) {
        alert('Hello '+ name +' !');
    };
},
`
    <div>
        <div><button events.click="callMeWithEvent" name = "Afeinclan" >Call me!</button></div>
        <br/>
        <div><button events.click="callMeWithValue($event.target.getAttribute('name'))" name = "PrinceMo" >Hey dude!</button></div>
        <br/>
        <div><button events.click="callMeWithEvent($event)" name = "Sarkodie" >Finish here!</button></div>
    </div>
`);Create and update state in component
const App = Habame.createComponent('App', function({ State, Actions }) {
    State.init({ value: 0, square: 0 });
    Actions.setValue = function(event) {
        State.value = Number(event.target.value);
        State.square = State.value * State.value;
    };
}, 
`
    <div>
        <div>
            <input type="number" events.input="setValue" />
        </div>
        <br/>
        <div>The square of {{ value }} is {{ square }}</div>
    </div>
`);Work with props
by default props are send to component but it doesn't affect the component state
const App = Habame.createComponent('App', function({ State, Actions }) {
    State.init({ nbClick: 0 });
    Actions.clickMe = function() {
        State.nbClick++;
    }
},
`
    <div>
        <NbClick props.count = "nbClick" />
        <button events.click = "clickMe" >Click</button>
    </div>
`);
const root = Habame.createRoot(document.getElementById('app'));
root.render(App);- In this case, count will empty and will never update
    Habame.createComponent('NbClick', function() {}, `<div >You click {{ count }} time.s</div>`);- Will show the first value captured, but will never update the state when the props will be update
    Habame.createComponent('NbClick', function({ State, Props }) {
        State.add('count', Props.count);
    }, `<div >You click {{ count }} time.s</div>`);- Chose the moment you want to update your component state
    Habame.createComponent('NbClick', function({ State, Props }) {
        State.add('count', Props.count);
        Props.onUpdate('count', (value) => {
            if(value % 2 === 0) {
                State.count = value;
            }
        });
    }, `<div >You click {{ count }} time.s</div>`);- Full Synchronisation with props, will automatically add and update your state when the props will be updated
    Habame.createComponent('NbClick', function({ State, Props }) {
        State.useProps(Props);
        // State.useProps(Props, ['count']); // chose only props to synchronise automatically
    }, `<div >You click {{ count }} time.s</div>`);Events
use HbEvent to make a communication between parent and child component
Habame.createComponent('CustomCountButton', function({ HbEvent, Actions }) {
    const onClick = HbEvent.create('onClick');
    Actions.emitTheClick = function() {
        onClick.emit();
    };
},
`
    <button events.click="emitTheClick" >Click me!</button>
`);
const App = Habame.createComponent('App', function({ State, Actions }) {
    State.init({
        count: 0
    });
    Actions.eventFromChild = function() {
        State.count++;
    };
},
`
    <div>
        {{ count }} nb click
        <br/><br/>
        <CustomCountButton events.onClick="eventFromChild" />
    </div>
`);Element Reference
Reference will allow you to get element from view (html element or component)
- get html element
const App = Habame.createComponent('App', function({ State, Actions, Refs }) {
    State.init({ value: 0, square: 0 });
    Actions.calculate = function() {
        const target = Refs.input.target();
        State.value = Number(target.value);
        State.square = State.value * State.value;
    };
},
`
    <div>
        <div>
            <input type="number" ref="input" /> <button events.click="calculate">Calculate</button>
        </div>
        <br/>
        <div>The square of {{ value }} is {{ square }}</div>
    </div>
`);- get component In this case, you could call the public function of component if available
Habame.createComponent('SwitchButton', function({ State }) {
    State.init({ isOn: false });
    return { // public functions for parent component
        toggle: () => {
            State.isOn = !State.isOn;
        }
    };
},
`
    <div >{{ isOn ? 'Button is on' : 'Button is off' }}</div>
`);
const App = Habame.createComponent('App', function({ Actions, Refs }) {
    Actions.togglePlayer = function() {
        const switchButton = Refs.switchButton.target();
        switchButton.toggle();
    };
},
`
    <div>
        <SwitchButton ref="switchButton" />
        <br/>
        <div>
            <button events.click = 'togglePlayer' >Toggle</button>
        </div>
    </div>
`);- collection of ref
collection of ref work only for loop context, refandrepeatmust be define the same tag
const App = Habame.createComponent('App', function({ Actions, Refs }) {
    Actions.togglePlayer = function() {
        Refs.switchButton.each((button) => {
            button.target().toggle();
        });
    };
},
`
    <div>
        <SwitchButton ref="switchButton" repeat="element in 1..3" />
        <br/>
        <div>
            <button events.click = 'togglePlayer' >Toggle</button>
        </div>
    </div>
`);Work with Loop
- use repeat with inorasStart..NbElements
const App = Habame.createComponent('App', function() {},
`
    <div>
        <div repeat="index in 5..3" >
            the index is {{ index }}
        </div>
        <br/>
        <div repeat="index, value in 5..3" >
            the value at  {{ index }} is {{ value}}
        </div>
        <br/>
        <div repeat="5..3 as (index, value)" >
            the value at  {{ index }} is {{ value}}
        </div>
        <br/>
        <div repeat="5..3 as value" >
            the value at  {{ index }} is {{ value}} <!-- index will be automatically available -->
        </div>
    </div>
`);- use repeat with inorasanditerable- index in iterable
- (index, value) in iterable
- iterable as value
- iterable as (index, value)
 
const App = Habame.createComponent('App', function({ State, Actions, Refs }) {
    State.add('products', []);
    Actions.addProduct = function() {
        const target = Refs.input.target();
        State.products.push(target.value);
        target.value = '';
        target.focus();
    };
},
`
    <div>
        <ul>
            <li repeat="products as product" >
                {{ product }}
            </li>
        </ul>
        <br/>
        <input type="text" ref="input" /> <button events.click = "addProduct" >Add +</button>
    </div>
`);If control structure
will allow you to easly show or display component or html element
const App = Habame.createComponent('App', function({ State, Actions }) {
    State.add('pill', '');
    Actions.chosePill = function($event) {
        State.pill = $event.target.value;
    };
},
`
    <div>
        <div>Chose your pill</div>
        <div>
            <label >
                <input type="radio" name="pill" value="blue" events.change="chosePill" />
                <span>Blue</span>
            </label>
            <label >
                <input type="radio" name="pill" value="red" events.change="chosePill"  />
                <span>Red</span>
            </label>
            <div if="pill === 'red'">Welcome into the matrix</div>
            <div elseif="pill === 'blue'">Welcome into the reality</div>
            <div else="" >You have to do your choice</div>
        </div>
    </div>
`);Create a service
Habame.createService('ProductService', function(State) {
    State.add('productList', []);
    this.addProduct = function(name, price) {
        State.productList.push({ name, price });
    };
}, { isUniqueInstance: true }); // use isUniqueInstance to share the same instance of service among applicaton component
Habame.createComponent('ProductForm', function({ Actions, Refs }) {
    const productService = Habame.Services.ProductService;
    Actions.addProduct = function() {
        const nameInput = Refs.name.target();
        const priceInput = Refs.price.target();
        productService.addProduct(nameInput.value, priceInput.value);
        nameInput.value = '';
        priceInput.value = '';
        nameInput.focus();
    };
},
`
    <input type="text" ref="name" placeholder="Name" />  <input type="text" ref="price" placeholder="Price" /> <button events.click = "addProduct" >Add +</button>
`);
const App = Habame.createComponent('App', function({ State }) {
    State.useService(Habame.Services.productService); // will sync your component state with all service states
    // State.useService(Habame.Services.productService, ['productList']); // will sync your component state with only required service states
},
`
<div>
    <ul>
        <li repeat="productList as product" >
            {{ product.name }} <strong>{{ product.price}}$</strong>
        </li>
    </ul>
    <br/>
    <ProductForm />
</div>
`);Create a directive
Habame.createDirective('validator', function({ element, attribute, attrs }) {
    const errorContainer = document.createElement('div');
    element.addEventListener('input', function() {
        const isCorrectValue = (new RegExp(attribute.value())).test(element.value);
        errorContainer.innerHTML = isCorrectValue ? '' : 'Error';
    });
    this.created = function() {
        const nextElement = element.nextSibling;
        if(nextElement) {
            element.parentNode.insertBefore(errorContainer, nextElement);
            return;
        }
        element.parentNode.appendChild(errorContainer);
    };
});
const App = Habame.createComponent('App', function() { },
`
<div>
    <form events.prevent.submit="" >
        <input type="text" directives.validator="'[0-9]+'}}" />
    </form>
</div>
`);create a view engine
Some time we repeat the same code to display, present or do something. In case you don't want to create a component you could just add a view engine to add or edit something specific before the view compilation.
Note : the view engine is only an interpret, nothing more
Habame.addViewEngine('formInput', function(sourceCode) {
    return sourceCode.replace(/@formTextInput/ig, '<input type="text" class="my-custom-form-input" placeholder="Simple text" />')
        .replace(/@formPasswordInput\b/ig, '<input type="password" class="my-custom-form-input" placeholder="Password" />');
});
const App = Habame.createComponent('App', function() { },
`
    <form>
        <div>@formTextInput</div>
        <br/>
        <div>@formPasswordInput</div>
    </form>
`, { engines: ['formInput']});
const root = Habame.createRoot(document.getElementById('app'));
root.render(App);Create a model with mutators
this will allow you to create model to manage your data and make it compatible with state, only methods define as mutators will be overridden.
const User = function () {
    this.lastname = '';
    this.firstname = '';
    this.setFullName = (firstname, lastname) => {
        this.lastname = lastname;
        this.firstname = firstname;
    };
};
User.prototype.MUTATORS = ['setFullName'];
const App = Habame.createComponent('App', function({ State, Actions }) {
    State.add('user', new User());
    Actions.changeToJhon = function() {
        State.user.setFullName('Jhon', 'do');
    };
},
`
 <div if="user.lastname" >hello {{ user.lastname }} {{ user.firstname }}</div>
 <button events.click = 'changeToJhon' >Change to Jhon do</button>
`);Use App to make communication between component
App is the instance of you rootApp which contain his own event handler and state handler
Habame.createComponent('MyComponent', function({ App }) {
    
    const appEvent = App.getEvent(); // will return the app HbEvent
    const state = App.getState(); // will return the app State
    
}, ``);example with app event
Habame.createComponent('Notifications', function({ App, State }) {
    State.init({ notifications: [] });
    App.getEvent().addEventListener('push-notification', function(notification) {
        State.notifications.push(notification);
        setTimeout(() => {
            State.notifications.shift();
        }, 3000);
    });
},
`
    <div class="notifications-container" >
        <div class="notification-container" repeat="notifications as notification" >
            {{ notification.message }}
        </div>
    </div>
`);
const App = Habame.createComponent('App', function({ App, State, Actions }) {
    State.init({
        count: 0
    });
    let countNotifications = 0;
    Actions.sendNotification = function() {
        App.getEvent().emit('push-notification', [{ message: 'Add new notification ' + (++countNotifications) }]);
    };
},
`
    <div>
        <Notifications />
        <br/><br/>
        <button events.click="sendNotification" >Send notification</button>
    </div>
`);12 months ago
12 months ago
11 months ago
12 months ago
11 months ago
12 months ago
11 months ago
12 months ago
12 months ago
12 months ago
11 months ago
11 months ago
11 months ago
11 months ago
12 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
12 months ago
11 months ago
12 months ago
11 months ago
11 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago