# egg-view [![NPM version][npm-image]][npm-url] [![build status][travis-image]][travis-url] [![Test coverage][codecov-image]][codecov-url] [![David deps][david-image]][david-url] [![Known Vulnerabilities][snyk-image]][snyk-url] [![npm download][download-image]][download-url] [npm-image]: https://img.shields.io/npm/v/egg-view.svg?style=flat-square [npm-url]: https://npmjs.org/package/egg-view [travis-image]: https://img.shields.io/travis/eggjs/egg-view.svg?style=flat-square [travis-url]: https://travis-ci.org/eggjs/egg-view [codecov-image]: https://img.shields.io/codecov/c/github/eggjs/egg-view.svg?style=flat-square [codecov-url]: https://codecov.io/github/eggjs/egg-view?branch=master [david-image]: https://img.shields.io/david/eggjs/egg-view.svg?style=flat-square [david-url]: https://david-dm.org/eggjs/egg-view [snyk-image]: https://snyk.io/test/npm/egg-view/badge.svg?style=flat-square [snyk-url]: https://snyk.io/test/npm/egg-view [download-image]: https://img.shields.io/npm/dm/egg-view.svg?style=flat-square [download-url]: https://npmjs.org/package/egg-view Base view plugin for egg **it's a plugin that has been built-in for egg.** ## Install ```bash $ npm i egg-view --save ``` ## Usage ```js // {app_root}/config/plugin.js exports.view = { enable: true, package: 'egg-view', }; ``` ## Use a template engine [egg-view] don't have build-in view engine, So you should choose a template engine like [ejs], and install [egg-view-ejs] plugin. You can choose a template engine first, link [ejs], so we use [egg-view-ejs] plugin. `egg-view` is in [eggjs], so you just need configure [egg-view-ejs]. ```js // config/plugin.js exports.ejs = { enable: true, package: 'egg-view-ejs', }; ``` Configure the mapping, the file with `.ejs` extension will be rendered by ejs. ```js // config/config.default.js exports.view = { mapping: { '.ejs': 'ejs', }, }; ``` In controller, you can call `ctx.render`. ```js module.exports = app => { return class UserController extends app.Controller { async list() { const { ctx } = this; await ctx.render('user.ejs'); } }; }; ``` If you call `ctx.renderString`, you should specify viewEngine in viewOptions. ```js module.exports = app => { return class UserController extends app.Controller { async list() { const { ctx } = this; ctx.body = await ctx.renderString('<%= user %>', { user: 'popomore' }, { viewEngine: 'ejs', }); } }; }; ``` ## Use multiple view engine [egg-view] support multiple view engine, so you can use more than one template engine in one application. If you want add another template engine like [nunjucks], then you can add [egg-view-nunjucks] plugin. Configure the plugin and mapping ```js // config/config.default.js exports.view = { mapping: { '.ejs': 'ejs', '.nj': 'nunjucks', }, }; ``` You can simply render the file with `.nj` extension. ```js await ctx.render('user.nj'); ``` ## How to write a view plugin You can use [egg-view]' API to register a plugin. ### View engine Create a view engine class first, and implement `render` and `renderString`, if the template engine don't support, just throw an error. The view engine is context level, so it receive ctx in `constructor`. ```js // lib/view.js module.exports = class MyView { constructor(ctx) { // do some initialize // get the plugin config from `ctx.app.config` } async render(fullpath, locals) { return myengine.render(fullpath, locals); } async renderString() { throw new Error('not implement'); } }; ``` `render` and `renderString` support generator function, async function, or normal function return a promise. If the template engine only support callback, you can wrap it by Promise. ```js class MyView { render(fullpath, locals) { return new Promise((resolve, reject) => { myengine.render(fullpath, locals, (err, result) => { if (err) { reject(err); } else { resolve(result); } }); }); } }; ``` These methods receive three arguments, `renderString` will pass tpl as the first argument instead of name in `render`. `render(name, locals, viewOptions)` - name: the file path that can resolve from root (`app/view` by default) - locals: data used by template - viewOptions: the view options for each render, it can override the view default config in `config/config.default.js`. Plugin should implement it if it has config. When you implement view engine, you will receive this options from `render`, the options contain: - root: egg-view will resolve the name to full path, but seperating root and name in viewOptions. - name: the original name when call render - locals: the original locals when call render `renderString(tpl, locals, viewOptions)` - tpl: the template string instead of the file, using in `renderString` - locals: same as `render` - viewOptions: same as `render` ### Register After define a view engine, you can register it. ```js // app.js module.exports = app => { app.view.use('myName', require('./lib/view')); }; ``` You can define a view engine name, normally it's a template name. ### Configure Define plugin name and depend on [egg-view] ```json { "eggPlugin": { "name": "myName", "dependencies": [ "view" ] } } ``` Set default config in `config/config.default.js`, the name is equals to plugin name. ```js exports.myName = {}, ``` See some examples - [egg-view-ejs] - [egg-view-nunjucks] ## Configuration ### Root Root is `${baseDir}/app/view` by default, but you can define multiple directory, seperated by `,`. [egg-view] will find a file from all root directories. ```js module.exports = appInfo => { const baseDir = appInfo.baseDir; return { view: { root: `${baseDir}/app/view,${baseDir}/app/view2` } } } ``` ### defaultExtension When render a file, you should specify a extension that let [egg-view] know whitch engine you want to use. However you can define `defaultExtension` without write the extension. ```js // config/config.default.js exports.view = { defaultExtension: '.html', }; // controller module.exports = app => { return class UserController extends app.Controller { async list() { const { ctx } = this; // render user.html await ctx.render('user'); } }; }; ``` ### viewEngine and defaultViewEngine If you are using `renderString`, you should specify viewEngine in view config, see example above. However, you can define `defaultViewEngine` without set each time. ```js // config/config.default.js exports.view = { defaultViewEngine: 'ejs', }; ``` see [config/config.default.js](https://github.com/eggjs/egg-view/blob/master/config/config.default.js) for more detail. ## Questions & Suggestions Please open an issue [here](https://github.com/eggjs/egg/issues). ## License [MIT](https://github.com/eggjs/egg-view/blob/master/LICENSE) [eggjs]: https://eggjs.org [ejs]: https://github.com/mde/ejs [egg-view-ejs]: https://github.com/eggjs/egg-view-ejs [egg-view]: https://github.com/eggjs/egg-view [nunjucks]: http://mozilla.github.io/nunjucks [egg-view-nunjucks]: https://github.com/eggjs/egg-view-nunjucks