Implement Trix Rich Text Editor in Lesson Form

Notes


In this lesson we're going to begin tackling something a bit more advanced. The content attribute of our Lesson object is currently just plain text. What we would like to do is incorporate a way to add more complex things to our content attribute's text like headers and paragraphs and formatting. To accomplish this we will use what's called a rich-text editor. There are quite a few to choose from but for this video we will be using Trix.

Trix rich-text editor is relatively new but incorporating it into our Rails app will allow us to create all the cool things you've seen in the notes like code blocks and italicized text. To check out what it actually does you can visit the Trix website.

To get started we need to head over to Trix's github repository and clone it. This is something we haven't done yet but the github repository containing this editor is the exact same thing that we have been pushing our code to this entire time. A github repository is just a place on the internet where code lives that is accessible through github's Command Line Interface.

When you land on Trix's github repository page, there is a button in the top right-ish that says Clone or download. We want to click this and copy the URL it gives us to the clipboard. After we have the URL we want to open up our terminal and navigate to a working directory that isn't inside of our application. The reason we do this is because Github will clone the files to whatever directory we type the command in and we don't want the Trix codebase in our application.

Once you are in a working directory that you want the Trix repository to be copied to type:

git clone git@github.com:basecamp/trix.git

After we clone the Trix repository we need to steal a few files from the dist folder in it's directory.  In this directory you will find trix-core.js, trix.js and trix.css. The file extensions really tell the tale here. We want to copy the two JavaScript files into our application's app/assets/javascripts folder and copy the CSS file into our application's app/assets/stylesheets directory.

What we're doing is feeding these files into what's called the Rails asset pipeline. Whenever we run rails c to open console or rails s to start a web server, Rails precompiles all of our JavaScript and CSS files to be used with our application. Any files that don't fall into the Rails MVC convention need listed as arguments to a particular method so Rails knows to precompile them anyways.

To do this we need to open our application's root/config/initializers/assets.rb file and add the file names to

Rails.application.config.assets.precompile += %w( home.css admin.css trix.css trix.js )

We didn't add the trix-core.js file at this time because we might not need it. Let's try to get it working without and we'll come back to that later if need be.

The next thing we need to do is move over to our admin layout and make sure that any views rendered with that particular layout link to the assets we precompiled. We can accomplish this with Rails helper methods.

<%= stylesheet_link_tag 'trix', media: 'all' %>
<%= javascript_include_tag 'trix' %>

If you were to try to visit the path to create a new Lesson object at this point you would probably get an error. That's because we already had the server started when we added the Trix files and they haven't had a chance to precompile yet. Let's just restart our Rails server and it will resolve that error.

This might be a good time to point out that, as a new developer, it's important to just slow down and really read error messages. In Ruby we're blessed with some really descriptive error messages and they will usually point you in the right direction to resolve the error.

Now, loading up the any page in the admin section we can check the developer tools to make sure that the appropriate CSS and js files are being accessed by our application. Click on the network tab and filter responses down to js files and you should see your Trix js files listed.

The next step we need to take to integrate the Trix editor is setting up the HTML structure. Going off of the Trix documentation it looks like we need to structure some HTML like so:

<input id="x" value="Editor content goes here" type="hidden" name="content">
<trix-editor input="x"></trix-editor>

Trix has given us a custom HTML element to use to render the rich-text editor and we tell that custom element the id attribute of the input tag it is tied to. In your Lesson object's new view, create another div tag with a class of form-group and copy the Trix HMTL structure into it. Now when we load the new Lesson object form we will see the old content input attribute with Trix version underneath. You'll notice that the value attribute of the trix-editor element is already typed into the form. Type some text in of your own and start testing some of the features Trix offers us.

Now we have the Trix editor present in our application, let's tie the input it uses to into the rails Lesson object form. We do this by building the HTML in a way that it still works with editor, but also fits into the convention of Rails forms. If you remember our link_to helper methods are just an easy way to generate HTML that fits into this convention. Instead of using a helper method, let's just craft the HTML ourselves.

<input id="lesson-content" name="lesson[content]" type="hidden" value="<%= @lesson.content %>">
<trix-editor input="lesson-content"></trix-editor>

When forms for Model objects are sent to a conventional rails controller they are sent in the structure of:

{ 
   lesson: {
      title: 'I typed a lesson title in the form',
      content: 'I typed lesson content into the form',
   }
}

The name attribute in the input tag declares this with the lesson[content] value for the name attribute. It's saying place the value of this form inside the lesson param with a key of content when posting this data to the controller. If the content was outside of the lesson param it wouldn't pass through the strong_params Rails defined for us in the controller. 

def lesson_params
   params.require(:lesson).permit(:title, :content, :video_html, :unit_id)
end

Params requires there be a lesson param and it will permit the title, content, video_html and unit_id keys to be passed inside of the lesson param. There are a lot of moving parts but it all ties into the MVC convention that rails was built upon. 

Now we have have the ability to create rich text when typing in our lesson content.

Happy coding!!!!