componentjs-mvc

1.0.7 • Public • Published

ComponentJS MVC

Model-View-Controller Component Roles.

About

ComponentJS is a generic hierarchical component orchestration library. It has no direct notion of any component roles, although it was designed with the roles of Ralf S. Engelschall's Model-View-Controller/Component-Tree (MVC/CT) pattern in mind. ComponentJS MVC is an opinionated companion library to ComponentJS, providing ECMAScript 6 abstract classes for implementing the classes of ComponentJS backing objects by using the distinct Model, View or Controller roles of the MVC/CT pattern. The abstract classes map the major and essential parts of the ComponentJS API onto local methods which then provide the ComponentJS functionality in a way which is slightly adjusted for convenience reasons and their distinct usage under MVC/CT. ComponentJS MVC is intended to simplify the programming of HTML5 Single-Page-Apps (SPA) in an Object-Oriented Programming (OOP) manner.

Installation

# with the help of the NPM package manager (primary approach)
$ npm install componentjs-mvc

# with the help of the YARN package manager (alternative approach)
$ yarn add componentjs-mvc

# with the help of the Bower package manager (obsolete approach)
$ bower install componentjs-mvc

Usage

Main Procedure:

import $   from "jquery"

import cs  from "componentjs"
import          "componentjs/component.plugin.vue.js"

import mvc from "componentjs-mvc"

import SV  from "./service"

class App {
    static main () {
        /*  fire up ComponentJS  */
        cs.bootstrap()
        cs("/").property("sv", new SV())

        /*  fire up ComponentJS MVC  */
        mvc.jQuery      = $
        mvc.ComponentJS = cs
        mvc.Plugin()
        mvc.latch("mask:vue-options", ({ id, options }) => {
            /*  example: provide id to Vue-I18Next Vue plugin  */
            options.i18nextNamespace = id
        })
        mvc.latch("mask:vue-result", ({ id, mask }) => {
            /*  example: integrate Perfect-Scroll-Bar jQuery plugin  */
            $(".perfect-scroll-bar", mask.$el).perfectScrollbar({})
        })
    }
}

Dialog Component:

import mvc from "componentjs-mvc"

class View extends mvc.View {
    ...
}
class Model extends mvc.Model {
    ...
}
class Controller extends mvc.Controller {
    ...
}

Application Programming Interface (API)

Globals:

  • import mvc from "componentjs-mvc":
    Load the ComponentJS-MVC library.

  • mvc.ComponentJS = ...:
    Configure ComponentJS-MVC to use a particular instance of the mandatory ComponentJS framework. By default ComponentJS-MVC uses the global symbol ComponentJS.

  • mvc.jQuery = ...:
    Configure ComponentJS-MVC to use a particular instance of the optional jQuery library. By default ComponentJS-MVC uses the global symbol jQuery. jQuery is necessary only if the mvc.View::$() method should be used. jQuery and jQuery-Markup are necessary only if the mvc.View::mask() method should be used with neither template nor render options.

  • mvc.Plugin():
    Hook into ComponentJS as an mvc plugin to automatically mark dynamically created ComponentJS-MVC-based components with the proper marker for the ComponentJS debugger without having to override the create() method and this way cause a super.create() burden on the users of the ComponentJS-MVC classes. Call this once in your main procedure if you want proper colors in the ComponentJS debugger for ComponentJS-MVC-based components.

