I worked with JB Brock yesterday on setting up and using Oracle JET's new Composite Component Architecture.
The aim of it all is to have reusable components that enable you to define your own HTML elements, like this, for example:
<!-- ko foreach: employees --> <demo-card class="oj-flex-item" name="{{name}}" avatar="{{avatar}}" work-title="{{title}}" work-number="{{work}}" email="{{email}}" background-image="{{backgroundImage}}"> </demo-card> <!-- /ko -->
Above you see a Knockout for-each loop which iterates through 'employees' and creates a new DOM element named "demo-card" for each of them.
The above is in the view, e.g., in "home.html", while "home.js", i.e., the viewModel, defines "employees" as follows:
self.employees = [ { name: 'Deb Raphaely', avatar: 'images/composites/debraphaely.png', title: 'Purchasing Director', work: '5171278899', email: 'deb.raphaely@oracle.com', backgroundImage: 'images/composites/card-background_1.png' }, { name: 'Adam Fripp', avatar: null, title: 'IT Manager', work: '6501232234', email: 'adam.fripp@oracle.com', backgroundImage: null } ];
In this case, the definition of "demo-card" transforms the above snippets into a view that looks like this, with a "demo-card" for each of the two employees defined above:
When the user clicks on each "demo-card", it flips around, and you see the other side of the card, which presents more information about the employee. (See the above live here.)
OK, so where does "demo-card" come from? Well, in "home.js", i.e., the same place where the 'employees' above are defined, my "define" block looks like this:
define(['ojs/ojcore', 'knockout', 'ojs/ojcomposite', 'jet-composites/demo-card/loader'],
Notice, first of all, that "ojs/ojcomposite" is included, which is new in Oracle JET 2.1.0. It defines composite components. Then, notice that something is loaded from a folder named 'jet-composites', which is a folder that looks like this:
Notice "demo-card" is a folder in there, which looks like this:
So, what you have is an infrastructure for creating encapsulated components, defined by JavaScript, HTML, and CSS, with properties defined in JSON. Once you have a composite component, you have created a new HTML element, in this case "demo-card", defined by "loader.js", which ties everything together:
define(['ojs/ojcore', 'text!./demo-card.html', './demo-card', 'text!./demo-card.json', 'css!./demo-card', 'ojs/ojcomposite'], function(oj, view, viewModel, metadata) { oj.Composite.register('demo-card', { view: {inline: view}, viewModel: {inline: viewModel}, metadata: {inline: JSON.parse(metadata)} }); } );
You can pass the composite component in a ZIP file to whoever needs to use it, who unzips the ZIP into a folder, and loads it into their viewModel as described earlier, via the "define" block of the viewModel. You can see composite components as plugins for developers, i.e., not for the end user of the app, but for the development team, enabling features to be packaged, shared, and reused.
Here is a more complex example, which is a composite component called "demo-memory-game" which itself makes use of a composite component called "demo-memory-card":
All the details, including all the code described above, are here in the Oracle JET Cookbook:
http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=composite&demo=basic