From 3e613987f708e3c580072a8aef18532b551efb0a Mon Sep 17 00:00:00 2001 From: Nobuo Kihara Date: Sun, 2 Nov 2014 16:18:04 +0900 Subject: [PATCH] docs/guide-ja/structure-views.md prepared for translation [ci skip] --- docs/guide-ja/structure-views.md | 722 +++++++++++++++++++++++++++++++ 1 file changed, 722 insertions(+) create mode 100644 docs/guide-ja/structure-views.md diff --git a/docs/guide-ja/structure-views.md b/docs/guide-ja/structure-views.md new file mode 100644 index 0000000000..b8553d8efb --- /dev/null +++ b/docs/guide-ja/structure-views.md @@ -0,0 +1,722 @@ +Views +===== + +Views are part of the [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) architecture. +They are code responsible for presenting data to end users. In a Web application, views are usually created +in terms of *view templates* which are PHP script files containing mainly HTML code and presentational PHP code. +They are managed by the [[yii\web\View|view]] [application component](structure-application-components.md) which provides commonly used methods +to facilitate view composition and rendering. For simplicity, we often call view templates or view template files +as views. + + +## Creating Views + +As aforementioned, a view is simply a PHP script mixed with HTML and PHP code. The following is the view +that presents a login form. As you can see, PHP code is used to generate the dynamic content, such as the +page title and the form, while HTML code organizes them into a presentable HTML page. + +```php +title = 'Login'; +?> +

title) ?>

+ +

Please fill out the following fields to login:

