fe3dback / kx-draw
PHP/JS handlebars wrapper with reactive update
Requires
- zordius/lightncandy: ^1.1
Requires (Dev)
- devster/ubench: ^1.2
- filp/whoops: ^2.1
- monolog/monolog: ^1.22
- phpunit/phpcov: ^4.0@dev
- phpunit/phpunit: ^6.1
- satooshi/php-coveralls: ^2.0@dev
This package is auto-updated.
Last update: 2025-03-04 10:23:10 UTC
README
Handlebars Render (PHP/JS)
This is reactive two side template library for handlebars. One template you can render on both sides:
- backend [PHP]
- frontend [JS] (optional)
Lib is wrapper of fastest handlebars implementation, based on: zordius/lightncandy
Install
$ composer require fe3dback/kx-draw
Requirements [PHP side]:
- php >= 7.0
- composer
Use
Prepare directories
-
First of all you need to make tmp folder inside your project, kxdraw will be store all cache data to optimize render speed. Check RWO access to this directory.
-
Also you need some folder for templates.
Something like this:
- my_project_root
|- example.php // some php script
|- tmp/draw // any cache will be here
|- public/templates/*.hbs // templates folder
Require lib
code from example.php
use KX\Template\Builders\EngineFactory; use KX\Template\Draw; require_once 'vendor/autoload.php'; $draw = new Draw ( (new EngineFactory()) ->setExt('hbs') // templates file extension (*.hbs) ->setCacheDirReal($cacheDir) // cache directory (we can safely delete dir, and cache will be rebuild) ->setTemplatesDirReal($templatesDir) // where our templates live ->setUseCache(true) // recommend to turn ON this feature (compile only first time) ->setUseMemCache(true) // recommend to turn ON this feature (helpful for loops) ->build() );
Ok, we got $draw class, so we can render some template:
code from public/templates/hello.hbs
<b>Hello {{name}}!</b>
code from example.php
$html = $draw->render('hello', 1, [ 'name' => 'world' ]);
What we use:
- 'hello' - this is template file name (without extension)
- 1 - unique render id. Good idea to use EntityID (productId, userId, articleId, etc..) for that.
- ['name'=>'world'] - data used in template
Result will be in $html:
<b>Hello world!</b>
Global scope use
In some case we want to use DrawLib from any application place:
Put this code in any shared file, executed from every other script (common.php, etc..)
/** * Get draw object * global scope wrapper * * @return Draw */ function KXDraw(): Draw { global $__kxDrawEntity; if (is_null($__kxDrawEntity)) { $cacheDir = '/'; // todo replace to your dir $templatesDir = '/'; // todo replace to your dir // make draw object, we can use only this class directly $__kxDrawEntity = new Draw ( (new EngineFactory()) ->setExt('hbs') // templates file extension (*.hbs) ->setCacheDirReal($cacheDir) // cache directory (we can safely delete dir, and cache will be rebuild) ->setTemplatesDirReal($templatesDir) // where our templates stored ->setUseCache(true) // recommend to turn ON this feature (compile only first time) ->setUseMemCache(true) // recommend to turn ON this feature (helpful for loops) ->build() ); } return $__kxDrawEntity; }
Use:
$html = KXDraw()->render('hello', 1, [ 'name' => 'world' ]);
Partials
Before use partials in our templates, we need to mark some templates (or entire folders as partials).
// mark /templates/common/header.hbs KXDraw()->addPartial('/common/header'); // mark /templates/shared/*/* KXDraw()->addPartialsDirectory('shared');
Now any marked templates can be used as partials:
code from public/templates/hello.hbs
<b>Hello {{> shared/name}}!</b>
code from public/templates/shared/name.hbs
<i>{{name}}</i>
code from example.php
$html = KXDraw()->render('hello', 1, [ 'name' => 'world' ]);
Result will be in $html:
<b>Hello <i>world</i>!</b>
Templates and Reactivity
- All templates should have only one parent. (like in react). For example:
This is OK:
<div>..some_content..</div>
This will be broken:
<div>..some_content1..</div> <div>..some_content2..</div>
In case when template have many nodes, we can wrap with some another div/span/etc..
This is OK:
<div> <div>..some_content1..</div> <div>..some_content2..</div> </div>
Export to JS
Requirements [JS side]:
- jquery >= 2.*
- handlebars.js
Handlebars can be installed with many variants:
Include
- place JQ and handlebars.js anywhere in markup (for example before < / body> tag closing)
- AFTER place js draw implementation and exported data:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.7/handlebars.min.js"></script> <script type="text/javascript" src="/vendor/fe3dback/kx-draw/draw.js"></script> <!-- after export no more rendering allowed, this should be last call to KXDraw --> <?=KXDraw()->exportToJS()?>
JS Usage
Go to page with templates and lib, and try in console:
KXDraw // KXDrawRender {templates: Object, data: Object, partials: Object}
If lib included correctly, this object should contain all data, templates and partials from backend
Methods:
KXDraw.getRawData()
Return all data used in backend
KXDraw.getRawData() // Object {hello: Object}
KXDraw.getRawPartials()
Return all partials
KXDraw.getRawPartials() // Object {shared/name: "<i>{{name}}</i>"}
KXDraw.getRawTemplates()
Return all raw templates from backend files
KXDraw.getRawTemplates() // Object {hello: "<b>Hello {{> shared/name}}!</b>"}
KXDraw.update(templateName, uniqueId, data = {}, assign = true)
Update html template on page, and template data.
- string templateName - path to templateFile (relative without extension)
- string uniqueId - id from backend
- object data - object with fields
- bool assign DEF: TRUE - if true, update will combine old data with new data
KXDraw.update('hello', 1, {name:"KXRender"}); // true
Assign example
// old data: { a: 1, b: 2 } // new data: { b: 4 } // RESULT WITH ASSIGN: { a: 1, b: 4 } // RESULT WITHOUT ASSIGN: { b: 4 }
KXDraw.getDataByUniqId(templateName, uniqueId)
Get stored data from used template
- string templateName - path to templateFile (relative without extension)
- string uniqueId - id from backend
KXDraw.getDataByUniqId('hello', 1); // Object { // name: "world", // _kx_draw_template_name: "hello", // _kx_draw_unique_id: "1" // }
KXDraw.getNodeByUniqId(templateName, uniqueId)
Get Jquery node object
- string templateName - path to templateFile (relative without extension)
- string uniqueId - id from backend
KXDraw.getNodeByUniqId('hello', 1); // [b, prevObject: r.fn.init(1)] // > 0: b // > length: 1
Examples
see examples folder.