Upgrade Your Drupal Skills
We trained 1,000+ Drupal Developers over the last decade.
See Advanced Courses NAH, I know EnoughHow to load JS and CSS libraries in a Drupal 8 controller
In the blog entry http://www.anexusit.com/blog/how-to-add-reactjs-drupal-8-composer, I show you how to add into Drupal 8 any library globally using composer.
But, that library is just there, because the library isn't used for any module or theme. For that reason, I am going to show you how to use a library in a controller.
In my example, I will include ReactJS inside a controller to be able to create react elements in that controller, to show how to use I will create a simple ReactJS form.
0. Setting your environment
I strongly recommend to set your environment in developer mode; that means to enable all debugs possible and disable all caches, the easy way to do that is using the Drupal Console project with the following command:
$ drupal site:mode dev
1. Create a module
Using the Drupal Console we could create a module using the following instruction:
$ drupal generate:module --module="MySearch" --machine-name="mysearch" --module-path="/modules/custom" --description="My custom search using react" --core="8.x" --package="Anexus" --module-file --composer -n
2. Create a controller
With our module generated, now we need to create a controller to, later on, add the ReactJS library, again using the Drupal Console commands we will make the controller.
$ drupal generate:controller --module="mysearch" --class="ReactJSFormController" --routes="title:MySearch name:mysearch.react_j_s_form_controller_form method:form path:/mysearch"
3. Including library in our module
To enable libraries in our module, we need to create a file named mysearch.libraries.yml, below could you find an example
react.min:
version: VERSION
js:
/libraries/reactjs/build/react.min.js: {}
react:
version: VERSION
js:
/libraries/reactjs/build/react.js: {}
react.dom.min:
version: VERSION
js:
/libraries/reactjs/build/react-dom.min.js: {}
The keys react.min, react and react.dom.min are arbitrary strings; you could change for any identifier do you prefer.
Maybe you are wondering about the empty curly brackets {}, the idea is like each module could load the same library with different properties, like CSS could have media info, or js could be declared to be minified or report that library is an external file.
I included the minify version of React to being used when you push this module in prod and min version could be utilized in development to facilitate the debugging.
The property version is supposed to be the library version, but if you are not sure about the proper value you could use the "constant" VERSION, this constant contains the Drupal version and is used to generate the URL to include the library resource as you can see below.
<script src="http://www.anexusit.com/libraries/reactjs/build/react.min.js?v=8.1.9-dev"></script>
In my case, I was using Drupal 8.1.9-dev.
4. Install your module
Using the Drupal Console we could install our module
$ drupal module:install mysearch
5. Updating our controller
The controller that was generated its pretty simple as you could see in the following snippet of code:
<?php
namespace Drupal\mysearch\Controller;
use Drupal\Core\Controller\ControllerBase;
/**
* Class ReactJSFormController.
*
* @package Drupal\mysearch\Controller
*/
class ReactJSFormController extends ControllerBase {
/**
* Form.
*
* @return string
* Return Hello string.
*/
public function form() {
return [
'#type' => 'markup',
'#markup' => $this->t('Implement method: form')
];
}
}
If you use the module Webprofiler you can validate how many JS were loaded in your controller, in my case 69 JS files as you could appreciate in the following image.
Let me change a little bit, to include our ReactJS library.
/**
* Form.
*
* @return string
* Return Hello string.
*/
public function form() {
return [
'#markup' => $this->t('Implement method: index'),
'#attached' => array(
'library' => array(
'mysearch/react.min',
'mysearch/react.dom.min',
),
),
];
}
If you remember, the library was registered as react.min, but we need to include the module name first, to avoid conflict with other modules that use the same key.
Sometimes you need to clear your cache to see the changes; you can do that with Drupal Console
$ drupal cache:rebuild all
After that, you could verify that you have one extra JS file, only for this particular controller.
6. Including ReactJS form
The objective of this example was to demonstrate how to render a ReactJS form in Drupal 8
The first thing I need to do is register a local library to load JS and CSS for our form, as you can check in the following example:
react.form:
version: VERSION
js:
js/mysearch.form.js: {}
css:
theme:
css/mysearch.form.css: {}
As you could notice the path is a little different, because doesn't start with "/" that means is a relative module path instead of Drupal Root relative.
When this new library has loaded both JS and CSS components are loaded.
The content of mysearch.form.css is listed below:
.SearchForm {
padding: 8px 24px;
}
.SearchForm > input,
.SearchForm > textarea,
.SearchForm > select {
display: block;
width: 240px;
padding: 4px 8px;
margin-bottom: 8px;
border-radius: 3px;
border: 1px solid #888;
font-size: 14px;
}
.ContactForm > input.ContactForm-error {
border-color: #b30e2f;
}
And the JS for our ReactJS form
var Search = React.createClass({
render: function(){
return (
React.createElement('form', {onSubmit: this.onSubmit, className: 'SearchForm', noValidate: true},
React.createElement('input', {
type: 'text',
placeholder: 'Search'
}),
React.createElement("select", { placeholder: 'Category', value: '', onChange: this.changeHandler },
React.createElement("option", { value: 1 }, "Software"),
React.createElement("option", { value: 2 }, "Movie")
),
React.createElement('button', {type: 'submit'}, "Go")
)
);
},
});
ReactDOM.render(React.createElement(Search), document.getElementById("content"));
The result will be a simple form, but with a lot of possibilities to implemented.
This form doesn't process anything, handle submits and request results via an API will be explaining in a further blog entry.
You can download a full and functional copy of this example from http://github.com/enzolutions/drupal-8-reactjs-form
About Drupal Sun
Drupal Sun is an Evolving Web project. It allows you to:
- Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
- Facet based on tags, author, or feed
- Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
- View the entire article text inline, or in the context of the site where it was created
See the blog post at Evolving Web