For the last (and only) website I did using prismic.io, I didn’t want any back-end, all client-side, pure JavaScript man. This way, I could host it nearly anywhere for pretty much free (GitHub pages FTW). To ease stuff, I decided to use the JavaScript kit from the prismic.io team.
One choice they made and that I don’t really like is using callbacks in it. For example, you have to write stuff like:
Can you see it? This ugly thing JavaScript experts name “callback hell”? And that’s a super simple example. In 2014, the way to do that is using Promises. That’s what’s hype (and readable, and nice, and cool, and swag). But I quite understand why they made this choice. Promises are not native everywhere yet, so going with it mean either writing your own implementation or imposing an existing one. Fair enough to have callbacks in the kit then, but we are hackers here, we can override it to use Promises!
I will use the last spec Promise syntax, native way baby!, but it is really important to keep in mind that it has a really poor support right now. You should probably be using a Javascript library as Promise implementation. I will link a snippet of code using the Q library at the end of the article. But I wanted this article to be future proof.
OMG, promises \o/
There are two main callbacks in the kit: when retrieving the API and when making a submit. What I want to write is something like:
Sooooo much more readable and swag… Overriding the Api callback is really simple:
Overriding the submit call is a bit more tricky because it is a prototype function of the SearchForm object, which is totally hidden inside Prismic clojure. This is a bit (super) sad but we can deal with it by creating a fake form and not submitting it. The easiest way I found so far is doing it right after getting the Api. Let’s add the following code at Save point 1 (see previous code).
And after that, you just need to use the new Api function in place of Prismic.Api. You can see the full code here using Q library. This refers to a particular commit to ensure the line highlight is correct but you can freely switch to the master branch to see the most recent code (which shouldn’t be much different… but who knows…).
Thanks for reading. Next time we will talk about responsive images inside StructuredText.
Warning This article is pretty old. Prismic has evolved a lot since then and most issues have been addressed. Check the last version of the docs.
TL;DR
If you don’t know about prismic.io, it’s a nice tool providing both a super clean web interface to write content and an API to retrieve it. No front-end provided, eventually some kits to help you and some examples, but no more. Which is cool because, if you are a web developer, you can focus on crafting an awesome optimized website and then easily put some content in it… well, that’s the theory…
But for me, after using it for a new website, as good as the idea can be, I have found way too much limitations to consider it production ready. The team behind prismic.io is working on most of them so I really hope the implementation will become as awesome as its concept at some point in the future.
The rest of the article will focus on bashing all those limitations, so there will be way more bad than good, but don’t get me wrong, prismic.io has tons of good stuff, and it’s still in beta, I just want to talk about what I don’t like in this article. And since I’m not all about trolling, I will try to consider how to solve them at the end. I will not explain what prismic.io is exactly, so it might be for the best that you quickly check their website before continuing reading. Enjoy.
Do you remember how happy we were at the beginning?
I will never forget… it all started on this windy saturday… I was looking for a solution to create a new blog about traveling. I didn’t want to use an all-in-one tool because I love crafting my UI from scratch, with exactly what I want on it (this point is super important for the rest of the story). I said bybye to Wordpress and all its friends. If I were alone, I would have probably go with raw Markdown or whatever, but I am not… I have other people that travel with me and want to write articles without learning a super complex geek syntax. I will call them… writers. Some colleagues of mine told me about you… that you might be the future of content management, that I would be free for the UI, that you had WISIWIG editors and stuff for… writers, sounds like a perfect match, and so our adventure began.
I still can’t believe how fast it all went… in a couple of hours, we were able to write new articles and display them in a custom website hosted in GitHub pages. Using one of your kits, it was so easy to query your API, retrieve the content as JSON and inject it inside Handlebars templates in order to render the final HTML. Oh man… it was so good.
And then fictions appeared
A few days later, I wanted to go further, moving forward to more crazy stuff. I know that sometimes I try to do complex features just for the fun of the challenge it provides me, but still, how could you do that to me… Remember this conversation?
Hey prismic.io, I would like to query documents that does not match this predicate
Ahahah, you so funny, no way…
Thanks! Wait… what? Why not?
I don’t have a NO operator or whatever close to it.
Whyyyyyy? You have crazy operators like similar to retrieve similar documents based on God know which algorithm and you cannot do a simple negation?
Nope. Deal with it.
Okay… I think I can manage something if the query match this OR that. That’s fine, right?
No.
Cool! Wait… what?
I only have AND operators between predicates.
You gotta be kidding me…
I was a bit sad, but I could manage it, retrieving too much documents and filtering client-side. Still, that was the starting point were all went wrong.
My biggest mistake: using StructuredText
All contents in prismic.io must be typed. This is an image, this is a number, etc… A StructuredText is probably the most powerful type since it allows writers to enter complex content through a WISIWIG editor, using paragraphes, images, lists, embedded stuff, … They can style it using bold, italic, and so on. It looks nice, right? So I decided to use it for the main content of my articles. Fair enough. As always, it was so great to have writers doing their own design using the editor, and so easy to render it automatically as HTML (except for some bugs here and there, but that’s what pull requests are for, isn’t it?). At some point, I just wanted to have a lightbox on some images: clicking on them should expand it to its full sized version with a caption. I don’t know for you, but for me, this is a really basic requirement and you should be able to do it in less than 2 hours.
First problem: I wanted to tag images that should have lightbox with [data-lightbox] HTML attribute, all images didn’t need one. Since I was using the JavaScript kit to render my HTML, I couldn’t do that at all. There is no way to add custom rendering or plugins in the HTML renderer from the kit. Dammit. So I rewrote the full renderer so I could customize it… Wait, how can I indicate which image has a lightbox and which hasn’t inside a StructuredText? Oh, right, I just can’t. Inside a StructuredText, you can only drop raw images and resize them, that’s it. Does that mean I cannot put nor caption or title? Yep, no way to do it. So I started to hack: if after an image, the following paragraph would begin with [caption], the image would be a lightbox, the content of the paragraph would be its legend, and the paragraph itself would be removed from the final rendering.
Guess what? Writers didn’t really like having to manually write [caption], they wanted a nice UI to do that… but that was just impossible… They throw some tomatoes at me and we tried to move on but we couldn’t… Solving one problem to discover a new one: when you define a type image in a Document, you can tell that it will have different sizes: one for desktop, one for tablet and one for smartphone for example. And that’s awesome because you can fully optimize for mobile, which is super important nowadays. Do you think you can do that with image inside StructuredText? Indeed, the answer is no! Once again, a great idea not fully supported. Is there a workaround? Sadly, no easy one. You can upload the same image several times, one for each size, then find a way to retrieve its generated ID by prismic.io and use the same hack as [caption] to specify it and hack a bit more the HTML renderer. I couldn’t find the courage to do it… pretty sure tomatoes would have been replaced by rocks from writers. I can only hope my mobile users have 4G now.
Want more? No biggy, I have tons of stories like that. A writer wanted to have blockquotes: a whole paragraph should be displayed in a custom design and have an author. I had to kill him really fast and bury his body deep. Another one wanted semantic distinction between paragraphs, something like: this one should be red and this one blue just because. Thrown him into a bucket full of piranhas. At some point, a writer became a madman and deleted half of documents… no way to find him since the delete operation does not appear in the timeline. But who cares? I mean, the document are gone anyway. I18N, do you speak it? I hope not because there is no support for it… yet. Want to put some tables? Could you please stop joking, it hurts me to laugh so much. Want do manage hundred of images in the media library? Might be less painful to jump from the top of the Eiffel tower. And so on, and so on…
We didn’t fully link anymore
Writers are generally really proud of their work, so they want everybody to know about it. I couldn’t just display “Title of the article”. If I wanted to stay alive, I needed to display “Title of the article, by an awesome author”, and if you would click on the name, you would access to a page saying how incredible the author was. As always, I was like “No biggy dudes, this is gonna be easy”. I wasn’t bluffing at that point since there is this nice feature that allow you to link documents between them. So every author would now have a dedicated document of type Author, where he could write whatever description he wanted, and each document of type Article would be linked to an Author. So far, so good.
And then the problem: if I get a list of Articles, I only got ids and a link to the Author resources, but I do not actually have the data on the Author document, which means I cannot display the real name of the author. And guess what? There is no aggregation or join possible in the API. You just cannot say that you want the 20 most recent articles with their authors. Solutions are: request all authors and then retrieve the good ones from ids (that’s 2 requests, and I did that since I don’t have that many authors), or do N+1 request (1 for articles, N for authors, one per author id from articles), or generate dynamically a request for authors using any operator (something like [:d = any(my.author.id, [id1, id2, ...])]). In any case, you need multiple requests, eventually not running in parallel, and with too much payload… mobile first, right?
I never though you would mask it from me…
One core concept in prismic.io is Document Mask. Each document must have one and it represents its pattern, how it will be persisted in prismic.io database and how it will be served by the API. So you start creating masks, easy. It directly provides a slick UI for writers to enter content. Nice! And at some point, you realize you could have done better, the mask can be improved. Just don’t do that, keep going with your broken mask, trust me!
Let’s say you don’t trust me (that’s fair enough, you don’t even really know me). If you rename any property of the mask, you are screwed. The new property will be empty since it doesn’t consider it a renaming but the suppression of the previous property and the creation of a new empty one. But you are super courageous, so you migrate all your documents to the new property, yeah! Now you have duplicate a property in your API. Hell yeah! Just check the raw JSON, you will see the new property (thanks God) but also the old one. Properties just keep adding, prismic.io never forget… never! Your payload will just increase. And be sure that your front-end developers always only rely on the mask definition, never on the data from the API, because… it doesn’t mean anything anymore.
My heart was so fragmented…
So, let’s summarize what’s the biggest problem with prismic.io: you can only do what the tool allow you to do. And right now, it allows you only super basic features. Which are needed obviously, but when you go to the real world, you know, outside of the matrix, those are just not enough. Imagine being Mario, you need to save the princess but you can only move forward, no jump, no strange mushroom, no yoshi… Good luck! Direct consequence, the killer feature that would make prismic.io really powerful, in my humble opinion, is what I will call “custom fragments”. The idea is to allow developers to create their own type of fragments and plug them both in the UI of the writing room and in the HTML renderer. That might sounds a bit challenging but it isn’t that hard in fact.
So first, how to create a custom fragment? Let’s use the mask system. When defining a document, you are creating a mask saying “this document will have an image and some text as title”. Why not doing the same for custom fragments? Remember the lightbox problem? I would create a custom fragment lightbox which is composed of an image and some text as its caption. Even better, since I am now using a real image type, I can specify several sizes for the image. Big win here.
Next, inside the writing room, how to render a custom fragments? Well, you already know how to render all its pieces, just group them together with an indentation or a left border or whatever. The lightbox fragment would be an image selector and a text input. Of course, you should be able to put a custom fragment both inside a document (like any other fragment) and inside a StructuredText if possible (just like you are allowing em or h2 inside a StructuredText)
Finally, each kit should have a renderFragment(type, json => html) method that allow you, for a specific fragment type (here lightbox), to pass a function that know how to render the final HTML from its raw JSON.
Hey, we can do even better, let’s add a second argument to the rendering function, this one will be the original rendering function for “native” fragments in prismic.io. This way, you can override just one or two “native” fragments. For example, if you want to render image with a <picture> HTML tag because that’s super hype. Just do something like:
And that’s it! You just solved so many limitations…
I didn’t understand your semantic anymore…
Ok, next step. Inside a StructuredText, I need to have semantic distinction between fields of the same type. This paragraph is important, this one is a blockquote and all the rest are normal. Let’s go the easy way: I just need a hash of key -> value, as strings, to reach a limitless world. This way, I could tag one paragraphe important: true, and another with with both blockquote: true and author: Someone. At last but not least, expose it in the API:
I have no idea how to integrate that in the UI of the writing room, but I know its designer, he will figure out something awesome, no doubt.
By adding that, you leverage tons of possibilities for developers to customize the rendering of a StructuredText without any heavy hack. Writers would still need to manually write each key name, but its way better than paragraphs starting with [caption] or [author]. Following a snippet on how to render a blockquote, using the previous renderFragment method of course:
This feature is for “quick and dirty” hacks if you could say, and allowing you to customize “native” fragments. Because otherwise, you could also have done that with a custom fragment. Rather than having two attributes, a blockquote could be a custom fragment grouping a StructuredText for the content and a simple text for the author. It is way more intuitive in the UI and it’s easier to create its own renderFragment.
I like a lot this renderFragment method, but I think we can make it even better! Right know, we can only specify / override for all the application. That’s super cool but limited… and if you have read carefully until now, you should know that I don’t like limitations. This method should be at least at 3 different levels:
Document instance
Document type
(Collection?)
Application
Here is the idea: when an instance of a Document wants to render some fields (or fragments) as HTML, it will do the following simple procedure:
Hey, do I have a custom renderer method for this type of field on myself? (yeah, because now each Document instance have the method). If so, use it, if not, continue.
I am a Document of type Article, does this type of Document has such a method on it? (yeah, because now you can call this method for just a particular type of Document). Yes, use, no continue.
Eventually, does my Collection have the method?
Nearly finished, does the method is defined at the application level?
If nothing found so far, if it is a native prismic.io field, render it as it should be, otherwise just crash or return empty string, I don’t know, it shouldn’t happen anyway.
Holy crap… we just created a “rendering context with awesomeness inheritance” or something like that. Can you imagine all the things you could do with that? Can you ?! I can’t… it’s too big…
Let’s break up
I could say more, but since it’s a miracle that you are still reading and it would not be as relevant as what I already said, I will stop here.
My conclusion so far: prismic.io is not ready for the real world and for real websites but there is a lot of work going on by its team so, as they say on half of their responses: stay tuned! It might become super awesome at some point (I hope it will).
Thanks for reading! See you soon for more hacky coding posts.
AngularJS provides a nice $location service which allows you to deal with routing and url inside your application. It supports both a fallback mode using hashbang and a real HTML5 routing using the new History API. Since we love bleeding edge technologies, that’s obvious we want to use the History API if possible. Lucky us, it appears it’s quite easy to do so with a Play Framework application. Let’s see how to do that.
Let’s keep things simple. Creating a new Play Framework application with play new. We will use a Scala application in this article, but it should as easy with a Java one. Then add AngularJS using CDN (see main.scala.html#L19). Then we will create an Angular module for our app and enable the HTML5 routing mode which is disable by default.
Nice. Now we will make some modification to the default views generated by Play. We want a single-page application, which means our root url must map to a main page which will contains all resource dependencies and includes the ng-view of AngularJS. I’ve done that by editing the main.scala.html file as you can see here and add a new Play route:
And a new Action in my Application controller:
Wait. Why is there a String param for the main method? And why do we pass a default any = "none" value? It seems a bit useless… Fair enough, I will explain it later on the article, don’t mind it for now. So, we have our main page. Let’s add some content for the landing page. As we have specified in the AngularJS routing, our root url, which is defined with $routeProvider.when("/", ...) is pointing to /views/index. So we need a Play route for that… but before, let’s talk about all those routes.
Routes, routes, routes…
As we advance in our coding, we can see that the term “route” is used in different contexts. It’s important to fully understand them all. Play routes, which are defined in the conf/routes file, are the core of your application. It’s those routes which will answer to the HTTP requests, serving either HTML, JSON, or whatever. But you, as the developer, will be the only one to know about them. Users of your application will only use and see AngularJS routes, which are defined in your main module using the $routeProvider.
The idea is that when a user land on your site, it should use AngularJS routing which will then use Play routes to load the template (= the content) of the page. So why not using the exact same url for both the AngularJS route and the templateUrl route? Well, in the case of the root, it’s obvious: the Play “/” route is already required for our main page. Ok. But in a more general case, could we do:
Nope, you can’t. Well, that’s a small lie… you could do that, and it would work if your user always open your main page first. If he does that, then all AngularJS routing is loaded, and when the user will go to “/page” url, it will be catch by AngularJS which will ask for the “/page” on Play routes which will give him the content of the page. So what’s the problem? If you user directly land on the “/page” url, because he arrived for the first time on your application after having clicked on a link somewhere which was pointing at “/page”, then the Play route will be directly called since there is no AngularJS routing initialized at all… And that’s bad, right? The user would have the raw content of the page without any JavaScript or CSS from the main page. It’s a fail.
In order to prevent that, I have chosen to use some conventions. There is nothing official, you can use your own, the only thing to keep in mind is that AngularJS routes and Play routes should never be equals. My solution to do that is to prefix all Play routes serving HTML with a “/views/” prefix, all Play routes serving JSON with a “/api/” prefix and, as it is by default, all Play routes serving resources with a “/assets/” prefix. Meaning I can now use all routes I want inside AngularJS routing but never starts them with one of those prefix.
Of course, it will just modify the problem without solving it. Now, if a user land directly on “/page”, he will have a huge orange Play error telling him that the route doesn’t exist. As before, AngularJS routing isn’t loaded, so it’s Play routing which try to handle that and, since there is no longer any “/page” route in Play, it crash.
So what’s the point of having different routes? The next trick is to redirect all unknow routes to our main page. By doing so, if the user land on “/page”, Play will say “I don’t know that route, go to the main page”, so the user will indeed go to your main page, but then, all AngularJS routing will be loaded and super awesome AngularJS will say “Hey, I do know that route, and I need the /views/page template”, and then Play will respond “Oh yeah, I can serve you /views/page, here is the HTML to display”, and your user will see the correct “/page1” content, even if he lands directly on it.
Another question? Why didn’t we use this trick before and then have the same routes for both AngularJS and Play? Because it’s important that the trick apply only to unknow routes. We cannot redirect to the main page an existing Play route because it needs to serve its own content. So by using different routes, we can intercept AngularJS routes inside Play as “unknown routes” and redirect them to the main page so AngularJS can handle them. I hope I’m clear enough here, that might be the hardest part of the article. In order to achieve that, we just need to put a Play route at the end of the route file which intercept all routes and redirect them to the main page:
And now you should understand why we had a any: String for our main page at the beginning.
First pages
Enough with all the theory, let’s do two concrete pages: creating “page1.scala.html” and “page2.scala.html” files with basic content (see source code, I’m using a template to stay DRY about the title and the menu but that’s not important), add then as Play routes (with a “/views/” as stated before) and also add them inside our controller:
And then add the AngularJS routing:
That’s it. We can now create a link, using a a tag, to point to the url “/page1” and AngularJS will do the rest, loading the “/views/page1” template using Play route which will return the HTML code generated from our Scala template. Nice isn’t it? The url is correct: http://localhost:9000/page1, you can use the back button to return to the index page, no ugly hashbang, but all in Ajax with a single-page application.
Handling url parameters
So, we have our url working by using the History API thanks to the HTML5 mode of the AngularJS $routeProvider. But that’s only for raw url. What if we want to have dynamic parameters inside them? Just like REST, having url as “/colors/1” and “/colors/2” if we deal with colors (yeah, why not?). Do you think that’s easy? Well, you could, after all, both AngularJS and Play know how to handle parameters in their url. We could do something like:
Nope, we can’t. Why? Because the “templateUrl” cannot handle url parameters. It’s just a template. And of course, using templateUrl: "/views/color" will not pass any “id” parameter to the Play route. Damn…
That’s not a problem in fact. Just keep to the AngularJS way of doing things: it’s not Play who should handle the data any longuer, it’s AngularJS who rules the world now, so you don’t need any params in your Scala code, just trust AngularJS. Ok, but we need a way to load the correct color depending on the id in the url right? Sure thing. It’s the role of AngularJS controller to that. That’s why there is a “ColorCtrl” along with our template, and guess what, the AngularJS controller know about the url params. Here is the code of the controller:
And just for fun, I’ve defined the fake database in the “AppCtrl”:
So as we can see, using the $routeParams service, we can retrieve the url params and then load the correct color in the $scope. At the end, it’s just a matter of displaying that color in our view using AngularJS data-binding:
And that’s it! you can now display some data depending of params inside your url (and show an error message in case the data doesn’t exist). Cool isn’t it?
Want more?
Oh God, you are still reading? You should already be able to do anything you need. But if you want, we can dive in a more complex example, using AngularJS $resource service and serve JSON from Play like a REST API would do. Sounds good for you? Ok, let’s do that. First, we will create a “Users” controller and it will have two methods: “all()” and “find(id: String)” which will return an Array of Json and a Json object representing our list of users and one particular user based on its id. I will not use a real database, but something like MongoDB would fit really good in there. Here is the code:
If you don’t fully understand it, you can check the PlayFramework documentation about handling Json (ScalaJsonRequests). I am using the new Json API from Play 2.1 (play.api.libs.json.package). Next we need our “UserCtrl” which will use the `$resource</code> service to retrieve the data:
To learn more about AngularJS $resource definition, see: ngResource.$resource. What is that “apiUrl” by the way? It’s a constant I’ve defined in my AngularJS app:
Pro tip Why is there the 9000 port twice? That’s because if we had written http://localhost:9000/api, AngularJS syntax would have analyzed that as a url with a dynamic parameter named “9000” because it’s placed right after a : character. So we need that strange syntax to tell AngularJS that this is not a parameter but a real value in our url.
Next, we are creating our resource by extending this apiUrl with our routing “/users/:id”. This time, “:id” is a real parameter. We can now use “get” and “query” methods on the resource, passing or not a value to the id, in order to retrieve our Json code and assign it to the $scope. We will need two Scala views: one for the list and one for the detail of course.
And that’s it. We now have a list of users and links to each user detail, and all that data is fetch from a REST API using Json.
Pro tip By the way, since our Play routes doesn’t clash with AngularJS routes, you can load them directly in your browser. It will works because the Play route handling the redirection to the main page is at the end of the route file, so any real Play route will be loaded before the redirection. If you have the demo running, check http://localhost:9000/api/users and http://localhost:9000/api/users/1 to see your REST API working nicely.
Conclusion
I hope this article will help you bootstrap your next awesome application using awesome tools like AngularJS and PlayFramework. Your next step (if that’s not already the case) would be to learn more about the new PlayFramework Json API so you can have typesafe Json (if I can say so). You would also probably need to plug a database on it. One choice could be a MongDB database since it can store raw Json, and interact with it using a nice driver like ReactiveMongo if you want to go all the way down to asynchronous application.
I’ve been a bit busy lately but I’m back on game. Looking for a job in Paris, I’ve been asked to do some code over more or less funny subjects and now that it’s done, I will share them, maybe it could help people to see some code around some technologies. It’s not at all perfect code, more experiments I’ve done.
Mowing is mainly a CoffeeScript project about giving orders to some automatic mowers and see the result. My goal was to test that new syntax around JavaScript and I have to admit it’s quite cool. You can see the result here (don’t ever do it in large grids). The source code is here on GitHub
Mowing-java is the Java version of Mowing. So in fact, it’s nearly the same syntax since you can create class in CoffeeScript but this one runs on a JVM. See here for source code.
Finally, GSearch is an AngularJS application built using Yeoman. Its goal is to plug on GitHub API and allow you to search through repositories and users and display informations and stats about them. Here is the result and go there for source code.
Of course, any feedback is welcome! I can be bugs, features, questions, anything…
NigthHacking Tour 2012
I’ve given a small quicky about RichFaces Bootstrap and RichFaces 5 on Paris a few weeks ago. Just so you know…
Are you in Paris?
Let’s finish with a personal note. I will be living in Paris from now and for quite some time. So if you living there or just passing by and want to grab a beer and talk about Java EE, HTML5, RichFaces, or anything cool, just let me now! Also if you are giving conferences or doing dojos or katas in the area, be sure to notice me so I can come to the next one. Thanks.
Red Alert! The RichFaces Bootstrap project is still under heavy development, tag and attribute names can change at any time and if you find something missing or buggy, there is high chance it’s not a bug but just hasn’t been done yet (… or it’s a real bug). So only use it for fun and prototype purposes.
Semantic components are a brand new concept. I need to present it first so I can use it when talking next about the new components. Most of the time, for one JSF tag, you have one and only one HTML renderer, it’s a oneToOne relation (according to JSF naming convention). It seems logical: for one component, you should always have (nearly) the same generated HTML code. But with HTML5, the web is becoming more semantic and that’s good. Why not have the same with RichFaces? But before we dive into it, what is “semantic”? For a real definition see Wikipedia but here, we will say it’s when a component serves a global purpose like being a header or a footer but shouldn’t always render in the same way, instead the rendered result should depend on the context (like a table header isn’t the same as a column header).
With RichFaces, a semantic component is a component with no renderer! Yeah yeah, if you use a semantic component on its own, it will throw an exception because it doesn’t know how to render itself. The concept is that a semantic component will ask its parent in the JSF tree: “Hey dad, do you know how I can render myself?”, if it knows, the parent will provide the correct renderer to the semantic component which will render it, otherwise, the semantic component will ask one level higher the same question, and so on until the root element. If no one answers yes to the question, it will throw an exception. That means we also have components that accept semantic components in order to provide them the correct renderer.
Let’s take a concrete example. The modal component in RichFaces Bootstrap can support 3 semantic components: a header, a body and a footer. You can see that by looking at which interfaces the AbstractModal implements (see GitHub). All interfaces with the syntax Render{1}Capable are components that support the semantic component {1}, so here, it’s headerFacet, bodyFacet and footerFacet. And if you look at the rest of the code of the AbstractModal, you will see methods with the syntax public String get{1}RendererType() which are the methods giving the right renderer to use by semantic components. Inside a modal, the headerFacet component will render as a div class="modal-header" according to the renderer provided by the modal. But inside another component, it could have been totally different HTML code.
Pro tip If you take a more accurate look to all current semantic components, you will see that they all follow the same syntax: first their purpose (like header or footer) and then a generic Facet suffix. That give us the full list of semantic components: headerFacet, bodyFacet, footerFacet, menuFacet and positionFacet. Why using a suffix? Because we want to keep the no-suffix name for the real HTML tag. The RichFaces header tag will always generate the HTML header tag like a classic JSF tag (the oneToOne relation) but the headerFacet tag is a semantic component so it can generate anything depending of the context. Also, it makes it easier to see if a RichFaces component is a semantic one or not by just looking at its name.
Warning Even if the suffix is Facet keep in mind that semantic components are not facets, they don’t have the same limitations: they have attributes, you can use the same semantic component several time inside the same parent, a semantic component doesn’t have to be a direct child of a component supporting it and a semantic component can have several children.
Now, let’s dive into the new components. input tag is a basic input with all Bootstrap features like prepend and append and several new attributes in order to support new HTML features. By the way, this input centralizes and supports all HTML5 input types, you will no longer need one JSF component for each type, just use the type attribute (default is “text” of course).
modal is like rich:modalPanel or rich:popupPanel, it will display a popup layout on top of your page, potentially covering your page with a dark layer to block any action outside of the modal. The default usage of the modal has a header, specified by using header attribute or header facet, a footer specified with footer facet and a body which will be the code inside the modal component. Concretely, what’s happening is that each part, header - body - footer, will be wrapped inside a div class="modal-xxx" where “xxx” is the name of the section in order to align with the Bootstrap syntax. Using footer as a facet might be limiting because you cannot have a form inside the modal wrapping both body and footer because footer, as a facet, will always be outside. The default usage should be the modal inside the form since you will probably not need several forms inside a modal most of the time.
What if that isn’t enough? What if you do want the form inside and not outside? Even if this behavior should be enough in most of use-cases, you can still fully customize your modal the way you want! The moment you use one of the following semantic components, headerFacet - bodyFacet - footerFacet, it considers you are doing a custom modal and it will not generate the div class="modal-xxx" anymore. I’m talking about the modal itself. Because the semantic components will generate the corresponding div. However using real components and not facets will allow you to put both bodyFacet and footerFacet inside a form for example.
tooltip and popover are two new ways to display bonus info when the mouse moves over particular content. The first one is for small texts and labels only, the second one can support custom content and a title. Right now, content can only be text but we are planning to improve this.
Pro tip Even if popover content only supports text, you can still put some light HTML in it. You just need to escape chevrons with < and >.
Finally, “orderingList”:http://bootstrap-richfaces.rhcloud.com/component/orderingList/ is the new RichFaces ordering list to allow you to re-arrange the order of some items. It already supports single drag-and-drop, multiple selection and “table” layout. Next features will be multiple drag-and-drop, maybe keyboard selection using SHIFT (CTRL is already supported). Thanks to Brian work, it is the first component mixing the power of the jQuery UI widget factory with Bootstrap design. If we can do it once, we can do it for lots of other widgets!
New EL functions are also there. jQuery and jQuerySelector are part of RichFaces Core but have been created to help RichFaces Bootstrap. They will allow you to retrieve a jQuery object or the jQuery selector from a server-side JSF id.
Next are more specific Bootstrap EL functions. If you have take a look at Bootstrap JavaScript API, you might have noticed that lots of JavaScript components have a set of functions with the following syntax: $(sel).compName('singleParameter');, like for example: $('#myModal').modal('show'); for a modal. The first approach to use it in JSF component was to use the previous jQuery function like: onclick="\#{rich:jQuery( 'myModal' )}.modal('show')". It works fine but obviously, that wasn’t enough for Lukas since he built a different approach from scratch.
The new concept is that the compName part of the call is nearly useless if you can retrieve it from the component returned from the jQuery call. In the previous example, if you know that \#{rich:jQuery('myModal')} is actually a modal component, then you also know that you will have to call the modal function, only remains with importance the singleParameter. So here is the new syntax: \#{b:singleParameter(sel)}. The previous example becomes: onclick="\#{b:show('myModal')}". Much more concise and readable, isn’t it? Right now, RichFaces Bootstrap supports show, hide and toggle functions but others will follow soon.
Pro tip Want to know how the EL function retrieves the name of the component? Easy. When the selector will be used to find the JSF component, it will find a UIComponent (like a UIModal) which, according to RichFaces CDK design, will extend an AbstractComponent (like AbstractModal). And if the AbstractComponent supports Bootstrap EL functions, it will be annotated with @BootstrapJSPlugin (like at line 43 of AbstractModal) and it’s the name attribute of that annotation that will give us the componentName. As I told you, really easy!
LESS support is no longer a dream (for those who doesn’t know LESS, it’s a more powerful way to write CSS, see the project website for more infos). Thanks to Lukas’ awesome work, a first prototype of that feature is already working. You can read his post to know more about that. There is still work to do but it’s an incredible starting point.
What’s coming?
Want more? Great, because we have tons of other plans to improve RichFaces!
New build design is currently under discussion on RichFaces wiki so be sure to take a look and give feedback if you care about the future of RichFaces.
Theming all current components from RichFaces Core with Bootstrap design is planned so you can use both projects at the same time.
The orderingList is just a beginning. More jQuery UI widget factory based components are incoming. Feel free to comment here to propose the ones you would like to see supported in RichFaces Bootstrap.