General

  eZ Systems Website
  Technical documentation
  Editor documentation

This Documentation contains:
 
Technical documentation:



⚠ WARNING ! This documentation is deprecated !

Please go to the current Technical Documentation

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: cosmetic changes

...

As written in the PlatformUI technical introduction, pages in PlatformUI can be generated either by the browser based on the REST API (or any other API) responses or by doing part of the rendering on the server side for instance with some Twig templates called by a Symfony controller. Both options are perfectly valid and choosing one or the other is mainly a matter of taste. In this This step will examine both strategies even if the later steps will be based on the server side rendering.

...

Then in ezconf-listviewservice.jswe can write the minimal view service:

...

This is the minimal view service, it only writes a "hello world" message in the console when instantiated but for now it's not used anywhere in the application.

...

After doing that, Y.eZConf.ListViewService becomes available in the application plugin code and we can change the eZConfList route to be:

Code Block
languagejs
themeMidnight
titleCreating a route with a view service
app.route({
    name: "eZConfList",
    path: "/ezconf/list",
    view: "ezconfListView",
    service: Y.eZConf.ListViewService, // constructor function to use to instantiate the view service
    sideViews: {'navigationHub': true, 'discoveryBar': false},
    callbacks: ['open', 'checkUser', 'handleSideViews', 'handleMainView'],
});

After doing this change, the Y.eZConf.ListViewService is used when a user reaches the eZConfList route.

...

A view service is responsible for fetching data so they it can be rendered. For a given route, the view service is instantiated the first time the route is accessed and then the same instance is reused. On that instance, the _load method is automatically called. This is where the loading logic should be in most cases. This method also receives a callback as its only parameter. This callback function should be called once the loading is finished. Typically, a view service will use the JavaScript REST Client to request the eZ Platform REST API. To do that, a JavaScript REST Client instance is available in the capi attribute of the view service.

...

At this point, if you refresh the PlatformUI application and follow the link added in the previous step, you should see a new REST API request to /api/ezp/v2/views in the network panel of the browser:

The Locations are build built in the application but not yet used anywhere.

...

Now that we have the Locations, we have to give them to the view. For that, we have to implement the _getViewParameters method in the view service. This method is automatically called when the view service loading is finished, it should return an object that will be used as a configuration object for the main view.

...

With that code, the view will receive the Location list as an attribute under the name locations.

Info
titleWhy implementing implement _load and _getViewParameters and not load and getViewParameters?

When implementing a custom view service, you should always implement the protected _load and _getViewParameters methods, not their public counterparts load and getViewParameters. By implementing the protected versions, you keep the opportunity for a developer to write a plugin to enhance your view service.

...

The view now receives the Location list in the locations attribute so we have to change the view to take that into account. For now, let's change the view it to just display the Location it receives as an unordered HTML list of links to those Locations. To do that, we have to:

  1. Declare the locations attribute in the view
  2. Give that list to the template in a form it can understand
  3. Update the template to generate the list

The point #2 Point 2 is required because Handlebars is not able to understand the complex model objects generated by YUI. So we have to transform those complex object to into plain JavaScript objects. After doing the changes #1 in steps 1 and #22, the view looks like this:

Code Block
languagejs
themeMidnight
titleezconf-listview.js
YUI.add('ezconf-listview', function (Y) {
    Y.namespace('eZConf');

    Y.eZConf.ListView = Y.Base.create('ezconfListView', Y.eZ.TemplateBasedView, [], {
        initializer: function () {
            console.log("Hey, I'm the list view");
        },

        render: function () {
            this.get('container').setHTML(
                this.template({
                    locations: this._getJsonifiedLocations(),
                })
            );
            return this;
        },

        _getJsonifiedLocations: function () {
            // to get usable objects in the template
            return Y.Array.map(this.get('locations'), function (loc) {
                return loc.toJSON();
            });
        },
    }, {
        ATTRS: {
            locations: {
                value: [],
            }
        }
    });
});

The Then the template has then to be changed to something like:

...

PlatformUI provides a path template helper that allows you to generate a route URL in PlatformUI. It expects a route name and the route parameters.

Tip
titleResults

The resulting code can be been in the 6_1_list_client tag on GitHub, this step result can also be viewed as a diff between tags 5_navigation and 6_1_list_client.

The rest of this tutorial is focused on the server side rendering strategy. Completing the browser side rendering strategy to get the expected features is left as an exerciceexercise.

Server side rendering

In this case a part of the rendering is delegated to the server. When building a PlatformUI page this way, the application will just do one or several more AJAX request(s) and inject the result in the UI. The PlatformUI Admin part is build built this way. To be easily usable in the JavaScript application, the server response has to be structured so that the application can retrieve and set the page title, the potential notifications to issue and the actual page content. This is done by generating an HTML fragment, in the following way:

...

In the case, the minimal view service is exactly the same as the one produced in the previous Minimal view service paragraph.

...

Code Block
languagetext
themeMidnight
titlelist.html.twig
{% extends "eZPlatformUIBundle::pjax_admin.html.twig" %}

{% block header_title %}
    <h1 class="ezconf-list-title">List view</h1>
{% endblock %}

{% block content %}
<ul class="ezconf-list">
{% for value in results.searchHits %}
    <li><a href="">{{ value.valueObject.contentInfo.name }}</a></li>
{% endfor %}
</ul>
{% endblock %}

{% block title %}List{% endblock %}

Again, it's a quite a regular template but to ease the generation of the expected structured HTML fragment, this template extends eZPlatformUIBundle::pjax_admin.html.twig and redefines a few blocks, the main one being content where the actual page content is supposed to be generated.

...

We now have a Symfony Controller able to generate our Location list but this list is not yet available in the application. As in Fetching Locations from the view service and Passing the Location to the view, we have to add the code in the view service. But in the case of a server side rendering, we can reuse Y.eZ.ServerSideViewService which provides the base API to parse an HTML fragment which also provides a ready to use _getViewParameters method. All we have to do then is to implement the loading logic in _load:

...

At this point, you should see the same list as the one that was generated in Browser side rendering section. The only difference lies in the non-working links being generated in the server side solution.

...

The server side code has no knowledge of the JavaScript application routing mechanism as a result, it can not directly generate any PlatformUI Application URI, but we know while generating the HTML fragment that we want each link to allow the navigation to the viewLocation route for the Location being displayed. We can then change the Twig template to add the necessary metadata on each link so that the application have way to guess has a way of guessing where the user is supposed to go when clicking on the link:

...

Info

In PlatformUI code, the Locations, Content items and Content Types are identified by their REST id ie , that is the REST resource URL which allows you to fetch the object in the REST API. That's why we are using the path Twig template function to build the Location id.

...

Info

The DOM event handling is one of the main YUI View featurefeatures. It is documented in the YUI View guide.

So now Now the click on the Location link is transformed in a navigateTo event, we have to subscribe to that event in the view service to trigger the expected navigation:

...

Info
titleApplication level events

PlatformUI uses a lots lot of custom application level events thanks to the EventTarget YUI component. Those events are very similar to DOM events but they are attached to the application components instead of the DOM elements. Like for DOM events, there is a bubbling mechanism. For instance, here the view is firing an event and unless the propagation of the event is stopped, it will bubble to the view service and then to the application. The event basically follows the components tree until the application. An application level event is way for a deeply nested component to communicate with a higher level component.

...