+ + + field($model, 'username') ?> + field($model, 'password')->passwordInput() ?> + + +``` + +Within a view, you can access `$this` which refers to the [[yii\web\View|view component]] managing +and rendering this view template. + +Besides `$this`, there may be other predefined variables in a view, such as `$model` in the above +example. These variables represent the data that are *pushed* into the view by [controllers](structure-controllers.md) +or other objects whose trigger the [view rendering](#rendering-views). + +> Tip: The predefined variables are listed in a comment block at beginning of a view so that they can + be recognized by IDEs. It is also a good way of documenting your views. + + +### Security + +When creating views that generate HTML pages, it is important that you encode and/or filter the data coming +from end users before presenting them. Otherwise, your application may be subject to +[cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting) attacks. + +To display a plain text, encode it first by calling [[yii\helpers\Html::encode()]]. For example, the following code +encodes the user name before displaying it: + +```php + + +
+ name) ?> +
+``` + +To display HTML content, use [[yii\helpers\HtmlPurifier]] to filter the content first. For example, the following +code filters the post content before displaying it: + +```php + + +
+ text) ?> +
+``` + +> Tip: While HTMLPurifier does excellent job in making output safe, it is not fast. You should consider + [caching](caching-overview.md) the filtering result if your application requires high performance. + + +### Organizing Views + +Like [controllers](structure-controllers.md) and [models](structure-models.md), there are conventions to organize views. + +* For views rendered by a controller, they should be put under the directory `@app/views/ControllerID` by default, + where `ControllerID` refers to the [controller ID](structure-controllers.md#routes). For example, if + the controller class is `PostController`, the directory would be `@app/views/post`; If it is `PostCommentController`, + the directory would be `@app/views/post-comment`. In case the controller belongs to a module, the directory + would be `views/ControllerID` under the [[yii\base\Module::basePath|module directory]]. +* For views rendered in a [widget](structure-widgets.md), they should be put under the `WidgetPath/views` directory by + default, where `WidgetPath` stands for the directory containing the widget class file. +* For views rendered by other objects, it is recommended that you follow the similar convention as that for widgets. + +You may customize these default view directories by overriding the [[yii\base\ViewContextInterface::getViewPath()]] +method of controllers or widgets. + + +## Rendering Views + +You can render views in [controllers](structure-controllers.md), [widgets](structure-widgets.md), or any +other places by calling view rendering methods. These methods share a similar signature shown as follows, + +``` +/** + * @param string $view view name or file path, depending on the actual rendering method + * @param array $params the data to be passed to the view + * @return string rendering result + */ +methodName($view, $params = []) +``` + + +### Rendering in Controllers + +Within [controllers](structure-controllers.md), you may call the following controller methods to render views: + +* [[yii\base\Controller::render()|render()]]: renders a [named view](#named-views) and applies a [layout](#layouts) + to the rendering result. +* [[yii\base\Controller::renderPartial()|renderPartial()]]: renders a [named view](#named-views) without any layout. +* [[yii\web\Controller::renderAjax()|renderAjax()]]: renders a [named view](#named-views) without any layout, + and injects all registered JS/CSS scripts and files. It is usually used in response to AJAX Web requests. +* [[yii\base\Controller::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or + [alias](concept-aliases.md). + +For example, + +```php +namespace app\controllers; + +use Yii; +use app\models\Post; +use yii\web\Controller; +use yii\web\NotFoundHttpException; + +class PostController extends Controller +{ + public function actionView($id) + { + $model = Post::findOne($id); + if ($model === null) { + throw new NotFoundHttpException; + } + + // renders a view named "view" and applies a layout to it + return $this->render('view', [ + 'model' => $model, + ]); + } +} +``` + + +### Rendering in Widgets + +Within [widgets](structure-widgets.md), you may call the following widget methods to render views. + +* [[yii\base\Widget::render()|render()]]: renders a [named view](#named-views). +* [[yii\base\Widget::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or + [alias](concept-aliases.md). + +For example, + +```php +namespace app\components; + +use yii\base\Widget; +use yii\helpers\Html; + +class ListWidget extends Widget +{ + public $items = []; + + public function run() + { + // renders a view named "list" + return $this->render('list', [ + 'items' => $this->items, + ]); + } +} +``` + + +### Rendering in Views + +You can render a view within another view by calling one of the following methods provided by the [[yii\base\View|view component]]: + +* [[yii\base\View::render()|render()]]: renders a [named view](#named-views). +* [[yii\web\View::renderAjax()|renderAjax()]]: renders a [named view](#named-views) and injects all registered + JS/CSS scripts and files. It is usually used in response to AJAX Web requests. +* [[yii\base\View::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or + [alias](concept-aliases.md). + +For example, the following code in a view renders the `_overview.php` view file which is in the same directory +as the view being currently rendered. Remember that `$this` in a view refers to the [[yii\base\View|view]] component: + +```php +render('_overview') ?> +``` + + +### Rendering in Other Places + +In any place, you can get access to the [[yii\base\View|view]] application component by the expression +`Yii::$app->view` and then call its aforementioned methods to render a view. For example, + +```php +// displays the view file "@app/views/site/license.php" +echo \Yii::$app->view->renderFile('@app/views/site/license.php'); +``` + + +### Named Views + +When you render a view, you can specify the view using either a view name or a view file path/alias. In most cases, +you would use the former because it is more concise and flexible. We call views specified using names as *named views*. + +A view name is resolved into the corresponding view file path according to the following rules: + +* A view name may omit the file extension name. In this case, `.php` will be used as the extension. For example, + the view name `about` corresponds to the file name `about.php`. +* If the view name starts with double slashes `//`, the corresponding view file path would be `@app/views/ViewName`. + That is, the view is looked for under the [[yii\base\Application::viewPath|application's view path]]. + For example, `//site/about` will be resolved into `@app/views/site/about.php`. +* If the view name starts with a single slash `/`, the view file path is formed by prefixing the view name + with the [[yii\base\Module::viewPath|view path]] of the currently active [module](structure-modules.md). + If there is no active module, `@app/views/ViewName` will be used. For example, `/user/create` will be resolved into + `@app/modules/user/views/user/create.php`, if the currently active module is `user`. If there is no active module, + the view file path would be `@app/views/user/create.php`. +* If the view is rendered with a [[yii\base\View::context|context]] and the context implements [[yii\base\ViewContextInterface]], + the view file path is formed by prefixing the [[yii\base\ViewContextInterface::getViewPath()|view path]] of the + context to the view name. This mainly applies to the views rendered within controllers and widgets. For example, + `site/about` will be resolved into `@app/views/site/about.php` if the context is the controller `SiteController`. +* If a view is rendered within another view, the directory containing the other view file will be prefixed to + the new view name to form the actual view file path. For example, `item` will be resolved into `@app/views/post/item` + if it is being rendered in the view `@app/views/post/index.php`. + +According to the above rules, calling `$this->render('view')` in a controller `app\controllers\PostController` will +actually render the view file `@app/views/post/view.php`, while calling `$this->render('_overview')` in that view +will render the view file `@app/views/post/_overview.php`. + + +### Accessing Data in Views + +There are two approaches to access data within a view: push and pull. + +By passing the data as the second parameter to the view rendering methods, you are using the push approach. +The data should be represented as an array of name-value pairs. When the view is being rendered, the PHP +`extract()` function will be called on this array so that the array is extracted into variables in the view. +For example, the following view rendering code in a controller will push two variables to the `report` view: +`$foo = 1` and `$bar = 2`. + +```php +echo $this->render('report', [ + 'foo' => 1, + 'bar' => 2, +]); +``` + +The pull approach actively retrieves data from the [[yii\base\View|view component]] or other objects accessible +in views (e.g. `Yii::$app`). Using the code below as an example, within the view you can get the controller object +by the expression `$this->context`. And as a result, it is possible for you to access any properties or methods +of the controller in the `report` view, such as the controller ID shown in the following: + +```php +The controller ID is: context->id ?> +?> +``` + +The push approach is usually the preferred way of accessing data in views, because it makes views less dependent +on context objects. Its drawback is that you need to manually build the data array all the time, which could +become tedious and error prone if a view is shared and rendered in different places. + + +### Sharing Data among Views + +The [[yii\base\View|view component]] provides the [[yii\base\View::params|params]] property that you can use +to share data among views. + +For example, in an `about` view, you can have the following code which specifies the current segment of the +breadcrumbs. + +```php +$this->params['breadcrumbs'][] = 'About Us'; +``` + +Then, in the [layout](#layouts) file, which is also a view, you can display the breadcrumbs using the data +passed along [[yii\base\View::params|params]]: + +```php + isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], +]) ?> +``` + + +## Layouts + +Layouts are a special type of views that represent the common parts of multiple views. For example, the pages +for most Web applications share the same page header and footer. While you can repeat the same page header and footer +in every view, a better way is to do this once in a layout and embed the rendering result of a content view at +an appropriate place in the layout. + + +### Creating Layouts + +Because layouts are also views, they can be created in the similar way as normal views. By default, layouts +are stored in the directory `@app/views/layouts`. For layouts used within a [module](structure-modules.md), +they should be stored in the `views/layouts` directory under the [[yii\base\Module::basePath|module directory]]. +You may customize the default layout directory by configuring the [[yii\base\Module::layoutPath]] property of +the application or modules. + +The following example shows how a layout looks like. Note that for illustrative purpose, we have greatly simplified +the code in the layout. In practice, you may want to add more content to it, such as head tags, main menu, etc. + +```php + +beginPage() ?> + + + + + + <?= Html::encode($this->title) ?> + head() ?> + + +beginBody() ?> +
My Company
+ + +endBody() ?> + + +endPage() ?> +``` + +As you can see, the layout generates the HTML tags that are common to all pages. Within the `` section, +the layout echoes the `$content` variable which represents the rendering result of content views and is pushed +into the layout when [[yii\base\Controller::render()]] is called. + +Most layouts should call the following methods like shown in the above code. These methods mainly trigger events +about the rendering process so that scripts and tags registered in other places can be properly injected into +the places where these methods are called. + +- [[yii\base\View::beginPage()|beginPage()]]: This method should be called at the very beginning of the layout. + It triggers the [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]] event which indicates the beginning of a page. +- [[yii\base\View::endPage()|endPage()]]: This method should be called at the end of the layout. + It triggers the [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]] event which indicates the end of a page. +- [[yii\web\View::head()|head()]]: This method should be called within the `` section of an HTML page. + It generates a placeholder which will be replaced with the registered head HTML code (e.g. link tags, meta tags) + when a page finishes rendering. +- [[yii\web\View::beginBody()|beginBody()]]: This method should be called at the beginning of the `` section. + It triggers the [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]] event and generates a placeholder which will + be replaced by the registered HTML code (e.g. JavaScript) targeted at the body begin position. +- [[yii\web\View::endBody()|endBody()]]: This method should be called at the end of the `` section. + It triggers the [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]] event and generates a placeholder which will + be replaced by the registered HTML code (e.g. JavaScript) targeted at the body end position. + + +### Accessing Data in Layouts + +Within a layout, you have access to two predefined variables: `$this` and `$content`. The former refers to +the [[yii\base\View|view]] component, like in normal views, while the latter contains the rendering result of a content +view which is rendered by calling the [[yii\base\Controller::render()|render()]] method in controllers. + +If you want to access other data in layouts, you have to use the pull method as described in +the [Accessing Data in Views](#accessing-data-in-views) subsection. If you want to pass data from a content view +to a layout, you may use the method described in the [Sharing Data among Views](#sharing-data-among-views) subsection. + + +### Using Layouts + +As described in the [Rendering in Controllers](#rendering-in-controllers) subsection, when you render a view +by calling the [[yii\base\Controller::render()|render()]] method in a controller, a layout will be applied +to the rendering result. By default, the layout `@app/views/layouts/main.php` will be used. + +You may use a different layout by configuring either [[yii\base\Application::layout]] or [[yii\base\Controller::layout]]. +The former governs the layout used by all controllers, while the latter overrides the former for individual controllers. +For example, the following code makes the `post` controller to use `@app/views/layouts/post.php` as the layout +when rendering its views. Other controllers, assuming their `layout` property is untouched, will still use the default +`@app/views/layouts/main.php` as the layout. + +```php +namespace app\controllers; + +use yii\web\Controller; + +class PostController extends Controller +{ + public $layout = 'post'; + + // ... +} +``` + +For controllers belonging to a module, you may also configure the module's [[yii\base\Module::layout|layout]] property to +use a particular layout for these controllers. + +Because the `layout` property may be configured at different levels (controllers, modules, application), +behind the scene Yii takes two steps to determine what is the actual layout file being used for a particular controller. + +In the first step, it determines the layout value and the context module: + +- If the [[yii\base\Controller::layout]] property of the controller is not null, use it as the layout value and + the [[yii\base\Controller::module|module]] of the controller as the context module. +- If [[yii\base\Controller::layout|layout]] is null, search through all ancestor modules (including the application itself) of the controller and + find the first module whose [[yii\base\Module::layout|layout]] property is not null. Use that module and + its [[yii\base\Module::layout|layout]] value as the context module and the chosen layout value. + If such a module cannot be found, it means no layout will be applied. + +In the second step, it determines the actual layout file according to the layout value and the context module +determined in the first step. The layout value can be: + +- a path alias (e.g. `@app/views/layouts/main`). +- an absolute path (e.g. `/main`): the layout value starts with a slash. The actual layout file will be + looked for under the application's [[yii\base\Application::layoutPath|layout path]] which defaults to + `@app/views/layouts`. +- a relative path (e.g. `main`): the actual layout file will be looked for under the context module's + [[yii\base\Module::layoutPath|layout path]] which defaults to the `views/layouts` directory under the + [[yii\base\Module::basePath|module directory]]. +- the boolean value `false`: no layout will be applied. + +If the layout value does not contain a file extension, it will use the default one `.php`. + + +### Nested Layouts + +Sometimes you may want to nest one layout in another. For example, in different sections of a Web site, you +want to use different layouts, while all these layouts share the same basic layout that generates the overall +HTML5 page structure. You can achieve this goal by calling [[yii\base\View::beginContent()|beginContent()]] and +[[yii\base\View::endContent()|endContent()]] in the child layouts like the following: + +```php +beginContent('@app/views/layouts/base.php'); ?> + +...child layout content here... + +endContent(); ?> +``` + +As shown above, the child layout content should be enclosed within [[yii\base\View::beginContent()|beginContent()]] and +[[yii\base\View::endContent()|endContent()]]. The parameter passed to [[yii\base\View::beginContent()|beginContent()]] +specifies what is the parent layout. It can be either a layout file or alias. + +Using the above approach, you can nest layouts in more than one levels. + + +### Using Blocks + +Blocks allow you to specify the view content in one place while displaying it in another. They are often used together +with layouts. For example, you can define a block in a content view and display it in the layout. + +You call [[yii\base\View::beginBlock()|beginBlock()]] and [[yii\base\View::endBlock()|endBlock()]] to define a block. +The block can then be accessed via `$view->blocks[$blockID]`, where `$blockID` stands for a unique ID that you assign +to the block when defining it. + +The following example shows how you can use blocks to customize specific parts of a layout in a content view. + +First, in a content view, define one or multiple blocks: + +```php +... + +beginBlock('block1'); ?> + +...content of block1... + +endBlock(); ?> + +... + +beginBlock('block3'); ?> + +...content of block3... + +endBlock(); ?> +``` + +Then, in the layout view, render the blocks if they are available, or display some default content if a block is +not defined. + +```php +... +blocks['block1'])): ?> + blocks['block1'] ?> + + ... default content for block1 ... + + +... + +blocks['block2'])): ?> + blocks['block2'] ?> + + ... default content for block2 ... + + +... + +blocks['block3'])): ?> + blocks['block3'] ?> + + ... default content for block3 ... + +... +``` + + +## Using View Components + +[[yii\base\View|View components]] provides many view-related features. While you can get view components +by creating individual instances of [[yii\base\View]] or its child class, in most cases you will mainly use +the `view` application component. You can configure this component in [application configurations](structure-applications.md#application-configurations) +like the following: + +```php +[ + // ... + 'components' => [ + 'view' => [ + 'class' => 'app\components\View', + ], + // ... + ], +] +``` + +View components provide the following useful view-related features, each described in more details in a separate section: + +* [theming](output-theming.md): allows you to develop and change the theme for your Web site. +* [fragment caching](caching-fragment.md): allows you to cache a fragment within a Web page. +* [client script handling](output-client-scripts.md): supports CSS and JavaScript registration and rendering. +* [asset bundle handling](structure-assets.md): supports registering and rendering of [asset bundles](structure-assets.md). +* [alternative template engines](tutorial-template-engines.md): allows you to use other template engines, such as + [Twig](http://twig.sensiolabs.org/), [Smarty](http://www.smarty.net/). + +You may also frequently use the following minor yet useful features when you are developing Web pages. + + +### Setting Page Titles + +Every Web page should have a title. Normally the title tag is being displayed in a [layout](#layouts). However, in practice +the title is often determined in content views rather than layouts. To solve this problem, [[yii\web\View]] provides +the [[yii\web\View::title|title]] property for you to pass the title information from content views to layouts. + +To make use of this feature, in each content view, you can set the page title like the following: + +```php +title = 'My page title'; +?> +``` + +Then in the layout, make sure you have the following code in the `` section: + +```php +<?= Html::encode($this->title) ?> +``` + + +### Registering Meta Tags + +Web pages usually need to generate various meta tags needed by different parties. Like page titles, meta tags +appear in the `` section and are usually generated in layouts. + +If you want to specify what meta tags to generate in content views, you can call [[yii\web\View::registerMetaTag()]] +in a content view, like the following: + +```php +registerMetaTag(['name' => 'keywords', 'content' => 'yii, framework, php']); +?> +``` + +The above code will register a "keywords" meta tag with the view component. The registered meta tag is +rendered after the layout finishes rendering. By then, the following HTML code will be inserted +at the place where you call [[yii\web\View::head()]] in the layout and generate the following HTML code: + +```php + +``` + +Note that if you call [[yii\web\View::registerMetaTag()]] multiple times, it will register multiple meta tags, +regardless whether the meta tags are the same or not. + +To make sure there is only a single instance of a meta tag type, you can specify a key as a second parameter when calling the method. +For example, the following code registers two "description" meta tags. However, only the second one will be rendered. + +```html +$this->registerMetaTag(['name' => 'description', 'content' => 'This is my cool website made with Yii!'], 'description'); +$this->registerMetaTag(['name' => 'description', 'content' => 'This website is about funny raccoons.'], 'description'); +``` + + +### Registering Link Tags + +Like [meta tags](#adding-meta-tags), link tags are useful in many cases, such as customizing favicon, pointing to +RSS feed or delegating OpenID to another server. You can work with link tags in the similar way as meta tags +by using [[yii\web\View::registerLinkTag()]]. For example, in a content view, you can register a link tag like follows, + +```php +$this->registerLinkTag([ + 'title' => 'Live News for Yii', + 'rel' => 'alternate', + 'type' => 'application/rss+xml', + 'href' => 'http://www.yiiframework.com/rss.xml/', +]); +``` + +The code above will result in + +```html + +``` + +Similar as [[yii\web\View::registerMetaTag()|registerMetaTags()]], you can specify a key when calling +[[yii\web\View::registerLinkTag()|registerLinkTag()]] to avoid generated repeated link tags. + + +## View Events + +[[yii\base\View|View components]] trigger several events during the view rendering process. You may respond +to these events to inject content into views or process the rendering results before they are sent to end users. + +- [[yii\base\View::EVENT_BEFORE_RENDER|EVENT_BEFORE_RENDER]]: triggered at the beginning of rendering a file + in a controller. Handlers of this event may set [[yii\base\ViewEvent::isValid]] to be false to cancel the rendering process. +- [[yii\base\View::EVENT_AFTER_RENDER|EVENT_AFTER_RENDER]]: triggered after rendering a file by the call of [[yii\base\View::afterRender()]]. + Handlers of this event may obtain the rendering result through [[yii\base\ViewEvent::output]] and may modify + this property to change the rendering result. +- [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]]: triggered by the call of [[yii\base\View::beginPage()]] in layouts. +- [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]]: triggered by the call of [[yii\base\View::endPage()]] in layouts. +- [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]]: triggered by the call of [[yii\web\View::beginBody()]] in layouts. +- [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]]: triggered by the call of [[yii\web\View::endBody()]] in layouts. + +For example, the following code injects the current date at the end of the page body: + +```php +\Yii::$app->view->on(View::EVENT_END_BODY, function () { + echo date('Y-m-d'); +}); +``` + + +## Rendering Static Pages + +Static pages refer to those Web pages whose main content are mostly static without the need of accessing +dynamic data pushed from controllers. + +You can output static pages by putting their code in the view, and then using the code like the following in a controller: + +```php +public function actionAbout() +{ + return $this->render('about'); +} +``` + +If a Web site contains many static pages, it would be very tedious repeating the similar code many times. +To solve this problem, you may introduce a [standalone action](structure-controllers.md#standalone-actions) +called [[yii\web\ViewAction]] in a controller. For example, + +```php +namespace app\controllers; + +use yii\web\Controller; + +class SiteController extends Controller +{ + public function actions() + { + return [ + 'page' => [ + 'class' => 'yii\web\ViewAction', + ], + ]; + } +} +``` + +Now if you create a view named `about` under the directory `@app/views/site/pages`, you will be able to +display this view by the following URL: + +``` +http://localhost/index.php?r=site/page&view=about +``` + +The `GET` parameter `view` tells [[yii\web\ViewAction]] which view is requested. The action will then look +for this view under the directory `@app/views/site/pages`. You may configure [[yii\web\ViewAction::viewPrefix]] +to change the directory for searching these views. + + +## Best Practices + +Views are responsible for presenting models in the format that end users desire. In general, views + +* should mainly contain presentational code, such as HTML, and simple PHP code to traverse, format and render data. +* should not contain code that performs DB queries. Such code should be done in models. +* should avoid direct access to request data, such as `$_GET`, `$_POST`. This belongs to controllers. + If request data is needed, they should be pushed into views by controllers. +* may read model properties, but should not modify them. + +To make views more manageable, avoid creating views that are too complex or contain too much redundant code. +You may use the following techniques to achieve this goal: + +* use [layouts](#layouts) to represent common presentational sections (e.g. page header, footer). +* divide a complicated view into several smaller ones. The smaller views can be rendered and assembled into a bigger + one using the rendering methods that we have described. +* create and use [widgets](structure-widgets.md) as building blocks of views. +* create and use helper classes to transform and format data in views. +