Hooks:

  • mvc.latch("mask:vue-options", (({ id, options }) => { ... }):
    Hook into the mvc.View::mask() method just before mask = ComponentJS::vue(options) is called internally. Use this to set particular options for VueJS. For instance, use mvc.latch("mask:vue-options", ({ id, options }) => { options.i18nextNamespace = id }) to set the I18N namespace when using VueJS and the Vue-I18Next plugin together.

  • mvc.latch("mask:vue-result", (({ id, result }) => { ... }):
    Hook into the mvc.View::mask() method just after mask = ComponentJS::vue(options) is called internally. Use this to post-process the VueJS instance. For instance, use mvc.latch("mask:vue-result", (({ id, result }) => { $(".perfect-scroll-bar", mask.$el).perfectScrollbar({ ... }) }) to apply the jQuery Perfect-Scrollbar plugin.

  • mvc.latch("establish:post-create", ({ id, comp, obj }) => { ... }):
    Hook into the mvc.Component::establish() method after each component was created. Use this to post-adjust created components. The comp is the created component, obj the attached backing object derived from the arguments to mvc.Component::establish().

  • mvc.latch("establish:pre-destroy", ({ id, comp, obj }) => { ... }):
    Hook into the mvc.Component::demolish() method before each component will be destroyed. Use this to pre-process components. The comp is the created component, obj the attached backing object derived from the arguments to mvc.Component::establish().

Classes:

  • class Component extends mvc.Component { ... }:
    Define an application Component class based on ComponentJS-MVC's Component class (usually not directly used in regular applications, but exposed for completeness reasons).

  • class View extends mvc.View { ... }:
    Define an application View class based on ComponentJS-MVC's View class. The mvc.View class inherits from the mvc.Component class.

  • class Model extends mvc.Model { ... }:
    Define an application Model class based on ComponentJS-MVC's Model class. The mvc.Model class inherits from the mvc.Component class.

  • class Controller extends mvc.Controller:
    Define an application Controller class based on ComponentJS-MVC's Controller class. The mvc.Controller class inherits from the mvc.Component class.

Methods (Component/View/Model/Controller Classes):

  • mvc.Component::cs(...): ComponentJS:
    Use the configured ComponentJS by just passing-through execution to ComponentJS. Use this in case you want to directly access the ComponentJS API from within a ComponentJS-MVC component.

  • mvc.Component::establish(anchor?: Component, tree: String, classes: Object|Object[], autoincrease?: Boolean = true, autodecrease?: Boolean = false): mvc.Component:
    This is a convenience wrapper around ComponentJS::create(). It internally basically calls mvc.ComponentJS(this[, anchor]).create(tree, classes.map((Clz) => typeof Clz === "function" ? new Clz() : Clz)) and remembers the created components by their id for forthcoming use via mvc.Component::my(). It also calls ComponentJS::state_auto_increase(autoincrease) and ComponentJS::state_auto_decrease(autodecrease) on all created components.

  • mvc.Component::demolish(id?: String): mvc.Component:
    This is a convenience wrapper around ComponentJS::destroy(). It either destroys just the specified component (by id) or all components previously created with mvc.Component::establish().

  • mvc.Component::my(id: String): ComponentJS:
    This fetches (by id) a particular component previously created with mvc.Component::establish().

  • mvc.Component::exists(id: String): ComponentJS:
    This checks (by id) whether a particular component previously was created with mvc.Component::establish() and was still not destroyed with mvc.Component::demolish().

  • mvc.Component::state(...args: any[]): ComponentJS:
    This is a convenience wrapper around ComponentJS::state(). The args positional arguments are just passed-through. The return value is the value of ComponentJS::state().

  • mvc.Component::guard(...args: any[]): ComponentJS:
    This is a convenience wrapper around ComponentJS::guard(). The args positional arguments are just passed-through. The return value is the value of ComponentJS::guard().

  • mvc.Component::await(...args: any[]): ComponentJS:
    This is a convenience wrapper around ComponentJS::await(). The args positional arguments are just passed-through. The return value is the value of ComponentJS::await().

  • mvc.Component::spool(func: Function, options?: Object): mvc.Component:
    This is a convenience wrapper around ComponentJS::spool(). It internally basically calls mvc.ComponentJS(this).spool({ name: mvc.ComponentJS(this).state(), ctx: this, func: func, ...options }). The twist of this wrapper is that it automatically uses the component state based spool.

  • mvc.Component::observe(name: String|String[], func: Function, options?: Object): mvc.Component:
    This is a convenience wrapper around ComponentJS::observe(). It internally basically calls mvc.ComponentJS(this[, "model"]) .observe({ name, func, spool: mvc.ComponentJS(this).state(), noevent: true, ...options }). The twists of this wrapper are: it performs automatical spooling, uses no event argument in the func callback and automatically steps down to a model child if this is a mvc.Controller. Additionally, instead of a single name, it allows you to pass an array of names.

  • mvc.Component::value(...args: any[]): any:
    This is a convenience wrapper around ComponentJS::value(). It internally basically calls mvc.ComponentJS(this[, "model"]) .value(...args). The main twist of this wrapper is: it automatically steps down to a model child if this is a mvc.Controller.

  • mvc.Component::touch(...args: any[]): mvc.Component:
    This is a convenience wrapper around ComponentJS::touch(). It internally basically calls mvc.ComponentJS(this[, "model"]) .touch(...args). The main twist of this wrapper is: it automatically steps down to a model child if this is a mvc.Controller.

  • mvc.Component::subscribe(name: String|String[], func: Function, options?: Object): mvc.Component:
    This is a convenience wrapper around ComponentJS::subscribe(). It internally basically calls mvc.ComponentJS(this).subscribe({ name, func, spool: mvc.ComponentJS(this).state(), noevent: true, capturing: false, spreading: false, bubbling: true, ...options }). The twists of this wrapper are: it performs automatical spooling, uses no event argument in the func callback, disables capturing and spreading, and enables bubbling. Additionally, instead of a single name, it allows you to pass an array of names.

  • mvc.Component::publish(name: String, args: any[], options?: Object): any:
    This is a convenience wrapper around ComponentJS::publish(). It internally basically calls mvc.ComponentJS(this).publish({ name, args, directresult: true, capturing: true, spreading: false, bubbling: true, ...options }). The twists of this wrapper are: enables direct results, enables capturing and bubbling and disables spreading.

  • mvc.Component::register(name: String|String[], func: Function, options?: Object): mvc.Component:
    This is a convenience wrapper around ComponentJS::register(). It internally basically calls mvc.ComponentJS(this).register({ name, func, spool: mvc.ComponentJS(this).state(), capturing: false, spreading: false, bubbling: true, ...options }). The twists of this wrapper are: it performs automatical spooling, disables capturing and spreading, and enables bubbling. Additionally, instead of a single name, it allows you to pass an array of names.

  • mvc.Component::call(name: String, args: any[], options?: Object): any:
    This is a convenience wrapper around ComponentJS::call(). It internally basically calls mvc.ComponentJS(this).call({ name, args, capturing: true, spreading: false, bubbling: true, ...options }). The twists of this wrapper are: it enables capturing, disabled spreading and enables bubbling.

Methods (View Class):

  • mvc.View::$(selector: String, baseElement?: DOMElement): jQuery:
    Use the configured jQuery by just passing-through execution to jQuery. Use this in case you want to directly manipulate the DOM via jQuery from within a View component. Use with caution, as jQuery and VueJS can conflict.

  • mvc.View::mask(id: String, options?: any): VueJS:
    Create a UI Mask with the help of VueJS. The id has to be unique within the UI, although it is not directly used by ComponentJS-MVC itself. It is intended to be passed through to the mask:vue-options hook and used there accordingly. The options are just passed-through to the ComponentJS::vue() method. Hence, this method requires the ComponentJS vue plugin to be loaded first.

  • mvc.View::socket(ctx: Object, plug: Function, unplug: Function): Number:
    mvc.View::socket(options: { ctx: Object, plug?: Function, unplug?: Function, ... }): Number:
    This is a convenience wrapper around ComponentJS::socket(). The ctx, plug and unplug positional arguments are just converted to the options form of method calling. If the options argument has no spool field, it is automatically created with the value of mvc.ComponentJS(this).state(). The return value is the value of ComponentJS::socket().

  • mvc.View::link(target: Object, socket: String): Number:
    mvc.View::link(options: { target: Object, socket: String, ... }): Number:
    This is a convenience wrapper around ComponentJS::link(). The target and socket positional arguments are just converted to the options form of method calling. If the options argument has no spool field, it is automatically created with the value of mvc.ComponentJS(this).state(). The return value is the value of ComponentJS::link().

  • mvc.View::plug(object: Object): Number:
    mvc.View::plug(options: { object: Object, ... }): Number:
    This is a convenience wrapper around ComponentJS::plug(). The object positional argument is just converted to the options form of method calling. If the options argument has no spool field, it is automatically created with the value of mvc.ComponentJS(this).state(). The return value is the value of ComponentJS::plug().

Methods (Model Class):

  • mvc.Model::model(spec: Object): Void:
    This just passes-through spec to the ComponentJS::model() method.

Methods (Controller Class):

  • mvc.Controller::sv(): Object:
    This is a short-hand for mvc.ComponentJS(this).property("sv") and simplifys the fetching of the underlying Service API, which beforehand should be placed into a property on the root component via mvc.ComponentJS("/").property("sv", value).

License

Copyright (c) 2016-2018 Ralf S. Engelschall (http://engelschall.com/)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Package Sidebar

Install

npm i componentjs-mvc

Weekly Downloads

33

Version

1.0.7

License

none

Unpacked Size

68 kB

Total Files

14

Last publish

Collaborators

  • rse