Using Smart Components with the Dev Portal
Working with Components in the Dev Portal
The Kong Dev Portal supports the use of Vue.js and React.js within the Dev
Portal template files to customize the functionality and look of the Dev Portal.
Working with Vue within Handlebars templates will feel familiar outside of a few
caveats which will be covered below. In addition to this guide, the Default
Dev Portal ships with examples of how to use these ‘smart components’.
Filetype
All non-spec files must have a primary filetype of .hbs
(Handlebars). As a
result Vue components are written within .hbs
files, it is suggested to
indicate this by appending -vue
to the filename: sample.hbs
->
sample-vue.hbs
Instantiation
In order to render correctly components must be instantiated within a callback
passed to window.registerApp
. Vue and React libraries are accessible via the
window. After handlebars renders the initial template, the Dev Portal will
iterate over and instantiate each component passed to it via registerApp
.
{{!-- component --}}
<script>
// Place Vue/React code within a callback passed as an argument to `registerApp`.
window.registerApp(function () {
// Vue and React components are accessed via the `window` as well.
new window.Vue({
el: '#component',
delimiters: ['${', '}'],
data () {
return {
title: 'hello!'
}
}
})
})
</script>
Delimiters
Handlebars & Vue share the use of the same template delimiters, this will cause
issues as the libraries will not know which fields should be used by who. For
this reason it is necessary to indicate custom delimiters in the Vue template:
{{!-- template --}}
<div id="delimiters-example">
<div class="handlebars-render">
{{!-- Handlebars will render this content using its default '{{}}' delimiters --}}
<p>{{ handlebarsContent }}<p>
</div>
<div class="vue-render">
{{!-- Vue will render this content using the custom '${}' delimiters set below --}}
<p>${ vueContent }<p>
</div>
</div>
{{!-- component --}}
<script>
window.registerApp(function () {
new window.Vue({
el: '#delimiters-example',
//Custom delimiters in Vue should be defined here
delimiters: ['${', '}'],
data () {
return {
vueContent: 'hello!'
}
}
})
})
</script>
File Structure
Vue maintains its general structure when written within handlebars and consists
of template
, component
, and style
sections.
{{!-- template --}}
<div id="file-structure-example">
<h1>${ title }<h1>
</div>
{{!-- component --}}
<script>
window.registerApp(function () {
new window.Vue({
el: '#file-structure-example',
delimiters: ['${', '}'],
data () {
return {
title: 'hello!'
}
}
})
})
</script>
{{!-- style --}}
<style>
h1 {
font-size: 24px;
color: red;
}
</style>
Importing
Importing logic from one file to another can be done via a handlebars partial.
In order to access the logic contained in the imported file, attach importable
content to the window. Reference search/widget.hbs
or spec/dropdown.hbs
partials in the default dev portal which act as working examples of how this can
be done.
import/helper-js.hbs
<script>
//create window.helpers object if needed
if (!window.helpers) {
window.helpers = {}
}
window.helpers.returnHelloWorld = () => {
return 'Hello World!'
}
</script>
import/example-vue.hbs
{{!-- imports --}}
{{> import/helper-js }}
{{!-- template --}}
<div id="import-example">
<h1>${ returnHelloWorld }<h1>
</div>
{{!-- component --}}
<script>
window.registerApp(function () {
new window.Vue({
el: '#import-example',
delimiters: ['${', '}'],
data () {
return {
returnHelloWorld: console.log('error: returnHelloWorld helper failed to load')
}
},
mounted () {
if (window.helpers) {
// assign helper if available, log error if not
this.returnHelloWorld = window.helpers.returnHelloWorld || this.returnHelloWorld
}
}
})
})
</script>