Tuesday, January 17, 2017

Part 5 - Further discussion

After I completed my first attempt at adding renderers and templates to my questionnaire plugin, I went on to use them much more thoroughly in the actual release. The Moodle 3.2 release of questionnaire uses templates for all of the major pages. This is a work in progress, and I have taken some shortcuts to make the transition easier while allowing me to release the code as it is worked on.

Most noticeably, since the output of questionnaire is generated by specific functions that return HTML pieces, I have created the templates to accept that HTML. This means that only the top level formatting of a page is templatable. But, I am working on extracting more and more of the output into the templates as the work continues.

In the RENDERER_32 work in progress branch, I have refactored and extracted almost all of the question specific output into individual question type templates. These templates are used with renderer functions to return the HTML to the main renderer. I have coded the renderer function so that it will use question templates as I define them, or fallback to the old method if they are not present. If you have questions about this work, contact me or post a question here.

If you wander through those templates, you'll see some other aspects of templates used that I didn't discuss in this series. For example, in the navbaralpha.mustache file you can see the use of the language string {{# str}} helper function. This is a way to put a language string directly into the template. You can find more information on that here.

In the question_check.mustache template, you can see the use of dotted notation for tag names. For example, choice.id. While not strictly necessary, I find that this notation helps to document the structure of the context data being used in the template. In this example, the fact that id is a subelement of the choice structure.

Regarding data structures, if you recall in "Part three", I mentioned that the template data could be formatted as arrays or objects and that both would work. The code I provided used strictly arrays. But it could have used objects as well as the one array needed for the rows element. Below is an alternate coding using objects instead of arrays where possible:

    /**
     * Prepare data for use in a template
     *
     * @param \renderer_base $output
     * @return stdClass
     */
    public function export_for_template(\renderer_base $output) {
        $data = new \stdClass();
        $data->headings = new \stdClass();
        foreach ($this->headings as $key => $heading) {
            $data->headings->{$key} = $heading;
        }
        $data->rows = [];
        foreach ($this->rows as $row) {
            list($topic, $name, $responses, $type) = $row;
            $item = new \stdClass();
            $item->topic = $topic;
            $item->name = $name;
            $item->responses = $responses;
            $item->type = $type;
            $data->rows[] = $item;
        }
        return $data;
    }

Lastly, I never got into using javascript with templates. I have personally not spent enough time with this to do that topic justice. If you wish to explore that though, start with the documentation. Additionally Damyon Wiese from Moodle HQ gives a great demonstration that covers how to include javascript and Ajax with templates, as well as a great introduction to templates in general. If you want to skip ahead to where javascript comes into play, fast-forward to around 14:10 in the video.

If you want to discuss any of this series, or recommend alternate approaches, please feel free to leave comments or contact me directly.