The PIE CLI tool supports development of Portable Interactions and Element by providing module packaging tools and live-reload features.
To create a new PIE:
- Install the PIE CLI tool:
npm install -g pie
- Create a directory with the required files. See Packaging PIEs and implement your Custom Element
- Create an Assessment item config by defining
config.json
andindex.html
. See Defining Items. - In the
config.json
define andelement
for your pie, and point it to the root directory of the package from step 1. - Load your item with
pie serve
edit your source code, and PIE CLI's live reload will automatically reload your changes
See the Development Totorial for a more complete walkthrough on creating a PIE.
See the PIE Elements organization on github for example PIEs.
PIE Custom Elements are defined as javascript modules. In their most simple form, they can be provided as self-contained ES5 or ES6 module that exports an HTMLElement and has no external dependencies.
In practice, however, most web developers use frameworks such as React to build user interfaces and often rely on external /shared libraries as dependencies.
To support this kind of development the PIE Framework provides packaging and development tools through the PIE CLI (which is built on top of the popular webpack and babel tools)
These PIE CLI tools:
- Support the use of ES6 modules in PIEs (ES6 is recommended, commonJS is supported)
- Will bundle external dependencies defined in the PIE's
package.json
- Support loading other assets (css/images)
- Provide hot-module loading for PIE development so developers can view code changes in real-time
- Support framework-specific file processing (such as
.jsx
or.vue
) through webpack loaders. - Provide packaging, transpilation and optimization for questions/assessments that use PIEs
As a best practice PIEs should be written using ES6 and using ES6 imports.
import Main from './main.jsx';
import React from 'react';
import ReactDOM from 'react-dom';
Pre-release note, this is not yet implemented. Currently plain ES6, React and Less are built-in. See: pie-framework/pie-cli#47
A PIE can define the framework used for development and other preferences for module building by adding properties to the pie-packaging
property in the package.json
file for the PIE.
{
"pie-packaging": {
"framework": "react",
"css": "sass"
}
}
Defines the framework used to build the PIE. Currently, ReactJS and Vue.js are supported contact us if you're interested in having support added for another framework.
If react
is specified: .jsx
files may be imported, and .js
files that contain JSX code will be handled correctly.
The following loaders are enabled by default:
- React
- Less
In this example, React JS is used as the framework for developing the PIE.
The main React Component is defined in main.jsx
, in this example module below, that component is wrapped in a Custom Element which is the interface to communicate with the PIE Player.
import Main from './main.jsx';
import React from 'react';
import ReactDOM from 'react-dom';
export default class MyReactElement extends HTMLElement{
constructor(){
super();
this._model = null;
this._session = null;
}
set model(s){
this._model = s;
this._rerender();
}
set session(s){
this._session = s;
this._rerender();
}
_rerender() {
if (this._model && this._session) {
var element = React.createElement(Main, { model: this._model, session: this._session });
ReactDOM.render(element, this, function () {
console.log('rendered');
});
} else {
console.log('skip');
}
}
connectedCallback() {
this._rerender();
}
}
import Vue from 'vue'
import Main from './main.vue'
export default class CorespringMultipleChoiceVueElement extends HTMLElement{
constructor(){
super();
this._model = null;
this._session = null;
}
set model(s){
this._model = s;
this._rerender();
}
set session(s){
this._session = s;
this._rerender();
}
connectedCallback() {
console.log('created');
this.innerHTML = "<root-component></root-component>";
this._rerender();
}
_rerender() {
console.log('_rerender...');
if (this._model && this._session) {
Vue.component('root-component', Main)
let vm = new Vue({
el: this
})
console.log("vue rendered");
} else {
console.log('skip');
}
}
}